bk://kernel.bkbits.net/gregkh/linux/usb-2.6
stern@rowland.harvard.edu|ChangeSet|20040905035315|47865 stern

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/09/06 17:32:27-07:00 akpm@bix.(none) 
#   Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6
#   into bix.(none):/usr/src/bk-usb
# 
# drivers/usb/media/dabusb.c
#   2004/09/06 17:32:23-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/class/usb-midi.c
#   2004/09/06 17:32:23-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/class/audio.c
#   2004/09/06 17:32:23-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/05 05:53:15+02:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Centralize logical disconnects in the hub driver
#   
#   This patch takes some code that was only used in one place in the hub
#   driver, and packages it up into a subroutine which is now called from
#   several places.  The routine does a logical disconnect -- for example,
#   after issuing a port reset, if the device descriptors have changed
#   (because of a firmware update perhaps) we logically disconnect the old
#   device structure and create a new one.  Or if a resume fails for any
#   reason we can do the same thing.
#   
#   This touches some of David Brownell's suspend/resume code, obviously.
#   (It also fixes a couple of small errors in there.)  He has said it looks
#   okay.
#   
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/hub.c
#   2004/08/18 17:44:48+02:00 stern@rowland.harvard.edu +36 -23
#   USB: Centralize logical disconnects in the hub driver
# 
# ChangeSet
#   2004/09/05 05:23:24+02:00 janitor@sternwelten.at 
#   [PATCH] list_for_each_entry: drivers-usb-class-audio.c
#   
#   Make code more readable with list_for_each_entry.
#   Compile tested.
#   
#   
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/class/audio.c
#   2004/09/01 19:34:25+02:00 janitor@sternwelten.at +6 -15
#   list_for_each_entry: drivers-usb-class-audio.c
# 
# ChangeSet
#   2004/09/05 05:22:50+02:00 janitor@sternwelten.at 
#   [PATCH] list_for_each_entry: drivers-usb-class-usb-midi.c
#   
#   Make code more readable with list_for_each_entry.
#   Compile tested.
#   
#   
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/class/usb-midi.c
#   2004/09/01 19:34:26+02:00 janitor@sternwelten.at +3 -8
#   list_for_each_entry: drivers-usb-class-usb-midi.c
# 
# ChangeSet
#   2004/09/05 05:22:18+02:00 janitor@sternwelten.at 
#   [PATCH] list_for_each_entry: drivers-usb-media-dabusb.c
#   
#   Use list_for_each_entry to make code more readable.
#   Compile tested.
#   
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/dabusb.c
#   2004/09/01 19:34:30+02:00 janitor@sternwelten.at +1 -4
#   list_for_each_entry: drivers-usb-media-dabusb.c
# 
# ChangeSet
#   2004/09/05 05:21:45+02:00 janitor@sternwelten.at 
#   [PATCH] list_for_each_entry: drivers-usb-host-hc_sl811.c
#   
#   Make code more readable with list_for_each_entry_safe.
#   (Is this a non i386? I can't compile it.)
#   
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/host/hc_sl811.c
#   2004/09/01 19:34:32+02:00 janitor@sternwelten.at +2 -6
#   list_for_each_entry: drivers-usb-host-hc_sl811.c
# 
# ChangeSet
#   2004/09/05 05:21:11+02:00 janitor@sternwelten.at 
#   [PATCH] list_for_each_entry: drivers-usb-serial-ipaq.c
#   
#   Use list_for_each_entry_safe to make code more readable.
#   Compile tested.
#   
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/ipaq.c
#   2004/09/01 19:34:33+02:00 janitor@sternwelten.at +5 -14
#   list_for_each_entry: drivers-usb-serial-ipaq.c
# 
# ChangeSet
#   2004/09/05 05:04:18+02:00 janitor@sternwelten.at 
#   [PATCH] list_for_each_entry: drivers-usb-core-devices.c
#   
#   Make code more readable with list_for_each_entry.
#   Compile tested.
#   
#   Patch incremental on the list_for_each() change.
#   
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/devices.c
#   2004/09/01 19:34:25+02:00 janitor@sternwelten.at +2 -6
#   list_for_each_entry: drivers-usb-core-devices.c
# 
# ChangeSet
#   2004/09/05 04:53:18+02:00 greg@kroah.com 
#   USB: remove usbdevfs filesystem name, usbfs is the proper one to use.
#   
#   This has been publicised for years now, and the usvfs name will work just
#   fine with a 2.4 kernel, so we are not breaking backwards compatibility.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# include/linux/usbdevice_fs.h
#   2004/09/05 04:52:09+02:00 greg@kroah.com +0 -10
#   USB: remove usbdevfs filesystem name, usbfs is the proper one to use.
#   
#   This has been publicised for years now, and the usvfs name will work just
#   fine with a 2.4 kernel, so we are not breaking backwards compatibility.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# include/linux/usb.h
#   2004/09/05 04:52:09+02:00 greg@kroah.com +0 -2
#   USB: remove usbdevfs filesystem name, usbfs is the proper one to use.
#   
#   This has been publicised for years now, and the usvfs name will work just
#   fine with a 2.4 kernel, so we are not breaking backwards compatibility.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/usb.h
#   2004/09/05 04:52:09+02:00 greg@kroah.com +6 -0
#   USB: remove usbdevfs filesystem name, usbfs is the proper one to use.
#   
#   This has been publicised for years now, and the usvfs name will work just
#   fine with a 2.4 kernel, so we are not breaking backwards compatibility.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/inode.c
#   2004/09/05 04:52:09+02:00 greg@kroah.com +13 -108
#   USB: remove usbdevfs filesystem name, usbfs is the proper one to use.
#   
#   This has been publicised for years now, and the usvfs name will work just
#   fine with a 2.4 kernel, so we are not breaking backwards compatibility.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/devio.c
#   2004/09/05 04:52:09+02:00 greg@kroah.com +5 -5
#   USB: remove usbdevfs filesystem name, usbfs is the proper one to use.
#   
#   This has been publicised for years now, and the usvfs name will work just
#   fine with a 2.4 kernel, so we are not breaking backwards compatibility.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/devices.c
#   2004/09/05 04:52:09+02:00 greg@kroah.com +2 -2
#   USB: remove usbdevfs filesystem name, usbfs is the proper one to use.
#   
#   This has been publicised for years now, and the usvfs name will work just
#   fine with a 2.4 kernel, so we are not breaking backwards compatibility.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/09/03 14:25:14-07:00 akpm@bix.(none) 
#   Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6
#   into bix.(none):/usr/src/bk-usb
# 
# drivers/usb/misc/tiglusb.c
#   2004/09/03 14:25:09-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/media/dabusb.c
#   2004/09/03 14:25:09-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/03 14:24:12-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# MAINTAINERS
#   2004/09/03 14:24:08-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/03 14:29:45+02:00 alborchers@steinerpoint.com 
#   [PATCH] USB: close waits for drain in pl2303
#   
#   Here is an additional patch for pl2303 in 2.6.9-rc1,
#   to be applied after my previous circular buffer patch.
#   This patch waits for the buffer to drain on close and
#   then clears the buffer.  In addition to the obvious
#   features, this also fixes a bug where closing a port
#   with a full buffer would accidentally disable writes
#   when the port was re-opened.
#   
#   The original pl2303 could lose data that was still going
#   out the port on close, and even this patch only solves
#   the problem completely for data rates of 1200 bps and
#   above.
#   
#   Waiting for data to drain from the circular buffer is
#   easy, but the problem is waiting for data to drain from
#   the 256 byte hardware buffer on the device.  I don't know
#   how much data is in the hardware buffer, so I just wait
#   long enough for a potentially full hardware buffer to
#   drain, but I don't want to wait that long for low data
#   rates if the buffer isn't full.  There is probably some
#   way to query the pl2303 to find out how much data is in
#   its hardware buffer, maybe snooping would reveal that.
#   
#   - Added a wait for data to drain from the driver
#     write buffer when closing.
#   
#   - Added a wait for the data to drain from the
#     device hardware buffer when closing.
#   
#   - Cleared the driver write buffer when closing.
#   
#   Signed-off-by: Al Borchers <alborchers@steinerpoint.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/pl2303.c
#   2004/08/30 02:27:08+02:00 alborchers@steinerpoint.com +58 -4
#   USB: close waits for drain in pl2303
# 
# ChangeSet
#   2004/09/03 14:29:06+02:00 alborchers@steinerpoint.com 
#   [PATCH] USB: circular buffer for pl2303
#   
#   Here is the patch adding a circular buffer to pl2303
#   updated to 2.6.9-rc1.  Phil and I both tested this.
#   (Phil tested a slightly different earlier version.)
#   
#   This fixes the carriage return newline problem Olaf
#   Hering reported and helps Phil with hotsyncing his
#   phone.  This patch also fixes a problem that would
#   sometimes leave a pl2303 port unable to send data,
#   reporting "already writing", after closing the port
#   while writing was in progress.  This happened about
#   1/3 of the time in my tests with the stock 2.6.9-rc1
#   pl2303 driver.
#   
#   
#   - Added a circular write buffer, protected by the
#     existing spin lock.
#   
#   - Write_room and chars_in_buffer now report room and
#     chars in the circular buffer.
#   
#   - Added a "bounce buffer" when transfering data from
#     user space to the circular buffer--needed for locking.
#   
#   - Replaced (urb->status != -EINPROGRESS) with a private
#     write_urb_in_use flag protected by the existing spin
#     lock.  Clear this flag when the urb is unlinked.
#   
#   - Free memory on failed startup.
#   
#   - These changes make ONLCR mapping work and fix a bug
#     that would sometimes leave the port unable to write,
#     reporting "already writing", after closing the port
#     while writing was in progress.
#   
#   Signed-off-by: Al Borchers <alborchers@steinerpoint.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/pl2303.c
#   2004/08/28 22:44:17+02:00 alborchers@steinerpoint.com +324 -25
#   USB: circular buffer for pl2303
# 
# ChangeSet
#   2004/09/03 13:33:55+02:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Nag message for usb_kill_urb
#   
#   This patch is only for nuisance value.  It puts a nag message in the
#   system log every time usb_unlink_urb() is called for synchronous
#   unlinking.  My hope is this will speed the process of converting drivers
#   to use usb_kill_urb().
#   
#   Don't apply this if it generates too much noise, but otherwise go ahead.
#   A little prodding never hurt anyone.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/urb.c
#   2004/08/30 13:39:08+02:00 stern@rowland.harvard.edu +3 -0
#   USB: Nag message for usb_kill_urb
# 
# ChangeSet
#   2004/09/03 13:33:20+02:00 janitor@sternwelten.at 
#   [PATCH] usb/dabusb: insert set_current_state() before schedule_timeout()
#   
#   After discussing this patch with Mark Hollomon, I think it is much safer
#   / better to leave the conditional check within the while loop. This way
#   the mutex state is as expected and maintainability is not compromised.
#   The previous patch should not be applied.
#   
#   
#   Description: Inserts appropriate set_current_state() call so that
#   schedule_timeout() functions as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/dabusb.c
#   2004/09/01 19:35:55+02:00 janitor@sternwelten.at +1 -0
#   usb/dabusb: insert set_current_state() before schedule_timeout()
# 
# ChangeSet
#   2004/09/03 13:32:49+02:00 janitor@sternwelten.at 
#   [PATCH] usb/tiglusb: insert set_current_state() before schedule_timeout()
#   
#   Insert set_current_state() so schedule_timeout() functions as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/misc/tiglusb.c
#   2004/09/01 19:35:55+02:00 janitor@sternwelten.at +1 -0
#   usb/tiglusb: insert set_current_state() before schedule_timeout()
# 
# ChangeSet
#   2004/09/03 13:32:12+02:00 bjorn.helgaas@hp.com 
#   [PATCH] HCD PCI probe: print actual, not ioremapped, address
#   
#   I think the USB HCD should print the actual PCI memory address, not the
#   ioremapped address.  AFAIK, there's no reason the ioremapped address has
#   to have any fixed relationship to the actual address.  Also, this makes
#   it match what's in /proc/iomem.  I also added a leading "0x".  Example
#   from ia64:
#   
#       - ehci_hcd 0000:00:01.2: irq 52, pci mem c000000080021000
#       + ehci_hcd 0000:00:01.2: irq 52, pci mem 0x80021000
#   
#   
#   
#   USB HCD: print actual PCI mem address, not the ioremapped value.
#   
#   Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/hcd-pci.c
#   2004/09/01 18:42:03+02:00 bjorn.helgaas@hp.com +2 -2
#   HCD PCI probe: print actual, not ioremapped, address
# 
# ChangeSet
#   2004/09/03 13:31:41+02:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Remove inappropriate unusual_devs.h entry
#   
#   A couple of months ago you applied a patch from Torsten Scherer to create
#   a new unusual_devs.h entry.  In further discussions with him I learned
#   that the entry wasn't needed to access the device; the only reason for it
#   was as a workaround for some old, buggy hotplug program on his system.
#   
#   Now Evan Fletcher reports that the entry actively prevents him from using
#   his device.  For me that's the last straw, so here's a patch to remove the
#   entry.  Torsten should be okay if he simply upgrades his hotplug package
#   or removes the buggy program.
#   
#   On Mon, 30 Aug 2004, Evan Fletcher wrote:
#   > Hi list,
#   >
#   > I have a Bytecc 5.25" External Enclosure, model ME-320U2F, that has
#   > both USB 2.0 and Firewire connections
#   > (http://www.byteccusa.com/product/enclosure/ME-320.htm).  It used to
#   > work fine on earlier Linux 2.6 kernels, but stopped working a few
#   > revisions ago.
#   >
#   > I tracked the problem down to an entry in unusual_devs.h:
#   >
#   > /* <torsten.scherer@uni-bielefeld.de>: I don't know the name of the bridge
#   >  * manufacturer, but I've got an external USB drive by the Revoltec company
#   >  * that needs this. otherwise the drive is recognized as /dev/sda, but any
#   >  * access to it blocks indefinitely.
#   >  */
#   > UNUSUAL_DEV(  0x0402, 0x5621, 0x0103, 0x0103,
#   >                 "Revoltec",
#   >                 "USB/IDE Bridge (ATA/ATAPI)",
#   >                 US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
#   
#   <...>
#   > So, is there some way that this entry can be modified so that my DVD+R
#   > works properly, and Mr. Scherer can still use his Revoltec external
#   > disk?
#   >
#   > Thank you,
#   > Evan Fletcher
#   
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/storage/unusual_devs.h
#   2004/08/30 16:12:17+02:00 stern@rowland.harvard.edu +0 -10
#   USB: Remove inappropriate unusual_devs.h entry
# 
# ChangeSet
#   2004/09/03 13:31:05+02:00 akpm@osdl.org 
#   [PATCH] USB: "Lost sync on frames" error in konicawc module
#   
#   From: <fgalea@prism.uvsq.fr>
#   
#   http://bugme.osdl.org/show_bug.cgi?id=3286
#   
#   The kernel keeps printing "Lost sync on frames" error messages as soon as a
#   program tries to access the webcam.  No video data can be retrieved from
#   the webcam.
#   
#   The following patch seems enough to solve the problem.  (just inverting the
#   order at which the old and new data blocks are sent to the user).
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/konicawc.c
#   2004/08/28 08:58:21+02:00 akpm@osdl.org +1 -1
#   USB: "Lost sync on frames" error in konicawc module
# 
# ChangeSet
#   2004/09/03 13:30:33+02:00 abbotti@mev.co.uk 
#   [PATCH] USB: Add B&B Electronics VID/PIDs to ftdi_sio
#   
#   This patch adds VID/PIDs for a few FTDI-based USB serial devices
#   from B&B Electronics to the ftdi_sio driver.
#   
#   
#   Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/ftdi_sio.h
#   2004/09/01 14:04:37+02:00 abbotti@mev.co.uk +8 -0
#   USB: Add B&B Electronics VID/PIDs to ftdi_sio
# 
# drivers/usb/serial/ftdi_sio.c
#   2004/09/01 14:04:37+02:00 abbotti@mev.co.uk +9 -0
#   USB: Add B&B Electronics VID/PIDs to ftdi_sio
# 
# ChangeSet
#   2004/09/03 13:29:55+02:00 david-b@pacbell.net 
#   [PATCH] USB: OHCI init cleanups
#   
#   This ought to fix the NS9750 init issue, and make the AMD756 case
#   at least somewhat better.  It makes the init go "by the book" in more
#   ways, and formalizes one quirk.
#   
#   Various OHCI init/reset cleanups for different silicion environments:
#   
#    - Reset a bit more "by the book".
#   
#       * Define a new quirk flag for the SiS and OPTi problem seen earlier.
#         Since 2.4 we've always worked around that quirk, even though we've
#         not seen that on other chips; but it's "wrong" and doesn't work on
#         some chips (notably NetSilicon NS9750).
#   
#         The quirk still seems to be needed for SiS, but either this test
#         machine is too fast for the OPTi problem to show up, or the frame
#         timing setup problem there came from a now-fixed bug.
#   
#       * Look at the HC state before resetting it; depending on whether
#         it was previously owned by BIOS, SMM, an OS, or nobody, different
#         USB signaling (and timings) might be needed.
#   
#       * Re-init the frame timings right after soft reset, rather than
#         later (potentially too much later).
#   
#       * Restore a reset in the PCI startup code, so this logic more closely
#         resembles the non-PCI paths (future code sharing).  It also makes it
#         easier to guarantee a 1-millisecond ceiling between reset and "go".
#   
#         An earlier reset is being done to help workaround BIOS-related
#         problems on some boards, but we may need an even earlier one
#         (as a PCI quirk, before IRQs get reconfigured).
#   
#    - Add an explicit #define to disable the BIOS/SMM handoff; it's
#      not just HPPA, many embedded chips don't expect BIOS either.
#   
#    - There are reports of AMD 756 machines disliking the OHCI suspend
#      patch of a few months back.  Erratum #10 partly explains that, so
#      now root hubs won't autosuspend on those Slot-A era chips.
#   
#    - Other minor fixes
#   
#       * We've got lots of non-PCI OHCI now too, so comments shouldn't
#         be assuming all-is-pci!
#   
#       * Hey, it's unsafe to call hc_reset() in IRQ (after unrecoverable
#         error); so just force a soft reset, don't do the whole thing.
#   
#   Tested on half a dozen different OHCI versions, but maybe some other
#   versions of OHCI will be sensitive to one of these changes.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/host/ohci.h
#   2004/09/02 18:39:10+02:00 david-b@pacbell.net +1 -0
#   USB: OHCI init cleanups
# 
# drivers/usb/host/ohci-pci.c
#   2004/09/02 18:39:10+02:00 david-b@pacbell.net +18 -0
#   USB: OHCI init cleanups
# 
# drivers/usb/host/ohci-hcd.c
#   2004/09/02 18:39:09+02:00 david-b@pacbell.net +52 -22
#   USB: OHCI init cleanups
# 
# ChangeSet
#   2004/09/03 13:29:11+02:00 alborchers@steinerpoint.com 
#   [PATCH] USB: corrected digi_acceleport 2.6.9-rc1 fix for hang on disconnect
#   
#   - Fixed hang on disconnect in digi_acceleport USB serial driver.
#     See http://bugme.osdl.org/show_bug.cgi?id=2459.  Close after
#     disconnect no longer tries to communicate with the device.
#   
#   Signed-off-by: Al Borchers <alborchers@steinerpoint.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/digi_acceleport.c
#   2004/09/03 10:43:16+02:00 alborchers@steinerpoint.com +6 -1
#   USB: corrected digi_acceleport 2.6.9-rc1 fix for hang on disconnect
# 
# ChangeSet
#   2004/09/03 13:28:34+02:00 oliver@neukum.org 
#   [PATCH] USB: switching microtek to usb_kill_urb
#   
#   Am Dienstag, 31. August 2004 17:41 schrieb Alan Stern:
#   > On Tue, 31 Aug 2004, Oliver Neukum wrote:
#   >
#   > Alan Stern
#   >
#   >
#   >
#   >
#   > > @@ -822,9 +822,8 @@
#   > >
#   > >  	usb_set_intfdata(intf, NULL);
#   > >
#   > > +	usb_kill_urb(desc->urb);
#   > >  	scsi_remove_host(desc->host);
#   > > -	usb_unlink_urb(desc->urb);
#   > > -	scsi_host_put(desc->host);
#   > >
#   > >  	usb_free_urb(desc->urb);
#   > >  	kfree(desc);
#   >
#   > I think you still need the scsi_host_put(), to account for the fact that
#   > scsi_host_alloc() sets the refcount to 1 initially.
#   
#   Right you are. Greg, please also apply this one.
#   
#   Signed-Off-By: Oliver Neukum <oliver@neukum.name>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/image/microtek.c
#   2004/08/31 21:10:57+02:00 oliver@neukum.org +1 -0
#   USB: switching microtek to usb_kill_urb
# 
# ChangeSet
#   2004/09/03 13:28:02+02:00 petkan@nucleusys.com 
#   [PATCH] USB: small rtl8150 patch
#   
#   this one make rtl8150 auto-load its register values at reset.  Not doing
#   so is known to cause improper setup when the device is being reseted
#   frequently.
#   
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/net/rtl8150.c
#   2004/08/27 10:50:54+02:00 petkan@nucleusys.com +2 -2
#   USB: small rtl8150 patch
# 
# ChangeSet
#   2004/09/03 13:27:27+02:00 wouter-kernel@fort-knox.rave.org 
#   [PATCH] USB: usb audio is for oss only
#   
#   Doh. Fixed.
# 
# drivers/usb/class/Kconfig
#   2004/08/27 16:45:25+02:00 wouter-kernel@fort-knox.rave.org +2 -1
#   USB: usb audio is for oss only
# 
# ChangeSet
#   2004/09/03 13:26:56+02:00 oliver@neukum.org 
#   [PATCH] USB: correct interrupt interval for kaweth
#   
#     - overriding the media check interrupt interval
#   
#   Signed-Off-By: Oliver Neukum <oliver@neukum.name>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/net/kaweth.c
#   2004/08/29 15:08:48+02:00 oliver@neukum.org +1 -1
#   USB: correct interrupt interval for kaweth
# 
# ChangeSet
#   2004/09/03 13:26:21+02:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Suspend/resume/wakeup support for UHCI root hub ports
#   
#   This patch adds support for suspending, resuming, and remote wakeup
#   detection on root hub ports to the UHCI driver.  It doesn't add support
#   for suspending or resuming the root hub itself (beyond what's already
#   there) -- that will require considerably more work.  But at least devices
#   plugged directly into the computer will interact nicely with power
#   management.
#   
#   Of lesser importance, the patch also simplifies some constant expressions.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/host/uhci-hub.c
#   2004/08/27 18:33:25+02:00 stern@rowland.harvard.edu +65 -26
#   USB: Suspend/resume/wakeup support for UHCI root hub ports
# 
# drivers/usb/host/uhci-hcd.h
#   2004/08/27 18:33:25+02:00 stern@rowland.harvard.edu +6 -0
#   USB: Suspend/resume/wakeup support for UHCI root hub ports
# 
# drivers/usb/host/uhci-hcd.c
#   2004/08/27 18:33:25+02:00 stern@rowland.harvard.edu +2 -0
#   USB: Suspend/resume/wakeup support for UHCI root hub ports
# 
# ChangeSet
#   2004/09/03 13:25:50+02:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Make usbcore use usb_kill_urb()
#   
#   This patch changes the only places in usbcore where usb_unlink_urb() is
#   still used for synchronous unlinking; now they will use usb_kill_urb().
#   As it turns out, there were only a couple of changes needed.
#   
#   This still leaves all the drivers to audit!
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/devio.c
#   2004/08/30 13:34:24+02:00 stern@rowland.harvard.edu +4 -3
#   USB: Make usbcore use usb_kill_urb()
# 
# ChangeSet
#   2004/09/03 13:25:14+02:00 zaitcev@redhat.com 
#   [PATCH] USB: Fixes for ub in 2.4.9-rc1 from Oliver and Pat
#   
#   - Set the allocation size in REQUEST SENSE (Pat LaVarre)
#   - Move add_timer invocations to safer places (Oliver Neukum)
#   
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/block/ub.c
#   2004/08/27 21:24:25+02:00 zaitcev@redhat.com +32 -27
#   USB: Fixes for ub in 2.4.9-rc1 from Oliver and Pat
# 
# ChangeSet
#   2004/09/03 13:24:41+02:00 oliver@neukum.org 
#   [PATCH] USB: switching microtek to usb_kill_urb
#   
#   this reworks the microtek driver's disconnect method, now that
#   usb_kill_urb is available.
#   
#   Signed-Off-By: Oliver Neukum <oliver@neukum.name>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/image/microtek.c
#   2004/08/30 23:10:24+02:00 oliver@neukum.org +2 -3
#   USB: switching microtek to usb_kill_urb
# 
# ChangeSet
#   2004/09/03 13:24:05+02:00 oliver@neukum.org 
#   [PATCH] USB: update of help text for hpusbscsi
#   
#   Signed-Off-By: Oliver Neukum <oliver@neukum.name>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/image/Kconfig
#   2004/08/30 21:05:25+02:00 oliver@neukum.org +4 -3
#   USB: update of help text for hpusbscsi
# 
# ChangeSet
#   2004/08/31 14:05:55-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# MAINTAINERS
#   2004/08/31 14:05:51-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/28 16:26:13-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# MAINTAINERS
#   2004/08/28 16:26:10-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/27 23:57:59-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# drivers/usb/gadget/inode.c
#   2004/08/27 23:57:54-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# MAINTAINERS
#   2004/08/27 23:57:54-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/27 14:14:37-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# include/linux/fs.h
#   2004/08/27 14:14:34-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# MAINTAINERS
#   2004/08/27 14:14:34-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/26 20:00:22-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# drivers/usb/gadget/inode.c
#   2004/08/26 20:00:18-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/core/message.c
#   2004/08/26 20:00:18-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/25 19:43:53-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# drivers/usb/misc/auerswald.c
#   2004/08/25 19:43:48-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/gadget/inode.c
#   2004/08/25 19:43:48-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/core/message.c
#   2004/08/25 19:43:48-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# MAINTAINERS
#   2004/08/25 19:43:48-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/24 17:51:22-07:00 akpm@bix.(none) 
#   Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6
#   into bix.(none):/usr/src/bk-usb
# 
# drivers/usb/misc/legousbtower.c
#   2004/08/24 17:51:16-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/24 17:50:09-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# include/linux/fs.h
#   2004/08/24 17:50:05-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# MAINTAINERS
#   2004/08/24 17:50:05-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/23 17:04:36-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# include/linux/fs.h
#   2004/08/23 17:04:32-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/misc/auerswald.c
#   2004/08/23 17:04:32-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/media/dabusb.c
#   2004/08/23 17:04:32-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/block/Kconfig
#   2004/08/23 17:04:32-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# MAINTAINERS
#   2004/08/23 17:04:32-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/23 14:47:21-07:00 akpm@bix.(none) 
#   Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6
#   into bix.(none):/usr/src/bk-usb
# 
# include/linux/fs.h
#   2004/08/23 14:47:18-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/misc/tiglusb.c
#   2004/08/23 14:47:18-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/misc/legousbtower.c
#   2004/08/23 14:47:18-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/misc/auerswald.c
#   2004/08/23 14:47:18-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/media/ov511.c
#   2004/08/23 14:47:18-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/media/dabusb.c
#   2004/08/23 14:47:18-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/class/usb-midi.c
#   2004/08/23 14:47:18-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/class/audio.c
#   2004/08/23 14:47:18-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/block/Kconfig
#   2004/08/23 14:47:18-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# MAINTAINERS
#   2004/08/23 14:47:17-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/23 14:46:26-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# include/linux/fs.h
#   2004/08/23 14:46:22-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/misc/auerswald.c
#   2004/08/23 14:46:22-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/media/dabusb.c
#   2004/08/23 14:46:22-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/block/Kconfig
#   2004/08/23 14:46:22-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# MAINTAINERS
#   2004/08/23 14:46:22-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/22 21:47:19-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# MAINTAINERS
#   2004/08/22 21:47:15-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/15 01:35:04-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# include/linux/fs.h
#   2004/08/15 01:35:01-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/08 14:55:28-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# drivers/usb/misc/tiglusb.c
#   2004/08/08 14:55:24-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/misc/legousbtower.c
#   2004/08/08 14:55:24-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/misc/auerswald.c
#   2004/08/08 14:55:24-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/media/dabusb.c
#   2004/08/08 14:55:24-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/class/usb-midi.c
#   2004/08/08 14:55:24-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/class/audio.c
#   2004/08/08 14:55:24-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/08 02:33:24-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# include/linux/fs.h
#   2004/08/08 02:33:20-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/07 19:17:31-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# include/linux/fs.h
#   2004/08/07 19:17:28-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/07 14:49:01-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# include/linux/fs.h
#   2004/08/07 14:48:57-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/06 16:01:52-07:00 akpm@bix.(none) 
#   Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6
#   into bix.(none):/usr/src/bk-usb
# 
# drivers/block/Kconfig
#   2004/08/06 16:01:49-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/06 16:01:00-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# include/linux/fs.h
#   2004/08/06 16:00:56-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/05 20:16:41-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# include/linux/fs.h
#   2004/08/05 20:16:38-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# MAINTAINERS
#   2004/08/05 20:16:38-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/05 13:06:30-07:00 akpm@bix.(none) 
#   Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6
#   into bix.(none):/usr/src/bk-usb
# 
# drivers/usb/media/ov511.c
#   2004/08/05 13:06:26-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/04 03:03:16-07:00 akpm@bix.(none) 
#   Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6
#   into bix.(none):/usr/src/bk-usb
# 
# drivers/usb/misc/tiglusb.c
#   2004/08/04 03:03:12-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/media/ov511.c
#   2004/08/04 03:03:12-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/02 13:35:47-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# MAINTAINERS
#   2004/08/02 13:35:43-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
diff -Nru a/drivers/block/ub.c b/drivers/block/ub.c
--- a/drivers/block/ub.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/block/ub.c	2004-09-06 17:33:19 -07:00
@@ -786,17 +786,16 @@
 	sc->work_urb.error_count = 0;
 	sc->work_urb.status = 0;
 
-	sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
-	add_timer(&sc->work_timer);
-
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
 		/* XXX Clear stalls */
 		printk("ub: cmd #%d start failed (%d)\n", cmd->tag, rc); /* P3 */
-		del_timer(&sc->work_timer);
 		ub_complete(&sc->work_done);
 		return rc;
 	}
 
+	sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
+	add_timer(&sc->work_timer);
+
 	cmd->state = UB_CMDST_CMD;
 	ub_cmdtr_state(sc, cmd);
 	return 0;
@@ -968,18 +967,17 @@
 		sc->work_urb.error_count = 0;
 		sc->work_urb.status = 0;
 
-		sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
-		add_timer(&sc->work_timer);
-
 		if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
 			/* XXX Clear stalls */
 			printk("ub: data #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */
-			del_timer(&sc->work_timer);
 			ub_complete(&sc->work_done);
 			ub_state_done(sc, cmd, rc);
 			return;
 		}
 
+		sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
+		add_timer(&sc->work_timer);
+
 		cmd->state = UB_CMDST_DATA;
 		ub_cmdtr_state(sc, cmd);
 
@@ -1063,19 +1061,18 @@
 			sc->work_urb.error_count = 0;
 			sc->work_urb.status = 0;
 
-			sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
-			add_timer(&sc->work_timer);
-
 			rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC);
 			if (rc != 0) {
 				/* XXX Clear stalls */
 				printk("%s: CSW #%d submit failed (%d)\n",
 				   sc->name, cmd->tag, rc); /* P3 */
-				del_timer(&sc->work_timer);
 				ub_complete(&sc->work_done);
 				ub_state_done(sc, cmd, rc);
 				return;
 			}
+
+			sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
+			add_timer(&sc->work_timer);
 			return;
 		}
 
@@ -1186,18 +1183,17 @@
 	sc->work_urb.error_count = 0;
 	sc->work_urb.status = 0;
 
-	sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
-	add_timer(&sc->work_timer);
-
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
 		/* XXX Clear stalls */
 		printk("ub: CSW #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */
-		del_timer(&sc->work_timer);
 		ub_complete(&sc->work_done);
 		ub_state_done(sc, cmd, rc);
 		return;
 	}
 
+	sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
+	add_timer(&sc->work_timer);
+
 	cmd->stat_count = 0;
 	cmd->state = UB_CMDST_STAT;
 	ub_cmdtr_state(sc, cmd);
@@ -1217,9 +1213,17 @@
 		goto error;
 	}
 
+	/*
+	 * ``If the allocation length is eighteen or greater, and a device
+	 * server returns less than eithteen bytes of data, the application
+	 * client should assume that the bytes not transferred would have been
+	 * zeroes had the device server returned those bytes.''
+	 */
 	memset(&sc->top_sense, 0, UB_SENSE_SIZE);
+
 	scmd = &sc->top_rqs_cmd;
 	scmd->cdb[0] = REQUEST_SENSE;
+	scmd->cdb[4] = UB_SENSE_SIZE;
 	scmd->cdb_len = 6;
 	scmd->dir = UB_DIR_READ;
 	scmd->state = UB_CMDST_INIT;
@@ -1271,14 +1275,13 @@
 	sc->work_urb.error_count = 0;
 	sc->work_urb.status = 0;
 
-	sc->work_timer.expires = jiffies + UB_CTRL_TIMEOUT;
-	add_timer(&sc->work_timer);
-
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
-		del_timer(&sc->work_timer);
 		ub_complete(&sc->work_done);
 		return rc;
 	}
+
+	sc->work_timer.expires = jiffies + UB_CTRL_TIMEOUT;
+	add_timer(&sc->work_timer);
 	return 0;
 }
 
@@ -1289,6 +1292,9 @@
 	unsigned char *sense = scmd->data;
 	struct ub_scsi_cmd *cmd;
 
+	/*
+	 * Ignoring scmd->act_len, because the buffer was pre-zeroed.
+	 */
 	ub_cmdtr_sense(sc, scmd, sense);
 
 	if ((cmd = ub_cmdq_peek(sc)) == NULL) {
@@ -1725,18 +1731,17 @@
 	sc->work_urb.error_count = 0;
 	sc->work_urb.status = 0;
 
-	init_timer(&timer);
-	timer.function = ub_probe_timeout;
-	timer.data = (unsigned long) &compl;
-	timer.expires = jiffies + UB_CTRL_TIMEOUT;
-	add_timer(&timer);
-
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
 		printk(KERN_WARNING
 		     "%s: Unable to submit a probe clear (%d)\n", sc->name, rc);
-		del_timer_sync(&timer);
 		return rc;
 	}
+
+	init_timer(&timer);
+	timer.function = ub_probe_timeout;
+	timer.data = (unsigned long) &compl;
+	timer.expires = jiffies + UB_CTRL_TIMEOUT;
+	add_timer(&timer);
 
 	wait_for_completion(&compl);
 
diff -Nru a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig
--- a/drivers/usb/class/Kconfig	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/class/Kconfig	2004-09-06 17:33:19 -07:00
@@ -9,7 +9,8 @@
 	depends on USB && SOUND
 	help
 	  Say Y here if you want to connect USB audio equipment such as
-	  speakers to your computer's USB port.
+	  speakers to your computer's USB port. You only need this if you use
+	  the OSS sound driver; ALSA has its own option for usb audio support.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called audio.
diff -Nru a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
--- a/drivers/usb/class/audio.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/class/audio.c	2004-09-06 17:33:19 -07:00
@@ -1949,15 +1949,12 @@
 static int usb_audio_open_mixdev(struct inode *inode, struct file *file)
 {
 	unsigned int minor = iminor(inode);
-	struct list_head *devs, *mdevs;
 	struct usb_mixerdev *ms;
 	struct usb_audio_state *s;
 
 	down(&open_sem);
-	list_for_each(devs, &audiodevs) {
-		s = list_entry(devs, struct usb_audio_state, audiodev);
-		list_for_each(mdevs, &s->mixerlist) {
-			ms = list_entry(mdevs, struct usb_mixerdev, list);
+	list_for_each_entry(s, &audiodevs, audiodev) {
+		list_for_each_entry(ms, &s->mixerlist, list) {
 			if (ms->dev_mixer == minor)
 				goto mixer_found;
 		}
@@ -2634,16 +2631,13 @@
 {
 	unsigned int minor = iminor(inode);
 	DECLARE_WAITQUEUE(wait, current);
-	struct list_head *devs, *adevs;
 	struct usb_audiodev *as;
 	struct usb_audio_state *s;
 
 	for (;;) {
 		down(&open_sem);
-		list_for_each(devs, &audiodevs) {
-			s = list_entry(devs, struct usb_audio_state, audiodev);
-			list_for_each(adevs, &s->audiolist) {
-				as = list_entry(adevs, struct usb_audiodev, list);
+		list_for_each_entry(s, &audiodevs, audiodev) {
+			list_for_each_entry(as, &s->audiolist, list) {
 				if (!((as->dev_audio ^ minor) & ~0xf))
 					goto device_found;
 			}
@@ -3809,7 +3803,6 @@
 static void usb_audio_disconnect(struct usb_interface *intf)
 {
 	struct usb_audio_state *s = usb_get_intfdata (intf);
-	struct list_head *list;
 	struct usb_audiodev *as;
 	struct usb_mixerdev *ms;
 
@@ -3831,8 +3824,7 @@
 	usb_set_intfdata (intf, NULL);
 
 	/* deregister all audio and mixer devices, so no new processes can open this device */
-	list_for_each(list, &s->audiolist) {
-		as = list_entry(list, struct usb_audiodev, list);
+	list_for_each_entry(as, &s->audiolist, list) {
 		usbin_disc(as);
 		usbout_disc(as);
 		wake_up(&as->usbin.dma.wait);
@@ -3843,8 +3835,7 @@
 		}
 		as->dev_audio = -1;
 	}
-	list_for_each(list, &s->mixerlist) {
-		ms = list_entry(list, struct usb_mixerdev, list);
+	list_for_each_entry(ms, &s->mixerlist, list) {
 		if (ms->dev_mixer >= 0) {
 			unregister_sound_mixer(ms->dev_mixer);
 			printk(KERN_INFO "usbaudio: unregister mixer 14,%d\n", ms->dev_mixer);
diff -Nru a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c
--- a/drivers/usb/class/usb-midi.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/class/usb-midi.c	2004-09-06 17:33:19 -07:00
@@ -805,7 +805,6 @@
 {
 	int minor = iminor(inode);
 	DECLARE_WAITQUEUE(wait, current);
-	struct list_head      *devs, *mdevs;
 	struct usb_midi_state *s;
 	struct usb_mididev    *m;
 	unsigned long flags;
@@ -817,10 +816,8 @@
 
 	for(;;) {
 		down(&open_sem);
-		list_for_each(devs, &mididevs) {
-			s = list_entry(devs, struct usb_midi_state, mididev);
-			list_for_each(mdevs, &s->midiDevList) {
-				m = list_entry(mdevs, struct usb_mididev, list);
+		list_for_each_entry(s, &mididevs, mididev) {
+			list_for_each_entry(m, &s->midiDevList, list) {
 				if ( !((m->dev_midi ^ minor) & ~0xf) )
 					goto device_found;
 			}
@@ -1994,7 +1991,6 @@
 static void usb_midi_disconnect(struct usb_interface *intf)
 {
 	struct usb_midi_state *s = usb_get_intfdata (intf);
-	struct list_head      *list;
 	struct usb_mididev    *m;
 
 	if ( !s )
@@ -2012,8 +2008,7 @@
 	s->usbdev = NULL;
 	usb_set_intfdata (intf, NULL);
 
-	list_for_each(list, &s->midiDevList) {
-		m = list_entry(list, struct usb_mididev, list);
+	list_for_each_entry(m, &s->midiDevList, list) {
 		wake_up(&(m->min.ep->wait));
 		wake_up(&(m->mout.ep->wait));
 		if ( m->dev_midi >= 0 ) {
diff -Nru a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
--- a/drivers/usb/core/devices.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/core/devices.c	2004-09-06 17:33:19 -07:00
@@ -149,7 +149,7 @@
 
 /*****************************************************************/
 
-void usbdevfs_conn_disc_event(void)
+void usbfs_conn_disc_event(void)
 {
 	conndiscevcnt++;
 	wake_up(&deviceconndiscwq);
@@ -569,7 +569,6 @@
 
 static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
-	struct list_head *buslist;
 	struct usb_bus *bus;
 	ssize_t ret, total_written = 0;
 	loff_t skip_bytes = *ppos;
@@ -581,12 +580,9 @@
 	if (!access_ok(VERIFY_WRITE, buf, nbytes))
 		return -EFAULT;
 
-	/* enumerate busses */
 	down (&usb_bus_list_lock);
-	list_for_each(buslist, &usb_bus_list) {
-		/* print devices for this bus */
-		bus = list_entry(buslist, struct usb_bus, bus_list);
-
+	/* print devices for all busses */
+	list_for_each_entry(bus, &usb_bus_list, bus_list) {
 		/* recurse through all children of the root hub */
 		if (!bus->root_hub)
 			continue;
@@ -682,7 +678,7 @@
 	return ret;
 }
 
-struct file_operations usbdevfs_devices_fops = {
+struct file_operations usbfs_devices_fops = {
 	.llseek =	usb_device_lseek,
 	.read =		usb_device_read,
 	.poll =		usb_device_poll,
diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
--- a/drivers/usb/core/devio.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/core/devio.c	2004-09-06 17:33:19 -07:00
@@ -21,7 +21,7 @@
  *
  *  $Id: devio.c,v 1.7 2000/02/01 17:28:48 fliegl Exp $
  *
- *  This file implements the usbdevfs/x/y files, where
+ *  This file implements the usbfs/x/y files, where
  *  x is the bus number and y the device number.
  *
  *  It allows user space programs/"drivers" to communicate directly
@@ -286,9 +286,10 @@
 	while (!list_empty(list)) {
 		as = list_entry(list->next, struct async, asynclist);
 		list_del_init(&as->asynclist);
+
+		/* drop the spinlock so the completion handler can run */
 		spin_unlock_irqrestore(&ps->lock, flags);
-                /* usb_unlink_urb calls the completion handler with status == -ENOENT */
-		usb_unlink_urb(as->urb);
+		usb_kill_urb(as->urb);
 		spin_lock_irqsave(&ps->lock, flags);
 	}
 	spin_unlock_irqrestore(&ps->lock, flags);
@@ -353,7 +354,7 @@
 	destroy_async_on_interface(ps, ifnum);
 }
 
-struct usb_driver usbdevfs_driver = {
+struct usb_driver usbfs_driver = {
 	.owner =	THIS_MODULE,
 	.name =		"usbfs",
 	.probe =	driver_probe,
@@ -378,7 +379,7 @@
 	if (!intf)
 		err = -ENOENT;
 	else
-		err = usb_driver_claim_interface(&usbdevfs_driver, intf, ps);
+		err = usb_driver_claim_interface(&usbfs_driver, intf, ps);
 	up_write(&usb_bus_type.subsys.rwsem);
 	if (err == 0)
 		set_bit(ifnum, &ps->ifclaimed);
@@ -401,7 +402,7 @@
 	if (!intf)
 		err = -ENOENT;
 	else if (test_and_clear_bit(ifnum, &ps->ifclaimed)) {
-		usb_driver_release_interface(&usbdevfs_driver, intf);
+		usb_driver_release_interface(&usbfs_driver, intf);
 		err = 0;
 	}
 	up_write(&usb_bus_type.subsys.rwsem);
@@ -976,7 +977,7 @@
 	as = async_getpending(ps, arg);
 	if (!as)
 		return -EINVAL;
-	usb_unlink_urb(as->urb);
+	usb_kill_urb(as->urb);
 	return 0;
 }
 
@@ -1314,7 +1315,7 @@
 	return mask;
 }
 
-struct file_operations usbdevfs_device_file_operations = {
+struct file_operations usbfs_device_file_operations = {
 	.llseek =	usbdev_lseek,
 	.read =		usbdev_read,
 	.poll =		usbdev_poll,
diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
--- a/drivers/usb/core/hcd-pci.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/core/hcd-pci.c	2004-09-06 17:33:19 -07:00
@@ -188,9 +188,9 @@
 	}
 	hcd->irq = dev->irq;
 
-	dev_info (hcd->self.controller, "irq %s, %s %p\n", bufp,
+	dev_info (hcd->self.controller, "irq %s, %s 0x%lx\n", bufp,
 		(driver->flags & HCD_MEMORY) ? "pci mem" : "io base",
-		base);
+		resource);
 
 	usb_bus_init (&hcd->self);
 	hcd->self.op = &usb_hcd_operations;
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/core/hub.c	2004-09-06 17:33:19 -07:00
@@ -1384,7 +1384,6 @@
 	int ret;
 
 	if (hdev->children[port]) {
-		/* FIXME need disconnect() for NOTATTACHED device */
 		usb_set_device_state(hdev->children[port],
 				USB_STATE_NOTATTACHED);
 	}
@@ -1396,6 +1395,30 @@
 	return ret;
 }
 
+/*
+ * Disable a port and mark a logical connnect-change event, so that some
+ * time later khubd will disconnect() any existing usb_device on the port
+ * and will re-enumerate if there actually is a device attached.
+ */
+static void hub_port_logical_disconnect(struct usb_device *hdev, int port)
+{
+	struct usb_hub *hub;
+
+	dev_dbg(hubdev(hdev), "logical disconnect on port %d\n", port + 1);
+	hub_port_disable(hdev, port);
+
+	hub = usb_get_intfdata(hdev->actconfig->interface[0]);
+	set_bit(port, hub->change_bits);
+
+	spin_lock_irq(&hub_event_lock);
+	if (list_empty(&hub->event_list)) {
+		list_add_tail(&hub->event_list, &hub_event_list);
+		wake_up(&khubd_wait);
+	}
+	spin_unlock_irq(&hub_event_lock);
+}
+
+
 #ifdef	CONFIG_USB_SUSPEND
 
 /*
@@ -1729,7 +1752,7 @@
 		}
 	}
 	if (status < 0)
-		status = hub_port_disable(hdev, port);
+		hub_port_logical_disconnect(hdev, port - 1);
 
 	return status;
 }
@@ -1869,11 +1892,11 @@
 			status = hub_port_resume(hdev, port + 1);
 		else {
 			status = finish_port_resume(udev);
-			if (status < 0)
-				status = hub_port_disable(hdev, port);
-			if (status < 0)
+			if (status < 0) {
 				dev_dbg(&intf->dev, "resume port %d --> %d\n",
-					port, status);
+					port + 1, status);
+				hub_port_logical_disconnect(hdev, port);
+			}
 		}
 		up(&udev->serialize);
 	}
@@ -2502,15 +2525,17 @@
 			if (portchange & USB_PORT_STAT_C_SUSPEND) {
 				clear_port_feature(hdev, i + 1,
 					USB_PORT_FEAT_C_SUSPEND);
-				if (hdev->children[i])
+				if (hdev->children[i]) {
 					ret = remote_wakeup(hdev->children[i]);
-				else
+					if (ret < 0)
+						connect_change = 1;
+				} else {
 					ret = -ENODEV;
+					hub_port_disable(hdev, i);
+				}
 				dev_dbg (hub_dev,
 					"resume on port %d, status %d\n",
 					i + 1, ret);
-				if (ret < 0)
-					ret = hub_port_disable(hdev, i);
 			}
 			
 			if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
@@ -2713,7 +2738,6 @@
 	struct usb_device *parent = udev->parent;
 	struct usb_device_descriptor descriptor = udev->descriptor;
 	int i, ret, port = -1;
-	struct usb_hub *hub;
 
 	if (udev->state == USB_STATE_NOTATTACHED ||
 			udev->state == USB_STATE_SUSPENDED) {
@@ -2794,18 +2818,7 @@
 	return 0;
  
 re_enumerate:
-	hub_port_disable(parent, port);
-
-	hub = usb_get_intfdata(parent->actconfig->interface[0]);
-	set_bit(port, hub->change_bits);
-
-	spin_lock_irq(&hub_event_lock);
-	if (list_empty(&hub->event_list)) {
-		list_add_tail(&hub->event_list, &hub_event_list);
-		wake_up(&khubd_wait);
-	}
-	spin_unlock_irq(&hub_event_lock);
-
+	hub_port_logical_disconnect(parent, port);
 	return -ENODEV;
 }
 EXPORT_SYMBOL(__usb_reset_device);
diff -Nru a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
--- a/drivers/usb/core/inode.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/core/inode.c	2004-09-06 17:33:19 -07:00
@@ -4,7 +4,7 @@
  *	inode.c  --  Inode/Dentry functions for the USB device file system.
  *
  *	Copyright (C) 2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
- *	Copyright (C) 2001,2002 Greg Kroah-Hartman (greg@kroah.com)
+ *	Copyright (C) 2001,2002,2004 Greg Kroah-Hartman (greg@kroah.com)
  *
  *	This program is free software; you can redistribute it and/or modify
  *	it under the terms of the GNU General Public License as published by
@@ -40,17 +40,15 @@
 #include <linux/smp_lock.h>
 #include <linux/parser.h>
 #include <asm/byteorder.h>
+#include "usb.h"
 
 static struct super_operations usbfs_ops;
 static struct file_operations default_file_operations;
 static struct inode_operations usbfs_dir_inode_operations;
-static struct vfsmount *usbdevfs_mount;
 static struct vfsmount *usbfs_mount;
-static int usbdevfs_mount_count;	/* = 0 */
 static int usbfs_mount_count;	/* = 0 */
 static int ignore_mount = 0;
 
-static struct dentry *devices_usbdevfs_dentry;
 static struct dentry *devices_usbfs_dentry;
 static int num_buses;	/* = 0 */
 
@@ -240,9 +238,6 @@
 	if (usbfs_mount && usbfs_mount->mnt_sb)
 		update_sb(usbfs_mount->mnt_sb);
 
-	if (usbdevfs_mount && usbdevfs_mount->mnt_sb)
-		update_sb(usbdevfs_mount->mnt_sb);
-
 	return 0;
 }
 
@@ -561,28 +556,12 @@
 
 /* --------------------------------------------------------------------- */
 
-
-
-/*
- * The usbdevfs name is now deprecated (as of 2.5.1).
- * It will be removed when the 2.7.x development cycle is started.
- * You have been warned :)
- */
-static struct file_system_type usbdevice_fs_type;
-
 static struct super_block *usb_get_sb(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data)
 {
 	return get_sb_single(fs_type, flags, data, usbfs_fill_super);
 }
 
-static struct file_system_type usbdevice_fs_type = {
-	.owner =	THIS_MODULE,
-	.name =		"usbdevfs",
-	.get_sb =	usb_get_sb,
-	.kill_sb =	kill_litter_super,
-};
-
 static struct file_system_type usb_fs_type = {
 	.owner =	THIS_MODULE,
 	.name =		"usbfs",
@@ -603,16 +582,10 @@
 	ignore_mount = 1;
 
 	/* create the devices special file */
-	retval = simple_pin_fs("usbdevfs", &usbdevfs_mount, &usbdevfs_mount_count);
-	if (retval) {
-		err ("Unable to get usbdevfs mount");
-		goto exit;
-	}
-
 	retval = simple_pin_fs("usbfs", &usbfs_mount, &usbfs_mount_count);
 	if (retval) {
 		err ("Unable to get usbfs mount");
-		goto error_clean_usbdevfs_mount;
+		goto exit;
 	}
 
 	ignore_mount = 0;
@@ -620,7 +593,7 @@
 	parent = usbfs_mount->mnt_sb->s_root;
 	devices_usbfs_dentry = fs_create_file ("devices",
 					       listmode | S_IFREG, parent,
-					       NULL, &usbdevfs_devices_fops,
+					       NULL, &usbfs_devices_fops,
 					       listuid, listgid);
 	if (devices_usbfs_dentry == NULL) {
 		err ("Unable to create devices usbfs file");
@@ -628,42 +601,19 @@
 		goto error_clean_mounts;
 	}
 
-	parent = usbdevfs_mount->mnt_sb->s_root;
-	devices_usbdevfs_dentry = fs_create_file ("devices",
-						  listmode | S_IFREG, parent,
-						  NULL, &usbdevfs_devices_fops,
-						  listuid, listgid);
-	if (devices_usbdevfs_dentry == NULL) {
-		err ("Unable to create devices usbfs file");
-		retval = -ENODEV;
-		goto error_remove_file;
-	}
-
 	goto exit;
 	
-error_remove_file:
-	fs_remove_file (devices_usbfs_dentry);
-	devices_usbfs_dentry = NULL;
-
 error_clean_mounts:
 	simple_release_fs(&usbfs_mount, &usbfs_mount_count);
-
-error_clean_usbdevfs_mount:
-	simple_release_fs(&usbdevfs_mount, &usbdevfs_mount_count);
-
 exit:
 	return retval;
 }
 
 static void remove_special_files (void)
 {
-	if (devices_usbdevfs_dentry)
-		fs_remove_file (devices_usbdevfs_dentry);
 	if (devices_usbfs_dentry)
 		fs_remove_file (devices_usbfs_dentry);
-	devices_usbdevfs_dentry = NULL;
 	devices_usbfs_dentry = NULL;
-	simple_release_fs(&usbdevfs_mount, &usbdevfs_mount_count);
 	simple_release_fs(&usbfs_mount, &usbfs_mount_count);
 }
 
@@ -671,11 +621,6 @@
 {
 	struct inode *inode;
 
-	if (devices_usbdevfs_dentry) {
-		inode = devices_usbdevfs_dentry->d_inode;
-		if (inode)
-			inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	}
 	if (devices_usbfs_dentry) {
 		inode = devices_usbfs_dentry->d_inode;
 		if (inode)
@@ -707,29 +652,16 @@
 		return;
 	}
 
-	parent = usbdevfs_mount->mnt_sb->s_root;
-	bus->usbdevfs_dentry = fs_create_file (name, busmode | S_IFDIR, parent,
-					       bus, NULL, busuid, busgid);
-	if (bus->usbdevfs_dentry == NULL) {
-		err ("error creating usbdevfs bus entry");
-		return;
-	}
-
 	usbfs_update_special();
-	usbdevfs_conn_disc_event();
+	usbfs_conn_disc_event();
 }
 
-
 void usbfs_remove_bus(struct usb_bus *bus)
 {
 	if (bus->usbfs_dentry) {
 		fs_remove_file (bus->usbfs_dentry);
 		bus->usbfs_dentry = NULL;
 	}
-	if (bus->usbdevfs_dentry) {
-		fs_remove_file (bus->usbdevfs_dentry);
-		bus->usbdevfs_dentry = NULL;
-	}
 
 	--num_buses;
 	if (num_buses <= 0) {
@@ -738,7 +670,7 @@
 	}
 
 	usbfs_update_special();
-	usbdevfs_conn_disc_event();
+	usbfs_conn_disc_event();
 }
 
 void usbfs_add_device(struct usb_device *dev)
@@ -750,20 +682,12 @@
 	sprintf (name, "%03d", dev->devnum);
 	dev->usbfs_dentry = fs_create_file (name, devmode | S_IFREG,
 					    dev->bus->usbfs_dentry, dev,
-					    &usbdevfs_device_file_operations,
+					    &usbfs_device_file_operations,
 					    devuid, devgid);
 	if (dev->usbfs_dentry == NULL) {
 		err ("error creating usbfs device entry");
 		return;
 	}
-	dev->usbdevfs_dentry = fs_create_file (name, devmode | S_IFREG,
-					       dev->bus->usbdevfs_dentry, dev,
-					       &usbdevfs_device_file_operations,
-					       devuid, devgid);
-	if (dev->usbdevfs_dentry == NULL) {
-		err ("error creating usbdevfs device entry");
-		return;
-	}
 
 	/* Set the size of the device's file to be
 	 * equal to the size of the device descriptors. */
@@ -775,11 +699,9 @@
 	}
 	if (dev->usbfs_dentry->d_inode)
 		dev->usbfs_dentry->d_inode->i_size = i_size;
-	if (dev->usbdevfs_dentry->d_inode)
-		dev->usbdevfs_dentry->d_inode->i_size = i_size;
 
 	usbfs_update_special();
-	usbdevfs_conn_disc_event();
+	usbfs_conn_disc_event();
 }
 
 void usbfs_remove_device(struct usb_device *dev)
@@ -791,10 +713,6 @@
 		fs_remove_file (dev->usbfs_dentry);
 		dev->usbfs_dentry = NULL;
 	}
-	if (dev->usbdevfs_dentry) {
-		fs_remove_file (dev->usbdevfs_dentry);
-		dev->usbdevfs_dentry = NULL;
-	}
 	while (!list_empty(&dev->filelist)) {
 		ds = list_entry(dev->filelist.next, struct dev_state, list);
 		list_del_init(&ds->list);
@@ -807,51 +725,38 @@
 		}
 	}
 	usbfs_update_special();
-	usbdevfs_conn_disc_event();
+	usbfs_conn_disc_event();
 }
 
 /* --------------------------------------------------------------------- */
 
-#ifdef CONFIG_PROC_FS		
 static struct proc_dir_entry *usbdir = NULL;
-#endif	
 
 int __init usbfs_init(void)
 {
 	int retval;
 
-	retval = usb_register(&usbdevfs_driver);
+	retval = usb_register(&usbfs_driver);
 	if (retval)
 		return retval;
 
 	retval = register_filesystem(&usb_fs_type);
 	if (retval) {
-		usb_deregister(&usbdevfs_driver);
-		return retval;
-	}
-	retval = register_filesystem(&usbdevice_fs_type);
-	if (retval) {
-		unregister_filesystem(&usb_fs_type);
-		usb_deregister(&usbdevfs_driver);
+		usb_deregister(&usbfs_driver);
 		return retval;
 	}
 
-#ifdef CONFIG_PROC_FS		
-	/* create mount point for usbdevfs */
+	/* create mount point for usbfs */
 	usbdir = proc_mkdir("usb", proc_bus);
-#endif	
 
 	return 0;
 }
 
 void usbfs_cleanup(void)
 {
-	usb_deregister(&usbdevfs_driver);
+	usb_deregister(&usbfs_driver);
 	unregister_filesystem(&usb_fs_type);
-	unregister_filesystem(&usbdevice_fs_type);
-#ifdef CONFIG_PROC_FS	
 	if (usbdir)
 		remove_proc_entry("usb", proc_bus);
-#endif
 }
 
diff -Nru a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
--- a/drivers/usb/core/urb.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/core/urb.c	2004-09-06 17:33:19 -07:00
@@ -451,6 +451,9 @@
 	if (!urb)
 		return -EINVAL;
 	if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) {
+		printk(KERN_NOTICE "usb_unlink_urb() is deprecated for "
+			"synchronous unlinks.  Use usb_kill_urb()\n");
+		WARN_ON(1);
 		usb_kill_urb(urb);
 		return 0;
 	}
diff -Nru a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
--- a/drivers/usb/core/usb.h	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/core/usb.h	2004-09-06 17:33:19 -07:00
@@ -27,3 +27,9 @@
 
 /* for labeling diagnostics */
 extern const char *usbcore_name;
+
+/* usbfs stuff */
+extern struct usb_driver usbfs_driver;
+extern struct file_operations usbfs_devices_fops;
+extern struct file_operations usbfs_device_file_operations;
+extern void usbfs_conn_disc_event(void);
diff -Nru a/drivers/usb/host/hc_sl811.c b/drivers/usb/host/hc_sl811.c
--- a/drivers/usb/host/hc_sl811.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/host/hc_sl811.c	2004-09-06 17:33:19 -07:00
@@ -1343,15 +1343,11 @@
  *****************************************************************/
 static void __exit hci_hcd_cleanup (void)
 {
-	struct list_head *hci_l;
-	hci_t *hci;
+	hci_t *hci, *tmp;
 
 	DBGFUNC ("Enter hci_hcd_cleanup\n");
-	for (hci_l = hci_hcd_list.next; hci_l != &hci_hcd_list;) {
-		hci = list_entry (hci_l, hci_t, hci_hcd_list);
-		hci_l = hci_l->next;
+	list_for_each_entry_safe(hci, tmp, &hci_hcd_list, hci_hcd_list)
 		hc_release_hci (hci);
-	}
 }
 
 module_init (hci_hcd_init);
diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
--- a/drivers/usb/host/ohci-hcd.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/host/ohci-hcd.c	2004-09-06 17:33:19 -07:00
@@ -2,7 +2,7 @@
  * OHCI HCD (Host Controller Driver) for USB.
  *
  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>
  * 
  * [ Initialisation is based on Linus'  ]
  * [ uhci code and gregs ohci fragments ]
@@ -122,6 +122,16 @@
 #define	OHCI_INTR_INIT \
 	(OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_WDH)
 
+#ifdef __hppa__
+/* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
+#define	IR_DISABLE
+#endif
+
+#ifdef CONFIG_ARCH_OMAP
+/* OMAP doesn't support IR (no SMM; not needed) */
+#define	IR_DISABLE
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 static const char	hcd_name [] = "ohci_hcd";
@@ -407,10 +417,8 @@
 		/* also: power/overcurrent flags in roothub.a */
 	}
 
-	/* SMM owns the HC?  not for long!
-	 * On PA-RISC, PDC can leave IR set incorrectly; ignore it there.
-	 */
-#ifndef __hppa__
+#ifndef IR_DISABLE
+	/* SMM owns the HC?  not for long! */
 	if (ohci_readl (&ohci->regs->control) & OHCI_CTRL_IR) {
 		ohci_dbg (ohci, "USB HC TakeOver from BIOS/SMM\n");
 
@@ -435,18 +443,40 @@
 	/* Disable HC interrupts */
 	writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
 
-	ohci_dbg (ohci, "reset, control = 0x%x\n",
-		  ohci_readl (&ohci->regs->control));
-
-  	/* Reset USB (needed by some controllers); RemoteWakeupConnected
+  	/* Reset USB nearly "by the book".  RemoteWakeupConnected
 	 * saved if boot firmware (BIOS/SMM/...) told us it's connected
 	 * (for OHCI integrated on mainboard, it normally is)
 	 */
 	ohci->hc_control = ohci_readl (&ohci->regs->control);
-	ohci->hc_control &= OHCI_CTRL_RWC;	/* hcfs 0 = RESET */
-	if (ohci->hc_control)
+	ohci_dbg (ohci, "resetting from state '%s', control = 0x%x\n",
+			hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
+			ohci->hc_control);
+
+	if (ohci->hc_control & OHCI_CTRL_RWC
+			&& !(ohci->flags & OHCI_QUIRK_AMD756))
 		ohci->hcd.can_wakeup = 1;
+
+	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+	case OHCI_USB_OPER:
+		temp = 0;
+		break;
+	case OHCI_USB_SUSPEND:
+	case OHCI_USB_RESUME:
+		ohci->hc_control &= OHCI_CTRL_RWC;
+		ohci->hc_control |= OHCI_USB_RESUME;
+		temp = 10 /* msec wait */;
+		break;
+	// case OHCI_USB_RESET:
+	default:
+		ohci->hc_control &= OHCI_CTRL_RWC;
+		ohci->hc_control |= OHCI_USB_RESET;
+		temp = 50 /* msec wait */;
+		break;
+	}
 	writel (ohci->hc_control, &ohci->regs->control);
+	// flush the writes
+	(void) ohci_readl (&ohci->regs->control);
+	msleep(temp);
 	if (power_switching) {
 		unsigned ports = roothub_a (ohci) & RH_A_NDP; 
 
@@ -455,9 +485,8 @@
 			writel (RH_PS_LSDA,
 				&ohci->regs->roothub.portstatus [temp]);
 	}
-	// flush those pci writes
+	// flush those writes
 	(void) ohci_readl (&ohci->regs->control);
-	msleep (50);
 
 	/* HC Reset requires max 10 us delay */
 	writel (OHCI_HCR,  &ohci->regs->cmdstatus);
@@ -469,6 +498,7 @@
 		}
 		udelay (1);
 	}
+	periodic_reinit (ohci);
 
 	/* now we're in the SUSPEND state ... must go OPERATIONAL
 	 * within 2msec else HC enters RESUME
@@ -477,10 +507,11 @@
 	 * (SiS, OPTi ...), so reset again instead.  SiS doesn't need
 	 * this if we write fmInterval after we're OPERATIONAL.
 	 */
-	writel (ohci->hc_control, &ohci->regs->control);
-	// flush those pci writes
-	(void) ohci_readl (&ohci->regs->control);
-
+	if (ohci->flags & OHCI_QUIRK_INITRESET) {
+		writel (ohci->hc_control, &ohci->regs->control);
+		// flush those writes
+		(void) ohci_readl (&ohci->regs->control);
+	}
 	return 0;
 }
 
@@ -506,8 +537,6 @@
 	/* a reset clears this */
 	writel ((u32) ohci->hcca_dma, &ohci->regs->hcca);
 
-	periodic_reinit (ohci);
-
 	/* some OHCI implementations are finicky about how they init.
 	 * bogus values here mean not even enumeration could work.
 	 */
@@ -553,7 +582,7 @@
 	writel (tmp, &ohci->regs->roothub.a);
 	writel (RH_HS_LPSC, &ohci->regs->roothub.status);
 	writel (power_switching ? RH_B_PPCM : 0, &ohci->regs->roothub.b);
-	// flush those pci writes
+	// flush those writes
 	(void) ohci_readl (&ohci->regs->control);
 
 	// POTPGT delay is bits 24-31, in 2 ms units.
@@ -620,7 +649,8 @@
 		// e.g. due to PCI Master/Target Abort
 
 		ohci_dump (ohci, 1);
-		hc_reset (ohci);
+		ohci->hc_control &= OHCI_CTRL_RWC;	/* hcfs 0 = RESET */
+		writel (ohci->hc_control, &ohci->regs->control);
 	}
 
 	if (ints & OHCI_INTR_RD) {
@@ -655,7 +685,7 @@
 	if (HCD_IS_RUNNING(ohci->hcd.state)) {
 		writel (ints, &regs->intrstatus);
 		writel (OHCI_INTR_MIE, &regs->intrenable);	
-		// flush those pci writes
+		// flush those writes
 		(void) ohci_readl (&ohci->regs->control);
 	}
 
diff -Nru a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
--- a/drivers/usb/host/ohci-pci.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/host/ohci-pci.c	2004-09-06 17:33:19 -07:00
@@ -61,6 +61,7 @@
 				&& pdev->device == 0x740c) {
 			ohci->flags = OHCI_QUIRK_AMD756;
 			ohci_info (ohci, "AMD756 erratum 4 workaround\n");
+			// also somewhat erratum 10 (suspend/resume issues)
 		}
 
 		/* FIXME for some of the early AMD 760 southbridges, OHCI
@@ -75,6 +76,8 @@
 				&& pdev->device == 0xc861) {
 			ohci_info (ohci,
 				"WARNING: OPTi workarounds unavailable\n");
+			/* OPTi sometimes acts wierd during init */
+			ohci->flags = OHCI_QUIRK_INITRESET;
 		}
 
 		/* Check for NSC87560. We have to look at the bridge (fn1) to
@@ -92,6 +95,12 @@
 				ohci_info (ohci, "Using NSC SuperIO setup\n");
 			}
 		}
+
+		/* SiS sometimes acts wierd during init */
+		else if (pdev->vendor == PCI_VENDOR_ID_SI) {
+			ohci->flags = OHCI_QUIRK_INITRESET;
+			ohci_info(ohci, "SiS init quirk\n");
+		}
 	
 	}
 
@@ -99,6 +108,15 @@
 	if ((ret = ohci_mem_init (ohci)) < 0) {
 		ohci_stop (hcd);
 		return ret;
+	}
+
+	/* NOTE: this is a second reset. the first one helps
+	 * keep bios/smm irqs from making trouble, but it was
+	 * probably more than 1msec ago...
+	 */
+	if (hc_reset (ohci) < 0) {
+		ohci_stop (hcd);
+		return -ENODEV;
 	}
 
 	if (hc_start (ohci) < 0) {
diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
--- a/drivers/usb/host/ohci.h	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/host/ohci.h	2004-09-06 17:33:19 -07:00
@@ -387,6 +387,7 @@
 	unsigned long		flags;		/* for HC bugs */
 #define	OHCI_QUIRK_AMD756	0x01			/* erratum #4 */
 #define	OHCI_QUIRK_SUPERIO	0x02			/* natsemi */
+#define	OHCI_QUIRK_INITRESET	0x04			/* SiS, OPTi, ... */
 	// there are also chip quirks/bugs in init logic
 
 	/*
diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
--- a/drivers/usb/host/uhci-hcd.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/host/uhci-hcd.c	2004-09-06 17:33:19 -07:00
@@ -1661,6 +1661,8 @@
 
 	/* Poll for and perform state transitions */
 	hc_state_transitions(uhci);
+	if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED))
+		uhci_check_resume(uhci);
 
 	init_stall_timer(hcd);
 }
diff -Nru a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
--- a/drivers/usb/host/uhci-hcd.h	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/host/uhci-hcd.h	2004-09-06 17:33:19 -07:00
@@ -352,6 +352,12 @@
 	int resume_detect;			/* Need a Global Resume */
 	unsigned int saved_framenumber;		/* Save during PM suspend */
 
+	/* Support for port suspend/resume */
+	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 */
+
 	/* Main list of URB's currently controlled by this HC */
 	struct list_head urb_list;		/* P: uhci->schedule_lock */
 
diff -Nru a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
--- a/drivers/usb/host/uhci-hub.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/host/uhci-hub.c	2004-09-06 17:33:19 -07:00
@@ -36,13 +36,13 @@
 static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-	unsigned long io_addr = uhci->io_addr;
-	int i;
+	int port;
 
 	*buf = 0;
-	for (i = 0; i < uhci->rh_numports; i++) {
-		if (inw(io_addr + USBPORTSC1 + i * 2) & RWC_BITS)
-			*buf |= (1 << (i + 1));
+	for (port = 0; port < uhci->rh_numports; ++port) {
+		if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & RWC_BITS) ||
+				test_bit(port, &uhci->port_c_suspend))
+			*buf |= (1 << (port + 1));
 	}
 	return !!*buf;
 }
@@ -62,6 +62,35 @@
 	status &= ~(RWC_BITS|WZ_BITS); \
 	outw(status, port_addr)
 
+/* 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_check_resume(struct uhci_hcd *uhci)
+{
+	unsigned int port;
+	unsigned int 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)) {
+			if (!test_bit(port, &uhci->resuming_ports)) {
+
+				/* Port received a wakeup request */
+				set_bit(port, &uhci->resuming_ports);
+				uhci->resume_timeout = jiffies +
+						msecs_to_jiffies(20);
+			} else if (time_after_eq(jiffies,
+						uhci->resume_timeout)) {
+				CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD);
+				clear_bit(port, &uhci->resuming_ports);
+				clear_bit(port, &uhci->suspended_ports);
+				set_bit(port, &uhci->port_c_suspend);
+			}
+		}
+	}
+}
 
 /* size of returned buffer is part of USB spec */
 static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
@@ -69,8 +98,9 @@
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	int status, retval = 0, len = 0;
-	unsigned long port_addr = uhci->io_addr + USBPORTSC1 + 2 * (wIndex-1);
-	__u16 wPortChange, wPortStatus;
+	unsigned int port = wIndex - 1;
+	unsigned long port_addr = uhci->io_addr + USBPORTSC1 + 2 * port;
+	u16 wPortChange, wPortStatus;
 
 	switch (typeReq) {
 		/* Request Destination:
@@ -82,11 +112,15 @@
 		*/
 
 	case GetHubStatus:
-		*(__u32 *)buf = cpu_to_le32(0);
+		*(u32 *) buf = cpu_to_le32(0);
 		OK(4);		/* hub power */
 	case GetPortStatus:
-		if (!wIndex || wIndex > uhci->rh_numports)
+		if (port >= uhci->rh_numports)
 			goto err;
+
+		if (uhci->resuming_ports)
+			uhci_check_resume(uhci);
+
 		status = inw(port_addr);
 
 		/* Intel controllers report the OverCurrent bit active on.
@@ -97,37 +131,39 @@
 				PCI_VENDOR_ID_VIA)
 			status ^= USBPORTSC_OC;
 
-		/* UHCI doesn't support C_SUSPEND and C_RESET (always false) */
+		/* UHCI doesn't support C_RESET (always false) */
 		wPortChange = 0;
 		if (status & USBPORTSC_CSC)
-			wPortChange |= 1 << (USB_PORT_FEAT_C_CONNECTION - 16);
+			wPortChange |= USB_PORT_STAT_C_CONNECTION;
 		if (status & USBPORTSC_PEC)
-			wPortChange |= 1 << (USB_PORT_FEAT_C_ENABLE - 16);
+			wPortChange |= USB_PORT_STAT_C_ENABLE;
 		if (status & USBPORTSC_OCC)
-			wPortChange |= 1 << (USB_PORT_FEAT_C_OVER_CURRENT - 16);
+			wPortChange |= USB_PORT_STAT_C_OVERCURRENT;
+		if (test_bit(port, &uhci->port_c_suspend))
+			wPortChange |= USB_PORT_STAT_C_SUSPEND;
 
 		/* UHCI has no power switching (always on) */
-		wPortStatus = 1 << USB_PORT_FEAT_POWER;
+		wPortStatus = USB_PORT_STAT_POWER;
 		if (status & USBPORTSC_CCS)
-			wPortStatus |= 1 << USB_PORT_FEAT_CONNECTION;
+			wPortStatus |= USB_PORT_STAT_CONNECTION;
 		if (status & USBPORTSC_PE) {
-			wPortStatus |= 1 << USB_PORT_FEAT_ENABLE;
+			wPortStatus |= USB_PORT_STAT_ENABLE;
 			if (status & (USBPORTSC_SUSP | USBPORTSC_RD))
-				wPortStatus |= 1 << USB_PORT_FEAT_SUSPEND;
+				wPortStatus |= USB_PORT_STAT_SUSPEND;
 		}
 		if (status & USBPORTSC_OC)
-			wPortStatus |= 1 << USB_PORT_FEAT_OVER_CURRENT;
+			wPortStatus |= USB_PORT_STAT_OVERCURRENT;
 		if (status & USBPORTSC_PR)
-			wPortStatus |= 1 << USB_PORT_FEAT_RESET;
+			wPortStatus |= USB_PORT_STAT_RESET;
 		if (status & USBPORTSC_LSDA)
-			wPortStatus |= 1 << USB_PORT_FEAT_LOWSPEED;
+			wPortStatus |= USB_PORT_STAT_LOW_SPEED;
 
 		if (wPortChange)
 			dev_dbg(uhci_dev(uhci), "port %d portsc %04x\n",
 					wIndex, status);
 
-		*(__u16 *)buf = cpu_to_le16(wPortStatus);
-		*(__u16 *)(buf + 2) = cpu_to_le16(wPortChange);
+		*(u16 *) buf = cpu_to_le16(wPortStatus);
+		*(u16 *) (buf + 2) = cpu_to_le16(wPortChange);
 		OK(4);
 	case SetHubFeature:		/* We don't implement these */
 	case ClearHubFeature:
@@ -140,11 +176,12 @@
 		}
 		break;
 	case SetPortFeature:
-		if (!wIndex || wIndex > uhci->rh_numports)
+		if (port >= uhci->rh_numports)
 			goto err;
 
 		switch (wValue) {
 		case USB_PORT_FEAT_SUSPEND:
+			set_bit(port, &uhci->suspended_ports);
 			SET_RH_PORTSTAT(USBPORTSC_SUSP);
 			OK(0);
 		case USB_PORT_FEAT_RESET:
@@ -164,7 +201,7 @@
 		}
 		break;
 	case ClearPortFeature:
-		if (!wIndex || wIndex > uhci->rh_numports)
+		if (port >= uhci->rh_numports)
 			goto err;
 
 		switch (wValue) {
@@ -175,10 +212,12 @@
 			CLR_RH_PORTSTAT(USBPORTSC_PEC);
 			OK(0);
 		case USB_PORT_FEAT_SUSPEND:
-			CLR_RH_PORTSTAT(USBPORTSC_SUSP);
+			set_bit(port, &uhci->resuming_ports);
+			uhci->resume_timeout = jiffies + msecs_to_jiffies(20);
+			SET_RH_PORTSTAT(USBPORTSC_RD);
 			OK(0);
 		case USB_PORT_FEAT_C_SUSPEND:
-			/* this driver won't report these */
+			clear_bit(port, &uhci->port_c_suspend);
 			OK(0);
 		case USB_PORT_FEAT_POWER:
 			/* UHCI has no power switching */
diff -Nru a/drivers/usb/image/Kconfig b/drivers/usb/image/Kconfig
--- a/drivers/usb/image/Kconfig	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/image/Kconfig	2004-09-06 17:33:19 -07:00
@@ -30,11 +30,12 @@
 	  This driver can be compiled as a module, called microtek.
 
 config USB_HPUSBSCSI
-	tristate "HP53xx USB scanner support (EXPERIMENTAL)"
-	depends on USB && SCSI && EXPERIMENTAL
+	tristate "HP53xx USB scanner support"
+	depends on USB && SCSI
 	help
 	  Say Y here if you want support for the HP 53xx series of scanners
-	  and the Minolta Scan Dual. This driver is experimental.
+	  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/microtek.c b/drivers/usb/image/microtek.c
--- a/drivers/usb/image/microtek.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/image/microtek.c	2004-09-06 17:33:19 -07:00
@@ -324,7 +324,7 @@
 	MTS_DEBUG_GOT_HERE();
 	mts_debug_dump(desc);
 
-	usb_unlink_urb( desc->urb );
+	usb_kill_urb( desc->urb );
 }
 
 static int mts_scsi_abort (Scsi_Cmnd *srb)
@@ -822,10 +822,10 @@
 
 	usb_set_intfdata(intf, NULL);
 
+	usb_kill_urb(desc->urb);
 	scsi_remove_host(desc->host);
-	usb_unlink_urb(desc->urb);
-	scsi_host_put(desc->host);
 
+	scsi_host_put(desc->host);
 	usb_free_urb(desc->urb);
 	kfree(desc);
 }
diff -Nru a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c
--- a/drivers/usb/media/dabusb.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/media/dabusb.c	2004-09-06 17:33:19 -07:00
@@ -109,16 +109,13 @@
 static int dabusb_cancel_queue (pdabusb_t s, struct list_head *q)
 {
 	unsigned long flags;
-	struct list_head *p;
 	pbuff_t b;
 
 	dbg("dabusb_cancel_queue");
 
 	spin_lock_irqsave (&s->lock, flags);
 
-	for (p = q->next; p != q; p = p->next) {
-		b = list_entry (p, buff_t, buff_list);
-
+	list_for_each_entry(b, q, buff_list) {
 #ifdef DEBUG
 		dump_urb(b->purb);
 #endif
@@ -598,6 +595,7 @@
 		if (file->f_flags & O_NONBLOCK) {
 			return -EBUSY;
 		}
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout (HZ / 2);
 
 		if (signal_pending (current)) {
diff -Nru a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c
--- a/drivers/usb/media/konicawc.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/media/konicawc.c	2004-09-06 17:33:19 -07:00
@@ -362,8 +362,8 @@
 		else if (!urb->status && !cam->last_data_urb->status)
 			len = konicawc_compress_iso(uvd, cam->last_data_urb, urb);
 
-		resubmit_urb(uvd, urb);
 		resubmit_urb(uvd, cam->last_data_urb);
+		resubmit_urb(uvd, urb);
 		cam->last_data_urb = NULL;
 		uvd->stats.urb_length = len;
 		uvd->stats.data_count += len;
diff -Nru a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c
--- a/drivers/usb/misc/tiglusb.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/misc/tiglusb.c	2004-09-06 17:33:19 -07:00
@@ -115,6 +115,7 @@
 			return -EBUSY;
 		}
 
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout (HZ / 2);
 
 		if (signal_pending (current)) {
diff -Nru a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
--- a/drivers/usb/net/kaweth.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/net/kaweth.c	2004-09-06 17:33:19 -07:00
@@ -668,7 +668,7 @@
 		INTBUFFERSIZE,
 		int_callback,
 		kaweth,
-		8);
+		250); /* overriding the descriptor */
 	kaweth->irq_urb->transfer_dma = kaweth->intbufferhandle;
 	kaweth->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
diff -Nru a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
--- a/drivers/usb/net/rtl8150.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/net/rtl8150.c	2004-09-06 17:33:19 -07:00
@@ -20,7 +20,7 @@
 #include <asm/uaccess.h>
 
 /* Version Information */
-#define DRIVER_VERSION "v0.6.1 (2004/03/13)"
+#define DRIVER_VERSION "v0.6.2 (2004/08/27)"
 #define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
 #define DRIVER_DESC "rtl8150 based usb-ethernet driver"
 
@@ -344,7 +344,7 @@
 
 static int rtl8150_reset(rtl8150_t * dev)
 {
-	u8 data = 0x10;
+	u8 data = 0x11;
 	int i = HZ;
 
 	set_registers(dev, CR, 1, &data);
diff -Nru a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
--- a/drivers/usb/serial/digi_acceleport.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/serial/digi_acceleport.c	2004-09-06 17:33:19 -07:00
@@ -1553,13 +1553,17 @@
 dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_count );
 
 
+	/* if disconnected, just clear flags */
+	if (!usb_get_intfdata(port->serial->interface))
+		goto exit;
+
 	/* do cleanup only after final close on this port */
 	spin_lock_irqsave( &priv->dp_port_lock, flags );
 	priv->dp_in_close = 1;
 	spin_unlock_irqrestore( &priv->dp_port_lock, flags );
 
 	/* tell line discipline to process only XON/XOFF */
-        tty->closing = 1;
+	tty->closing = 1;
 
 	/* wait for output to drain */
 	if( (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) {
@@ -1624,6 +1628,7 @@
 
 	tty->closing = 0;
 
+exit:
 	spin_lock_irqsave( &priv->dp_port_lock, flags );
 	priv->dp_write_urb_in_use = 0;
 	priv->dp_in_close = 0;
diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
--- a/drivers/usb/serial/ftdi_sio.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/serial/ftdi_sio.c	2004-09-06 17:33:19 -07:00
@@ -368,6 +368,9 @@
 	{ USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FALCOM_VID, FALCOM_TWIST_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_SUUNTO_SPORTS_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(BANDB_VID, BANDB_USOTL4_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(BANDB_VID, BANDB_USTL4_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(BANDB_VID, BANDB_USO9ML2_PID, 0, 0x3ff) },
 	{ }						/* Terminating entry */
 };
 
@@ -478,6 +481,9 @@
 	{ USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FALCOM_VID, FALCOM_TWIST_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_SUUNTO_SPORTS_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(BANDB_VID, BANDB_USOTL4_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(BANDB_VID, BANDB_USTL4_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(BANDB_VID, BANDB_USO9ML2_PID, 0x400, 0xffff) },
 	{ }						/* Terminating entry */
 };
 
@@ -595,6 +601,9 @@
 	{ USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) },
 	{ USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) },
+	{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
+	{ USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
+	{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) },
 	{ }						/* Terminating entry */
 };
 
diff -Nru a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
--- a/drivers/usb/serial/ftdi_sio.h	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/serial/ftdi_sio.h	2004-09-06 17:33:19 -07:00
@@ -225,6 +225,14 @@
  */
 #define FTDI_SUUNTO_SPORTS_PID	0xF680	/* Suunto Sports instrument */
 
+/*
+ * Definitions for B&B Electronics products.
+ */
+#define BANDB_VID		0x0856	/* B&B Electronics Vendor ID */
+#define BANDB_USOTL4_PID	0xAC01	/* USOTL4 Isolated RS-485 Converter */
+#define BANDB_USTL4_PID		0xAC02	/* USTL4 RS-485 Converter */
+#define BANDB_USO9ML2_PID	0xAC03	/* USO9ML2 Isolated RS-232 Converter */
+
 /* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
diff -Nru a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
--- a/drivers/usb/serial/ipaq.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/serial/ipaq.c	2004-09-06 17:33:19 -07:00
@@ -419,9 +419,8 @@
 	struct ipaq_private	*priv = usb_get_serial_port_data(port);
 	struct usb_serial	*serial = port->serial;
 	int			count, room;
-	struct ipaq_packet	*pkt;
+	struct ipaq_packet	*pkt, *tmp;
 	struct urb		*urb = port->write_urb;
-	struct list_head	*tmp;
 
 	if (urb->status == -EINPROGRESS) {
 		/* Should never happen */
@@ -429,9 +428,7 @@
 		return;
 	}
 	room = URBDATA_SIZE;
-	for (tmp = priv->queue.next; tmp != &priv->queue;) {
-		pkt = list_entry(tmp, struct ipaq_packet, list);
-		tmp = tmp->next;
+	list_for_each_entry_safe(pkt, tmp, &priv->queue, list) {
 		count = min(room, (int)(pkt->len - pkt->written));
 		memcpy(urb->transfer_buffer + (URBDATA_SIZE - room),
 		       pkt->data + pkt->written, count);
@@ -503,22 +500,16 @@
 static void ipaq_destroy_lists(struct usb_serial_port *port)
 {
 	struct ipaq_private	*priv = usb_get_serial_port_data(port);
-	struct list_head	*tmp;
-	struct ipaq_packet	*pkt;
+	struct ipaq_packet	*pkt, *tmp;
 
-	for (tmp = priv->queue.next; tmp != &priv->queue;) {
-		pkt = list_entry(tmp, struct ipaq_packet, list);
-		tmp = tmp->next;
+	list_for_each_entry_safe(pkt, tmp, &priv->queue, list) {
 		kfree(pkt->data);
 		kfree(pkt);
 	}
-	for (tmp = priv->freelist.next; tmp != &priv->freelist;) {
-		pkt = list_entry(tmp, struct ipaq_packet, list);
-		tmp = tmp->next;
+	list_for_each_entry_safe(pkt, tmp, &priv->freelist, list) {
 		kfree(pkt->data);
 		kfree(pkt);
 	}
-	return;
 }
 
 
diff -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
--- a/drivers/usb/serial/pl2303.c	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/serial/pl2303.c	2004-09-06 17:33:19 -07:00
@@ -55,11 +55,26 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.11"
+#define DRIVER_VERSION "v0.12"
 #define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver"
 
 static int debug;
 
+#define PL2303_CLOSING_WAIT	(30*HZ)
+
+#define PL2303_BUF_SIZE		1024
+#define PL2303_TMP_BUF_SIZE	1024
+
+static char pl2303_tmp_buf[PL2303_TMP_BUF_SIZE];
+static DECLARE_MUTEX(pl2303_tmp_buf_sem);
+
+struct pl2303_buf {
+	unsigned int	buf_size;
+	char		*buf_buf;
+	char		*buf_get;
+	char		*buf_put;
+};
+
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) },
 	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) },
@@ -134,12 +149,24 @@
 static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
 static int pl2303_write (struct usb_serial_port *port, int from_user,
 			 const unsigned char *buf, int count);
+static void pl2303_send (struct usb_serial_port *port);
+static int pl2303_write_room(struct usb_serial_port *port);
+static int pl2303_chars_in_buffer(struct usb_serial_port *port);
 static void pl2303_break_ctl(struct usb_serial_port *port,int break_state);
 static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file);
 static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file,
 			    unsigned int set, unsigned int clear);
 static int pl2303_startup (struct usb_serial *serial);
 static void pl2303_shutdown (struct usb_serial *serial);
+static struct pl2303_buf *pl2303_buf_alloc(unsigned int size);
+static void pl2303_buf_free(struct pl2303_buf *pb);
+static void pl2303_buf_clear(struct pl2303_buf *pb);
+static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb);
+static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb);
+static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
+	unsigned int count);
+static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
+	unsigned int count);
 
 
 /* All of the device info needed for the PL2303 SIO serial converter */
@@ -162,6 +189,8 @@
 	.read_bulk_callback =	pl2303_read_bulk_callback,
 	.read_int_callback =	pl2303_read_int_callback,
 	.write_bulk_callback =	pl2303_write_bulk_callback,
+	.write_room =		pl2303_write_room,
+	.chars_in_buffer =	pl2303_chars_in_buffer,
 	.attach =		pl2303_startup,
 	.shutdown =		pl2303_shutdown,
 };
@@ -174,6 +203,8 @@
 
 struct pl2303_private {
 	spinlock_t lock;
+	struct pl2303_buf *buf;
+	int write_urb_in_use;
 	wait_queue_head_t delta_msr_wait;
 	u8 line_control;
 	u8 line_status;
@@ -201,14 +232,28 @@
 	for (i = 0; i < serial->num_ports; ++i) {
 		priv = kmalloc (sizeof (struct pl2303_private), GFP_KERNEL);
 		if (!priv)
-			return -ENOMEM;
+			goto cleanup;
 		memset (priv, 0x00, sizeof (struct pl2303_private));
 		spin_lock_init(&priv->lock);
+		priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE);
+		if (priv->buf == NULL) {
+			kfree(priv);
+			goto cleanup;
+		}
 		init_waitqueue_head(&priv->delta_msr_wait);
 		priv->type = type;
 		usb_set_serial_port_data(serial->port[i], priv);
 	}
 	return 0;
+
+cleanup:
+	for (--i; i>=0; --i) {
+		priv = usb_get_serial_port_data(serial->port[i]);
+		pl2303_buf_free(priv->buf);
+		kfree(priv);
+		usb_set_serial_port_data(serial->port[i], NULL);
+	}
+	return -ENOMEM;
 }
 
 static int set_control_lines (struct usb_device *dev, u8 value)
@@ -224,40 +269,109 @@
 
 static int pl2303_write (struct usb_serial_port *port, int from_user,  const unsigned char *buf, int count)
 {
-	int result;
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
 
 	dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
 
 	if (!count)
 		return count;
 
-	if (port->write_urb->status == -EINPROGRESS) {
-		dbg("%s - already writing", __FUNCTION__);
-		return 0;
-	}
-
-	count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
 	if (from_user) {
-		if (copy_from_user (port->write_urb->transfer_buffer, buf, count))
+		if (count > PL2303_TMP_BUF_SIZE)
+			count = PL2303_TMP_BUF_SIZE;
+		down(&pl2303_tmp_buf_sem);
+		if (copy_from_user(pl2303_tmp_buf, buf, count)) {
+			up(&pl2303_tmp_buf_sem);
 			return -EFAULT;
-	} else {
-		memcpy (port->write_urb->transfer_buffer, buf, count);
+		}
+		buf = pl2303_tmp_buf;
 	}
-	
+
+	spin_lock_irqsave(&priv->lock, flags);
+	count = pl2303_buf_put(priv->buf, buf, count);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (from_user)
+		up(&pl2303_tmp_buf_sem);
+
+	pl2303_send(port);
+
+	return count;
+}
+
+static void pl2303_send(struct usb_serial_port *port)
+{
+	int count, result;
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	if (priv->write_urb_in_use) {
+		spin_unlock_irqrestore(&priv->lock, flags);
+		return;
+	}
+
+	count = pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer,
+		port->bulk_out_size);
+
+	if (count == 0) {
+		spin_unlock_irqrestore(&priv->lock, flags);
+		return;
+	}
+
+	priv->write_urb_in_use = 1;
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
 	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer);
 
 	port->write_urb->transfer_buffer_length = count;
 	port->write_urb->dev = port->serial->dev;
 	result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
-	if (result)
+	if (result) {
 		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
-	else
-		result = count;
+		priv->write_urb_in_use = 0;
+		// TODO: reschedule pl2303_send
+	}
 
-	return result;
+	schedule_work(&port->work);
 }
 
+static int pl2303_write_room(struct usb_serial_port *port)
+{
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
+	int room = 0;
+	unsigned long flags;
 
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	room = pl2303_buf_space_avail(priv->buf);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	dbg("%s - returns %d", __FUNCTION__, room);
+	return room;
+}
+
+static int pl2303_chars_in_buffer(struct usb_serial_port *port)
+{
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
+	int chars = 0;
+	unsigned long flags;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	chars = pl2303_buf_data_avail(priv->buf);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	dbg("%s - returns %d", __FUNCTION__, chars);
+	return chars;
+}
 
 static void pl2303_set_termios (struct usb_serial_port *port, struct termios *old_termios)
 {
@@ -422,7 +536,7 @@
 	}
 
 	kfree (buf);
-} 
+}
 
 static int pl2303_open (struct usb_serial_port *port, struct file *filp)
 {
@@ -461,7 +575,7 @@
 	FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
 	SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0, 1);
 	SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 1, 0);
- 
+
 	if (priv->type == HX) {
 		/* HX chip */
 		SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x44);
@@ -504,13 +618,52 @@
 
 static void pl2303_close (struct usb_serial_port *port, struct file *filp)
 {
-	struct pl2303_private *priv;
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	unsigned int c_cflag;
 	int result;
+	int bps;
+	long timeout;
+	wait_queue_t wait;						\
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
+	/* wait for data to drain from the buffer */
+	spin_lock_irqsave(&priv->lock, flags);
+	timeout = PL2303_CLOSING_WAIT;
+	init_waitqueue_entry(&wait, current);
+	add_wait_queue(&port->tty->write_wait, &wait);
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (pl2303_buf_data_avail(priv->buf) == 0
+		|| timeout == 0 || signal_pending(current)
+		|| !usb_get_intfdata(port->serial->interface))	/* disconnect */
+			break;
+		spin_unlock_irqrestore(&priv->lock, flags);
+		timeout = schedule_timeout(timeout);
+		spin_lock_irqsave(&priv->lock, flags);
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&port->tty->write_wait, &wait);
+	/* clear out any remaining data in the buffer */
+	pl2303_buf_clear(priv->buf);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* wait for characters to drain from the device */
+	/* (this is long enough for the entire 256 byte */
+	/* pl2303 hardware buffer to drain with no flow */
+	/* control for data rates of 1200 bps or more, */
+	/* for lower rates we should really know how much */
+	/* data is in the buffer to compute a delay */
+	/* that is not unnecessarily long) */
+	bps = tty_get_baud_rate(port->tty);
+	if (bps > 1200)
+		timeout = max((HZ*2560)/bps,HZ/10);
+	else
+		timeout = 2*HZ;
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(timeout);
+
 	/* shutdown our urbs */
 	dbg("%s - shutting down urbs", __FUNCTION__);
 	result = usb_unlink_urb (port->write_urb);
@@ -535,14 +688,12 @@
 		c_cflag = port->tty->termios->c_cflag;
 		if (c_cflag & HUPCL) {
 			/* drop DTR and RTS */
-			priv = usb_get_serial_port_data(port);
 			spin_lock_irqsave(&priv->lock, flags);
 			priv->line_control = 0;
 			spin_unlock_irqrestore (&priv->lock, flags);
 			set_control_lines (port->serial->dev, 0);
 		}
 	}
-
 }
 
 static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file,
@@ -672,12 +823,17 @@
 static void pl2303_shutdown (struct usb_serial *serial)
 {
 	int i;
+	struct pl2303_private *priv;
 
 	dbg("%s", __FUNCTION__);
 
 	for (i = 0; i < serial->num_ports; ++i) {
-		kfree (usb_get_serial_port_data(serial->port[i]));
-		usb_set_serial_port_data(serial->port[i], NULL);
+		priv = usb_get_serial_port_data(serial->port[i]);
+		if (priv) {
+			pl2303_buf_free(priv->buf);
+			kfree(priv);
+			usb_set_serial_port_data(serial->port[i], NULL);
+		}
 	}		
 }
 
@@ -815,11 +971,23 @@
 static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	int result;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
-	
-	if (urb->status) {
+
+	switch (urb->status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+		priv->write_urb_in_use = 0;
+		return;
+	default:
 		/* error in the urb, so we have to resubmit it */
 		dbg("%s - Overflow in write", __FUNCTION__);
 		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
@@ -828,13 +996,198 @@
 		result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
 		if (result)
 			dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n", __FUNCTION__, result);
+		else
+			return;
+	}
 
-		return;
+	priv->write_urb_in_use = 0;
+
+	/* send any buffered data */
+	pl2303_send(port);
+}
+
+
+/*
+ * pl2303_buf_alloc
+ *
+ * Allocate a circular buffer and all associated memory.
+ */
+
+static struct pl2303_buf *pl2303_buf_alloc(unsigned int size)
+{
+
+	struct pl2303_buf *pb;
+
+
+	if (size == 0)
+		return NULL;
+
+	pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
+	if (pb == NULL)
+		return NULL;
+
+	pb->buf_buf = kmalloc(size, GFP_KERNEL);
+	if (pb->buf_buf == NULL) {
+		kfree(pb);
+		return NULL;
 	}
 
-	schedule_work(&port->work);
+	pb->buf_size = size;
+	pb->buf_get = pb->buf_put = pb->buf_buf;
+
+	return pb;
+
+}
+
+
+/*
+ * pl2303_buf_free
+ *
+ * Free the buffer and all associated memory.
+ */
+
+static void pl2303_buf_free(struct pl2303_buf *pb)
+{
+	if (pb != NULL) {
+		if (pb->buf_buf != NULL)
+			kfree(pb->buf_buf);
+		kfree(pb);
+	}
 }
 
+
+/*
+ * pl2303_buf_clear
+ *
+ * Clear out all data in the circular buffer.
+ */
+
+static void pl2303_buf_clear(struct pl2303_buf *pb)
+{
+	if (pb != NULL)
+		pb->buf_get = pb->buf_put;
+		/* equivalent to a get of all data available */
+}
+
+
+/*
+ * pl2303_buf_data_avail
+ *
+ * Return the number of bytes of data available in the circular
+ * buffer.
+ */
+
+static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb)
+{
+	if (pb != NULL)
+		return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
+	else
+		return 0;
+}
+
+
+/*
+ * pl2303_buf_space_avail
+ *
+ * Return the number of bytes of space available in the circular
+ * buffer.
+ */
+
+static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb)
+{
+	if (pb != NULL)
+		return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
+	else
+		return 0;
+}
+
+
+/*
+ * pl2303_buf_put
+ *
+ * Copy data data from a user buffer and put it into the circular buffer.
+ * Restrict to the amount of space available.
+ *
+ * Return the number of bytes copied.
+ */
+
+static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
+	unsigned int count)
+{
+
+	unsigned int len;
+
+
+	if (pb == NULL)
+		return 0;
+
+	len  = pl2303_buf_space_avail(pb);
+	if (count > len)
+		count = len;
+
+	if (count == 0)
+		return 0;
+
+	len = pb->buf_buf + pb->buf_size - pb->buf_put;
+	if (count > len) {
+		memcpy(pb->buf_put, buf, len);
+		memcpy(pb->buf_buf, buf+len, count - len);
+		pb->buf_put = pb->buf_buf + count - len;
+	} else {
+		memcpy(pb->buf_put, buf, count);
+		if (count < len)
+			pb->buf_put += count;
+		else /* count == len */
+			pb->buf_put = pb->buf_buf;
+	}
+
+	return count;
+
+}
+
+
+/*
+ * pl2303_buf_get
+ *
+ * Get data from the circular buffer and copy to the given buffer.
+ * Restrict to the amount of data available.
+ *
+ * Return the number of bytes copied.
+ */
+
+static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
+	unsigned int count)
+{
+
+	unsigned int len;
+
+
+	if (pb == NULL)
+		return 0;
+
+	len = pl2303_buf_data_avail(pb);
+	if (count > len)
+		count = len;
+
+	if (count == 0)
+		return 0;
+
+	len = pb->buf_buf + pb->buf_size - pb->buf_get;
+	if (count > len) {
+		memcpy(buf, pb->buf_get, len);
+		memcpy(buf+len, pb->buf_buf, count - len);
+		pb->buf_get = pb->buf_buf + count - len;
+	} else {
+		memcpy(buf, pb->buf_get, count);
+		if (count < len)
+			pb->buf_get += count;
+		else /* count == len */
+			pb->buf_get = pb->buf_buf;
+	}
+
+	return count;
+
+}
 
 static int __init pl2303_init (void)
 {
diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
--- a/drivers/usb/storage/unusual_devs.h	2004-09-06 17:33:19 -07:00
+++ b/drivers/usb/storage/unusual_devs.h	2004-09-06 17:33:19 -07:00
@@ -68,16 +68,6 @@
 		US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0), 
 #endif
 
-/* <torsten.scherer@uni-bielefeld.de>: I don't know the name of the bridge
- * manufacturer, but I've got an external USB drive by the Revoltec company
- * that needs this. otherwise the drive is recognized as /dev/sda, but any
- * access to it blocks indefinitely.
- */
-UNUSUAL_DEV(  0x0402, 0x5621, 0x0103, 0x0103,
-		"Revoltec",
-		"USB/IDE Bridge (ATA/ATAPI)",
-		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
-
 /* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
  * Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message
  * always fails and confuses drive.
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h	2004-09-06 17:33:19 -07:00
+++ b/include/linux/usb.h	2004-09-06 17:33:19 -07:00
@@ -264,7 +264,6 @@
 	int bandwidth_isoc_reqs;	/* number of Isoc. requests */
 
 	struct dentry *usbfs_dentry;	/* usbfs dentry entry for the bus */
-	struct dentry *usbdevfs_dentry;	/* usbdevfs dentry entry for the bus */
 
 	struct class_device class_dev;	/* class device for this bus */
 	void (*release)(struct usb_bus *bus);	/* function to destroy this bus's memory */
@@ -315,7 +314,6 @@
 	
 	struct list_head filelist;
 	struct dentry *usbfs_dentry;	/* usbfs dentry entry for the device */
-	struct dentry *usbdevfs_dentry;	/* usbdevfs dentry entry for the device */
 
 	/*
 	 * Child devices - these can be either new devices
diff -Nru a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
--- a/include/linux/usbdevice_fs.h	2004-09-06 17:33:19 -07:00
+++ b/include/linux/usbdevice_fs.h	2004-09-06 17:33:19 -07:00
@@ -166,16 +166,6 @@
 	unsigned long ifclaimed;
 };
 
-/* internal methods & data */
-extern struct usb_driver usbdevfs_driver;
-extern struct file_operations usbdevfs_drivers_fops;
-extern struct file_operations usbdevfs_devices_fops;
-extern struct file_operations usbdevfs_device_file_operations;
-extern struct inode_operations usbdevfs_device_inode_operations;
-extern struct inode_operations usbdevfs_bus_inode_operations;
-extern struct file_operations usbdevfs_bus_file_operations;
-extern void usbdevfs_conn_disc_event(void);
-
 #endif /* __KERNEL__ */
 
 /* --------------------------------------------------------------------- */