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

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/04/25 23:06:05-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# include/linux/pci_ids.h
#   2004/04/25 23:06:02-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/24 23:51:05-07:00 akpm@bix.(none) 
#   Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6
#   into bix.(none):/usr/src/bk-usb
# 
# drivers/usb/core/usb.c
#   2004/04/24 23:51:02-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/23 16:41:30-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Altsetting update for USB net drivers
#   
#   The only driver under usb/net that needed any altsetting changes was
#   usbnet.  I'm not looking forward to going through all the source files
#   under usb/serial. :-(
# 
# drivers/usb/net/usbnet.c
#   2004/04/22 09:56:28-07:00 stern@rowland.harvard.edu +4 -4
#   USB: Altsetting update for USB net drivers
# 
# ChangeSet
#   2004/04/23 16:41:04-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Altsetting update for USB misc drivers
#   
#   This is the altsetting update for the drivers under usb/misc.  As you can,
#   not much was needed at all.
# 
# drivers/usb/misc/uss720.c
#   2004/04/22 09:08:37-07:00 stern@rowland.harvard.edu +1 -1
#   USB: Altsetting update for USB misc drivers
# 
# drivers/usb/misc/legousbtower.c
#   2004/04/22 09:01:26-07:00 stern@rowland.harvard.edu +1 -1
#   USB: Altsetting update for USB misc drivers
# 
# ChangeSet
#   2004/04/23 16:40:35-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Altsetting updates for USB media drivers
#   
#   This patch implements the new altsetting regime for the drivers under
#   usb/media.  Not much needed to be changed.  I'm unable to test any of the
#   changes, but at least they compile all right (except that I didn't even
#   try to compile the pwc driver since it's marked BROKEN).
#   
#   The stv680 and w9968cf drivers still include an assumption that they are
#   bound to interface number 0.  Since that the drivers are fairly tightly
#   linked to a specific kind of device I didn't try to change those
#   assumptions, but maybe they should be changed.
# 
# drivers/usb/media/vicam.c
#   2004/04/22 04:41:49-07:00 stern@rowland.harvard.edu +1 -1
#   USB: Altsetting updates for USB media drivers
# 
# drivers/usb/media/ultracam.c
#   2004/04/21 09:26:45-07:00 stern@rowland.harvard.edu +4 -3
#   USB: Altsetting updates for USB media drivers
# 
# drivers/usb/media/se401.c
#   2004/04/21 09:21:19-07:00 stern@rowland.harvard.edu +1 -1
#   USB: Altsetting updates for USB media drivers
# 
# drivers/usb/media/pwc-if.c
#   2004/04/21 09:18:47-07:00 stern@rowland.harvard.edu +5 -2
#   USB: Altsetting updates for USB media drivers
# 
# drivers/usb/media/ov511.c
#   2004/04/22 04:40:56-07:00 stern@rowland.harvard.edu +11 -3
#   USB: Altsetting updates for USB media drivers
# 
# drivers/usb/media/konicawc.c
#   2004/04/21 09:41:57-07:00 stern@rowland.harvard.edu +12 -5
#   USB: Altsetting updates for USB media drivers
# 
# drivers/usb/media/ibmcam.c
#   2004/04/21 09:32:00-07:00 stern@rowland.harvard.edu +5 -4
#   USB: Altsetting updates for USB media drivers
# 
# ChangeSet
#   2004/04/23 16:40:06-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Cosmetic improvements for the UHCI driver
#   
#   This patch makes a few minor improvements to the appearance of the UHCI
#   driver.  Please apply.
# 
# drivers/usb/host/uhci-hcd.h
#   2004/04/19 04:05:56-07:00 stern@rowland.harvard.edu +7 -7
#   USB: Cosmetic improvements for the UHCI driver
# 
# drivers/usb/host/uhci-hcd.c
#   2004/04/14 03:19:54-07:00 stern@rowland.harvard.edu +10 -10
#   USB: Cosmetic improvements for the UHCI driver
# 
# ChangeSet
#   2004/04/23 16:39:38-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Ignore URB_NO_INTERRUPT flag in UHCI
#   
#   Following a suggestion of David Brownell's I have decided to remove
#   support for the URB_NO_INTERRUPT flag in the UHCI driver.  The overall
#   effect of the flag is to reduce the number of interrupts, thereby
#   improving throughput somewhat while increasing the duration of the
#   remaining IRQ handlers quite a lot (i.e., increasing interrupt variance).
#   So I think we're better off without it.  Mind you, this is all in the
#   absence of any firm measurements.
#   
#   A common case where this will come up is during usb-storage bulk
#   transfers.  Such transfers are generally divided into scatter-gather
#   components each corresponding to a single URB and transferring one memory
#   page (4 KB).  While generating an interrupt for each one is a little
#   faster than ideal -- about every 3 ms -- it's better than waiting until 64
#   KB has been transferred and there are 1024 individual TDs to clean up
#   during the IRQ.
# 
# drivers/usb/host/uhci-hcd.c
#   2004/04/16 04:02:37-07:00 stern@rowland.harvard.edu +7 -3
#   USB: Ignore URB_NO_INTERRUPT flag in UHCI
# 
# ChangeSet
#   2004/04/23 16:20:26-07:00 baldrick@free.fr 
#   [PATCH] USB usbfs: drop pointless racy check
#   
#   The check of interface->dev.driver requires a lock to be taken
#   to protect against driver binding changes.  But in fact I think it
#   is better just to drop the test.  The result is that the caller is
#   required to claim an interface before changing the altsetting,
#   which is consistent with the other routines that operate on
#   interfaces.
#   
#    devio.c |    6 ++----
#    1 files changed, 2 insertions(+), 4 deletions(-)
# 
# drivers/usb/core/devio.c
#   2004/04/14 05:18:37-07:00 baldrick@free.fr +2 -4
#   USB usbfs: drop pointless racy check
# 
# ChangeSet
#   2004/04/23 16:20:07-07:00 baldrick@free.fr 
#   [PATCH] USB usbfs: missing lock in proc_getdriver
#   
#   Hi Oliver,
#   
#   > I expect it to rarely matter, but it might matter now and then. It's
#   > just a question of hygiene. If you are using a temporary buffer I'd
#   > like to see it used to full advantage. So either drop the lock or do
#   > a direct copy. I'd prefer the first option your patch implemented.
#   
#   I agree.  Greg, please consider applying the updated patch:
#   
#   
#   
#   Protect against driver binding changes while reading the driver name.
# 
# drivers/usb/core/devio.c
#   2004/04/14 07:03:12-07:00 baldrick@free.fr +6 -4
#   USB usbfs: missing lock in proc_getdriver
# 
# ChangeSet
#   2004/04/23 16:19:43-07:00 baldrick@free.fr 
#   [PATCH] USB usbfs: destroy submitted urbs only on the disconnected interface
#   
#   The remaining three patches contain miscellaneous fixes to usbfs.
#   This one fixes up the disconnect callback to only shoot down urbs
#   on the disconnected interface, and not on all interfaces.  It also adds
#   a sanity check (this check is pointless because the interface could
#   never have been claimed in the first place if it failed, but I feel better
#   having it there).
#   
#    devio.c |    6 ++++--
#    1 files changed, 4 insertions(+), 2 deletions(-)
# 
# drivers/usb/core/devio.c
#   2004/04/14 05:18:20-07:00 baldrick@free.fr +4 -2
#   USB usbfs: destroy submitted urbs only on the disconnected interface
# 
# ChangeSet
#   2004/04/23 16:19:14-07:00 baldrick@free.fr 
#   [PATCH] USB usbfs: fix up releaseintf
#   
#   The semaphore is now taken in the callers.
#   
#    devio.c |    2 --
#    1 files changed, 2 deletions(-)
# 
# drivers/usb/core/devio.c
#   2004/04/14 05:18:08-07:00 baldrick@free.fr +0 -2
#   USB usbfs: fix up releaseintf
# 
# ChangeSet
#   2004/04/23 16:18:50-07:00 baldrick@free.fr 
#   [PATCH] USB usbfs: fix up proc_ioctl
#   
#   The semaphore is now taken in the caller.
#   
#    devio.c |    2 --
#    1 files changed, 2 deletions(-)
# 
# drivers/usb/core/devio.c
#   2004/04/14 05:17:56-07:00 baldrick@free.fr +0 -2
#   USB usbfs: fix up proc_ioctl
# 
# ChangeSet
#   2004/04/23 16:18:24-07:00 baldrick@free.fr 
#   [PATCH] USB usbfs: fix up proc_setconfig
#   
#   The semaphore is now taken in the caller.
#   
#    devio.c |    2 --
#    1 files changed, 2 deletions(-)
# 
# drivers/usb/core/devio.c
#   2004/04/14 05:17:46-07:00 baldrick@free.fr +0 -2
#   USB usbfs: fix up proc_setconfig
# 
# ChangeSet
#   2004/04/23 16:17:59-07:00 baldrick@free.fr 
#   [PATCH] USB usbfs: remove obsolete comment from proc_resetdevice
#   
#    devio.c |    3 ---
#    1 files changed, 3 deletions(-)
# 
# drivers/usb/core/devio.c
#   2004/04/14 05:17:37-07:00 baldrick@free.fr +0 -3
#   USB usbfs: remove obsolete comment from proc_resetdevice
# 
# ChangeSet
#   2004/04/23 16:17:35-07:00 baldrick@free.fr 
#   [PATCH] USB usbfs: replace the per-file semaphore with the per-device semaphore
#   
#    devio.c		|   43 +++++++++++++++++++++++--------------------
#    usbdevice_fs.h	|    1 -
#    2 files changed, 23 insertions(+), 21 deletions(-)
# 
# include/linux/usbdevice_fs.h
#   2004/04/14 05:34:00-07:00 baldrick@free.fr +0 -1
#   USB usbfs: replace the per-file semaphore with the per-device semaphore
# 
# drivers/usb/core/devio.c
#   2004/04/14 05:17:29-07:00 baldrick@free.fr +23 -20
#   USB usbfs: replace the per-file semaphore with the per-device semaphore
# 
# ChangeSet
#   2004/04/23 16:17:09-07:00 baldrick@free.fr 
#   [PATCH] USB usbfs: take a reference to the usb device
#   
#   Hi Greg, this is the first of a series of patches that replace the
#   per-file semaphore ps->devsem with the per-device semaphore
#   ps->dev->serialize.  The role of devsem was to protect against
#   device disconnection.  This can be done equally well using
#   ps->dev->serialize.  On the other hand, ps->dev->serialize
#   protects against configuration and other changes, and has
#   already been introduced into usbfs in several places.  Using
#   just one semaphore simplifies the code and removes some
#   remaining race conditions.  It should also fix the oopses some
#   people have been seeing.  In this first patch, a reference is
#   taken to the usb device as long as the usbfs file is open.  That
#   way we can use ps->dev->serialize for as long as ps exists.
#   
#    devio.c |   27 ++++++++++++++++-----------
#    inode.c |    3 ---
#    2 files changed, 16 insertions(+), 14 deletions(-)
# 
# drivers/usb/core/inode.c
#   2004/04/14 05:15:29-07:00 baldrick@free.fr +0 -3
#   USB usbfs: take a reference to the usb device
# 
# drivers/usb/core/devio.c
#   2004/04/14 05:15:29-07:00 baldrick@free.fr +16 -11
#   USB usbfs: take a reference to the usb device
# 
# ChangeSet
#   2004/04/23 15:45:24-07:00 david-b@pacbell.net 
#   [PATCH] USB: khubd fixes
#   
#   This goes on top of the other enumeration patch I just sent,
#   to handle some dubious and/or broken hub configurations better.
#   
#   
#   Make khubd handle some cases better:
#   
#    - Track power budget for bus-powered hubs.  This version only warns
#      when the budgets are exceeded.  Eventually, the budgets should help
#      prevent such errors.
#   
#    - Rejects illegal USB setup:  two consecutive bus powered hubs
#      would exceed the voltage drop budget, causing much flakiness.
#   
#    - For hosts with high speed hubs, warn when devices are hooked up
#      to full speed hubs if they'd be faster on a high speed one.
#   
#    - For hubs that don't do power switching, don't try to use it
#   
#    - For hubs that aren't self-powered, don't report local power status
# 
# drivers/usb/core/hub.h
#   2004/04/19 08:29:02-07:00 david-b@pacbell.net +2 -0
#   USB: khubd fixes
# 
# drivers/usb/core/hub.c
#   2004/04/20 20:44:45-07:00 david-b@pacbell.net +143 -15
#   USB: khubd fixes
# 
# ChangeSet
#   2004/04/23 15:44:57-07:00 david-b@pacbell.net 
#   [PATCH] USB: re-factor enumeration logic
#   
#   This is an update to some patches from the December/January
#   timeframe, which will help sort out some of the mess for
#   drivers that need to use the reset logic.  It's one of the
#   last significant patches in my gadget-2.6 tree that haven't
#   yet been merged into the main kernel tree.
#   
#   
#   More refactoring of the enumeration code paths:
#   
#    * The first half of usb_new_device() becomes the second half of a new
#      hub_port_init() routine (resets, sets address, gets descriptor)
#   
#    * The middle chunk of hub_port_connect_change() becomes the first half
#      of that new hub_port_init() routine.
#   
#    * Khubd uses that new routine in hub_port_connect_change().
#   
#    * Now usb_new_device() cleans up better after faults, and has
#      a more useful locking policy (caller owns dev->serialize).
#   
#    * Has related minor cleanups including commenting some of
#      the curious request sequences coming from khubd.
#   
#   Refactoring means a lot of the current usb_reset_device() logic won't
#   need to stay an imperfect clone of the enumeration code ... soon, it
#   can just call hub_port_init().
#   
#   Even without touching usb_reset_device(), this eliminates a deadlock.
#   Previously, address0_sem was used both during probe and during reset,
#   so probe routines can't implement DFU firmware download (involves a
#   reset; DFU also uncovers other problems) or safely recover from probe
#   faults by resetting (usb-storage can try that).  Now that lock is no
#   longer held during probe(); so those deadlocks are gone.  (And some
#   drivers, like at76c503, can start to remove ugly workarounds.)
# 
# drivers/usb/core/usb.c
#   2004/04/21 03:46:29-07:00 david-b@pacbell.net +13 -79
#   USB: re-factor enumeration logic
# 
# drivers/usb/core/hub.c
#   2004/04/21 03:46:29-07:00 david-b@pacbell.net +215 -72
#   USB: re-factor enumeration logic
# 
# drivers/usb/core/hcd.c
#   2004/04/21 03:46:29-07:00 david-b@pacbell.net +12 -0
#   USB: re-factor enumeration logic
# 
# ChangeSet
#   2004/04/23 15:44:32-07:00 david-b@pacbell.net 
#   [PATCH] USB: usbtest, smp unlink modes
#   
#   Handle some SMP-visible unlink states better.
# 
# drivers/usb/misc/usbtest.c
#   2004/04/14 20:23:11-07:00 david-b@pacbell.net +3 -3
#   USB: usbtest, smp unlink modes
# 
# ChangeSet
#   2004/04/23 14:50:19-07:00 greg@kroah.com 
#   [PATCH] USB: fix devio compiler warnings created by previous patch.
# 
# drivers/usb/core/devio.c
#   2004/04/23 07:33:30-07:00 greg@kroah.com +2 -2
#   USB: fix devio compiler warnings created by previous patch.
# 
# ChangeSet
#   2004/04/23 14:49:56-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Eliminate dead code from the UHCI driver
#   
#   I'm not sure what this piece of code is doing in the UHCI driver.  It
#   looks like someone envisioned queuing several URBs for the same endpoint
#   simultaneously.  Anyway, the driver can't do that and this code can never
#   run.
# 
# drivers/usb/host/uhci-hcd.c
#   2004/04/16 04:02:37-07:00 stern@rowland.harvard.edu +1 -11
#   USB: Eliminate dead code from the UHCI driver
# 
# ChangeSet
#   2004/04/23 14:49:33-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Implement endpoint_disable() for UHCI
#   
#   This patch implements the endpoint_disable method for the UHCI driver, as
#   you requested a while back.  It guarantees that during unbinding events
#   (disconnect, configuration change, rmmod) the UHCI driver will have
#   finished using every URB for the interface being unbound.  It doesn't
#   quite guarantee that the completion handlers will have finished running,
#   but it would take a pretty unlikely race to violate that assumption.  (I
#   think it's the same with the OHCI and EHCI drivers.)
#   
#   Despite the patch numbering this one applies _after_ as249, which is a
#   more important bugfix.
# 
# drivers/usb/host/uhci-hcd.h
#   2004/04/19 04:05:56-07:00 stern@rowland.harvard.edu +2 -0
#   USB: Implement endpoint_disable() for UHCI
# 
# drivers/usb/host/uhci-hcd.c
#   2004/04/14 03:19:54-07:00 stern@rowland.harvard.edu +49 -0
#   USB: Implement endpoint_disable() for UHCI
# 
# ChangeSet
#   2004/04/23 14:49:10-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: unusual_devs.h update
#   
#   On Tue, 20 Apr 2004, Damian Ivereigh wrote:
#   
#   > Here is the output of dmesg when plugging in an IBM USB MemKey
#   >
#   > usb-storage: This device (0a16,8888,0100 S 06 P 50) has unneeded SubClass and Protocol entries in unusual_devs.h
#   >    Please send a copy of this message to <linux-usb-devel@lists.sourceforge.net>
#   
#   Thank you for sending this in.  Greg and Pete, here's the patch.
# 
# drivers/usb/storage/unusual_devs.h
#   2004/04/19 05:11:29-07:00 stern@rowland.harvard.edu +1 -1
#   USB: unusual_devs.h update
# 
# ChangeSet
#   2004/04/23 14:48:47-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Remove unusual_devs entries for Minolta DiMAGE 7, 7Hi
#   
#   It looks safe to conclude that the unusual_devs.h entries for the Minolta
#   DiMAGE 7x cameras aren't needed.  (Michael has tested the 7Hi and it's
#   definitely unnecessary.)  The two other DiMAGE entries probably aren't
#   needed either, but we don't have any evidence of that so I'm leaving them.
# 
# drivers/usb/storage/unusual_devs.h
#   2004/04/16 04:37:06-07:00 stern@rowland.harvard.edu +0 -16
#   USB: Remove unusual_devs entries for Minolta DiMAGE 7, 7Hi
# 
# ChangeSet
#   2004/04/23 14:48:28-07:00 david-b@pacbell.net 
#   [PATCH] USB: root hubs can report remote wakeup feature
#   
#   The patch lets HCDs report the root hub remote wakeup feature to usbcore
#   through config descriptors, and lets usbcore say whether or not remote
#   wakeup (of host from sleep, by devices) should be enabled.
#   
#   Both OHCI and UHCI HCDs have some remote wakeup support already; I'm not
#   too sure how well it works.  Given (separate) patches, their root hubs
#   can start to act more like other hubs in this area too.  That'll make
#   it easier to start using USB suspend mode.
# 
# drivers/usb/core/hcd.h
#   2004/04/13 11:48:39-07:00 david-b@pacbell.net +10 -1
#   USB: root hubs can report remote wakeup feature
# 
# drivers/usb/core/hcd.c
#   2004/04/13 11:33:31-07:00 david-b@pacbell.net +28 -11
#   USB: root hubs can report remote wakeup feature
# 
# ChangeSet
#   2004/04/23 14:48:02-07:00 david-b@pacbell.net 
#   [PATCH] USB: fix usbfs iso interval problem
#   
#   In 2.6, ISO transfers on USB require a value for urb->interval ... which
#   usbfs didn't provide (until this patch), or let user mode drivers specify.
#   
#   This patch initializes the urb->interval from the endpoint's descriptor,
#   so ISO transfers should now work from userspace.  It also fixes a related
#   problem for interrupt transfers.
# 
# drivers/usb/core/devio.c
#   2004/04/14 13:36:53-07:00 david-b@pacbell.net +7 -1
#   USB: fix usbfs iso interval problem
# 
# ChangeSet
#   2004/04/23 12:58:38-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# CREDITS
#   2004/04/23 12:58:35-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/19 19:45:10-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# include/linux/pci_ids.h
#   2004/04/19 19:45:07-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# MAINTAINERS
#   2004/04/19 19:45:07-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# CREDITS
#   2004/04/19 19:45:06-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/07 20:17:13-07:00 akpm@bix.(none) 
#   Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6
#   into bix.(none):/usr/src/bk-usb
# 
# drivers/usb/core/message.c
#   2004/04/07 20:17:11-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/02 11:35:28-08:00 akpm@bix.(none) 
#   Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6
#   into bix.(none):/usr/src/bk-usb
# 
# include/linux/pci_ids.h
#   2004/04/02 11:35:25-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/01 15:16:14-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# CREDITS
#   2004/04/01 15:16:11-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/31 19:24:39-08:00 akpm@bix.(none) 
#   Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6
#   into bix.(none):/usr/src/bk-usb
# 
# include/linux/usb.h
#   2004/03/31 19:24:37-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/core/usb.c
#   2004/03/31 19:24:37-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/core/message.c
#   2004/03/31 19:24:37-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/ppc64/defconfig
#   2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/ppc64/configs/pSeries_defconfig
#   2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/ppc/defconfig
#   2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/ppc/configs/pmac_defconfig
#   2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/ppc/configs/common_defconfig
#   2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/parisc/configs/c3000_defconfig
#   2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/ia64/defconfig
#   2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/ia64/configs/zx1_defconfig
#   2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/ia64/configs/generic_defconfig
#   2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/arm/configs/neponset_defconfig
#   2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/30 20:18:36-08:00 akpm@bix.(none) 
#   Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6
#   into bix.(none):/usr/src/bk-usb
# 
# arch/ppc64/defconfig
#   2004/03/30 20:18:33-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/ppc64/configs/pSeries_defconfig
#   2004/03/30 20:18:33-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/ppc/defconfig
#   2004/03/30 20:18:33-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/ppc/configs/pmac_defconfig
#   2004/03/30 20:18:33-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/ppc/configs/common_defconfig
#   2004/03/30 20:18:33-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/parisc/configs/c3000_defconfig
#   2004/03/30 20:18:33-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/ia64/defconfig
#   2004/03/30 20:18:33-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/ia64/configs/zx1_defconfig
#   2004/03/30 20:18:33-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/ia64/configs/generic_defconfig
#   2004/03/30 20:18:33-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/arm/configs/neponset_defconfig
#   2004/03/30 20:18:32-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/30 12:09:32-08:00 akpm@bix.(none) 
#   Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6
#   into bix.(none):/usr/src/bk-usb
# 
# include/linux/usb.h
#   2004/03/30 12:09:29-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/core/usb.c
#   2004/03/30 12:09:29-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/core/message.c
#   2004/03/30 12:09:29-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/29 18:05:43-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# MAINTAINERS
#   2004/03/29 18:05:41-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/29 13:51:58-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# CREDITS
#   2004/03/29 13:51:56-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/28 12:29:41-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# drivers/usb/core/message.c
#   2004/03/28 12:29:38-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/27 02:28:18-08:00 akpm@bix.(none) 
#   Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6
#   into bix.(none):/usr/src/bk-usb
# 
# drivers/usb/input/wacom.c
#   2004/03/27 02:28:16-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/26 12:24:49-08:00 akpm@bix.(none) 
#   Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6
#   into bix.(none):/usr/src/bk-usb
# 
# include/linux/usb_gadget.h
#   2004/03/26 12:24:46-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/core/usb.c
#   2004/03/26 12:24:46-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/20 13:26:55-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# CREDITS
#   2004/03/20 13:26:53-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/16 21:53:42-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# drivers/usb/input/wacom.c
#   2004/03/16 21:53:39-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/input/hid-core.c
#   2004/03/16 21:53:39-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/16 12:59:58-08:00 akpm@bix.(none) 
#   Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6
#   into bix.(none):/usr/src/bk-usb
# 
# include/linux/usb_gadget.h
#   2004/03/16 12:59:47-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# include/linux/usb.h
#   2004/03/16 12:59:47-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/core/usb.c
#   2004/03/16 12:59:46-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# MAINTAINERS
#   2004/03/16 12:59:46-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# CREDITS
#   2004/03/16 12:59:46-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/16 12:58:57-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# drivers/usb/input/wacom.c
#   2004/03/16 12:58:47-08:00 akpm@bix.(none) +0 -4
#   Auto merged
# 
# drivers/usb/input/hid-core.c
#   2004/03/16 12:58:47-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# CREDITS
#   2004/03/16 12:58:46-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/14 11:03:00-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# include/linux/usb_gadget.h
#   2004/03/14 11:02:47-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# include/linux/usb.h
#   2004/03/14 11:02:47-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/core/usb.c
#   2004/03/14 11:02:47-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# MAINTAINERS
#   2004/03/14 11:02:47-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/12 10:57:17-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb
# 
# MAINTAINERS
#   2004/03/12 10:57:02-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# CREDITS
#   2004/03/12 10:57:01-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
--- a/drivers/usb/core/devio.c	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/core/devio.c	Sun Apr 25 23:06:52 2004
@@ -60,6 +60,11 @@
 	struct urb *urb;
 };
 
+static inline int connected (struct usb_device *dev)
+{
+	return dev->state != USB_STATE_NOTATTACHED;
+}
+
 static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
 {
 	loff_t ret;
@@ -87,14 +92,15 @@
 static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
 	struct dev_state *ps = (struct dev_state *)file->private_data;
+	struct usb_device *dev = ps->dev;
 	ssize_t ret = 0;
 	unsigned len;
 	loff_t pos;
 	int i;
 
 	pos = *ppos;
-	down_read(&ps->devsem);
-	if (!ps->dev) {
+	down(&dev->serialize);
+	if (!connected(dev)) {
 		ret = -ENODEV;
 		goto err;
 	} else if (pos < 0) {
@@ -106,7 +112,7 @@
 		len = sizeof(struct usb_device_descriptor) - pos;
 		if (len > nbytes)
 			len = nbytes;
-		if (copy_to_user(buf, ((char *)&ps->dev->descriptor) + pos, len)) {
+		if (copy_to_user(buf, ((char *)&dev->descriptor) + pos, len)) {
 			ret = -EFAULT;
 			goto err;
 		}
@@ -118,9 +124,9 @@
 	}
 
 	pos = sizeof(struct usb_device_descriptor);
-	for (i = 0; nbytes && i < ps->dev->descriptor.bNumConfigurations; i++) {
+	for (i = 0; nbytes && i < dev->descriptor.bNumConfigurations; i++) {
 		struct usb_config_descriptor *config =
-			(struct usb_config_descriptor *)ps->dev->rawdescriptors[i];
+			(struct usb_config_descriptor *)dev->rawdescriptors[i];
 		unsigned int length = le16_to_cpu(config->wTotalLength);
 
 		if (*ppos < pos + length) {
@@ -128,7 +134,7 @@
 			/* The descriptor may claim to be longer than it
 			 * really is.  Here is the actual allocated length. */
 			unsigned alloclen =
-				ps->dev->config[i].desc.wTotalLength;
+				dev->config[i].desc.wTotalLength;
 
 			len = length - (*ppos - pos);
 			if (len > nbytes)
@@ -138,7 +144,7 @@
 			if (alloclen > (*ppos - pos)) {
 				alloclen -= (*ppos - pos);
 				if (copy_to_user(buf,
-				    ps->dev->rawdescriptors[i] + (*ppos - pos),
+				    dev->rawdescriptors[i] + (*ppos - pos),
 				    min(len, alloclen))) {
 					ret = -EFAULT;
 					goto err;
@@ -155,7 +161,7 @@
 	}
 
 err:
-	up_read(&ps->devsem);
+	up(&dev->serialize);
 	return ret;
 }
 
@@ -335,6 +341,7 @@
 static void driver_disconnect(struct usb_interface *intf)
 {
 	struct dev_state *ps = usb_get_intfdata (intf);
+	unsigned int ifnum = intf->altsetting->desc.bInterfaceNumber;
 
 	if (!ps)
 		return;
@@ -343,13 +350,12 @@
 	 * all pending I/O requests; 2.6 does that.
 	 */
 
-	/* prevent new I/O requests */
-	ps->dev = 0;
-	clear_bit(intf->cur_altsetting->desc.bInterfaceNumber, &ps->ifclaimed);
+	if (ifnum < 8*sizeof(ps->ifclaimed))
+		clear_bit(ifnum, &ps->ifclaimed);
 	usb_set_intfdata (intf, NULL);
 
 	/* force async requests to complete */
-	destroy_all_async (ps);
+	destroy_async_on_interface(ps, ifnum);
 }
 
 struct usb_driver usbdevfs_driver = {
@@ -365,7 +371,7 @@
 	struct usb_interface *iface;
 	int err;
 
-	if (intf >= 8*sizeof(ps->ifclaimed) || !dev
+	if (intf >= 8*sizeof(ps->ifclaimed)
 			|| intf >= dev->actconfig->desc.bNumInterfaces)
 		return -EINVAL;
 	/* already claimed */
@@ -395,7 +401,6 @@
 		return -EINVAL;
 	err = -EINVAL;
 	dev = ps->dev;
-	down(&dev->serialize);
 	/* lock against other changes to driver bindings */
 	down_write(&usb_bus_type.subsys.rwsem);
 	if (test_and_clear_bit(intf, &ps->ifclaimed)) {
@@ -404,7 +409,6 @@
 		err = 0;
 	}
 	up_write(&usb_bus_type.subsys.rwsem);
-	up(&dev->serialize);
 	return err;
 }
 
@@ -506,7 +510,7 @@
 
 	lock_kernel();
 	ret = -ENOENT;
-	dev = inode->u.generic_ip;
+	dev = usb_get_dev(inode->u.generic_ip);
 	if (!dev) {
 		kfree(ps);
 		goto out;
@@ -518,7 +522,6 @@
 	INIT_LIST_HEAD(&ps->async_pending);
 	INIT_LIST_HEAD(&ps->async_completed);
 	init_waitqueue_head(&ps->wait);
-	init_rwsem(&ps->devsem);
 	ps->discsignr = 0;
 	ps->disctask = current;
 	ps->disccontext = NULL;
@@ -535,18 +538,21 @@
 static int usbdev_release(struct inode *inode, struct file *file)
 {
 	struct dev_state *ps = (struct dev_state *)file->private_data;
+	struct usb_device *dev = ps->dev;
 	unsigned int i;
 
-	lock_kernel();
+	down(&dev->serialize);
 	list_del_init(&ps->list);
 
-	if (ps->dev) {
+	if (connected(dev)) {
 		for (i = 0; ps->ifclaimed && i < 8*sizeof(ps->ifclaimed); i++)
 			if (test_bit(i, &ps->ifclaimed))
 				releaseintf(ps, i);
+		destroy_all_async(ps);
 	}
-	unlock_kernel();
-	destroy_all_async(ps);
+	up(&dev->serialize);
+	usb_put_dev(dev);
+	ps->dev = NULL;
 	kfree(ps);
         return 0;
 }
@@ -702,13 +708,15 @@
 		return -EFAULT;
 	if ((ret = findintfif(ps->dev, gd.interface)) < 0)
 		return ret;
+	down_read(&usb_bus_type.subsys.rwsem);
 	interface = ps->dev->actconfig->interface[ret];
-	if (!interface->dev.driver)
+	if (!interface || !interface->dev.driver) {
+		up_read(&usb_bus_type.subsys.rwsem);
 		return -ENODATA;
+	}
 	strncpy(gd.driver, interface->dev.driver->name, sizeof(gd.driver));
-	if (copy_to_user(arg, &gd, sizeof(gd)))
-		return -EFAULT;
-	return 0;
+	up_read(&usb_bus_type.subsys.rwsem);
+	return copy_to_user(arg, &gd, sizeof(gd)) ? -EFAULT : 0;
 }
 
 static int proc_connectinfo(struct dev_state *ps, void __user *arg)
@@ -724,9 +732,6 @@
 
 static int proc_resetdevice(struct dev_state *ps)
 {
-	/* FIXME when usb_reset_device() is fixed we'll need to grab
-	 * ps->dev->serialize before calling it.
-	 */
 	return usb_reset_device(ps->dev);
 
 }
@@ -742,10 +747,8 @@
 	if ((ret = findintfif(ps->dev, setintf.interface)) < 0)
 		return ret;
 	interface = ps->dev->actconfig->interface[ret];
-	if (interface->dev.driver) {
-		if ((ret = checkintf(ps, ret)))
-			return ret;
-	}
+	if ((ret = checkintf(ps, ret)))
+		return ret;
 	if (usb_set_interface(ps->dev, setintf.interface, setintf.altsetting))
 		return -EINVAL;
 	return 0;
@@ -760,7 +763,6 @@
 	if (get_user(u, (unsigned int __user *)arg))
 		return -EFAULT;
 
-	down(&ps->dev->serialize);
  	actconfig = ps->dev->actconfig;
  
  	/* Don't touch the device if any interfaces are claimed.
@@ -796,7 +798,6 @@
 		else
 			status = usb_set_configuration(ps->dev, u);
 	}
-	up(&ps->dev->serialize);
 
 	return status;
 }
@@ -873,6 +874,9 @@
 		/* arbitrary limit */
 		if (uurb.number_of_packets < 1 || uurb.number_of_packets > 128)
 			return -EINVAL;
+		if (!(ep_desc = usb_epnum_to_ep_desc(ps->dev, uurb.endpoint)))
+			return -ENOENT;
+		interval = 1 << min (15, ep_desc->bInterval - 1);
 		isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb.number_of_packets;
 		if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
 			return -ENOMEM;
@@ -898,7 +902,10 @@
 		uurb.number_of_packets = 0;
 		if (!(ep_desc = usb_epnum_to_ep_desc(ps->dev, uurb.endpoint)))
 			return -ENOENT;
-		interval = ep_desc->bInterval;
+		if (ps->dev->speed == USB_SPEED_HIGH)
+			interval = 1 << min (15, ep_desc->bInterval - 1);
+		else
+			interval = ep_desc->bInterval;
 		if (uurb.buffer_length > 16384)
 			return -EINVAL;
 		if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
@@ -1012,18 +1019,19 @@
         DECLARE_WAITQUEUE(wait, current);
 	struct async *as = NULL;
 	void __user *addr;
+	struct usb_device *dev = ps->dev;
 	int ret;
 
 	add_wait_queue(&ps->wait, &wait);
-	while (ps->dev) {
+	while (connected(dev)) {
 		__set_current_state(TASK_INTERRUPTIBLE);
 		if ((as = async_getcompleted(ps)))
 			break;
 		if (signal_pending(current))
 			break;
-		up_read(&ps->devsem);
+		up(&dev->serialize);
 		schedule();
-		down_read(&ps->devsem);
+		down(&dev->serialize);
 	}
 	remove_wait_queue(&ps->wait, &wait);
 	set_current_state(TASK_RUNNING);
@@ -1125,13 +1133,12 @@
 		}
 	}
 
-	if (!ps->dev) {
+	if (!connected(ps->dev)) {
 		if (buf)
 			kfree(buf);
 		return -ENODEV;
 	}
 
-	down(&ps->dev->serialize);
 	if (ps->dev->state != USB_STATE_CONFIGURED)
 		retval = -ENODEV;
 	else if (!(ifp = usb_ifnum_to_if (ps->dev, ctrl.ifno)))
@@ -1169,7 +1176,6 @@
 		}
 		up_read(&usb_bus_type.subsys.rwsem);
 	}
-	up(&ps->dev->serialize);
 
 	/* cleanup and return */
 	if (retval >= 0
@@ -1190,13 +1196,14 @@
 static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct dev_state *ps = (struct dev_state *)file->private_data;
+	struct usb_device *dev = ps->dev;
 	int ret = -ENOTTY;
 
 	if (!(file->f_mode & FMODE_WRITE))
 		return -EPERM;
-	down_read(&ps->devsem);
-	if (!ps->dev) {
-		up_read(&ps->devsem);
+	down(&dev->serialize);
+	if (!connected(dev)) {
+		up(&dev->serialize);
 		return -ENODEV;
 	}
 	switch (cmd) {
@@ -1278,7 +1285,7 @@
 		ret = proc_ioctl(ps, (void __user *) arg);
 		break;
 	}
-	up_read(&ps->devsem);
+	up(&dev->serialize);
 	if (ret >= 0)
 		inode->i_atime = CURRENT_TIME;
 	return ret;
@@ -1293,7 +1300,7 @@
 	poll_wait(file, &ps->wait, wait);
 	if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed))
 		mask |= POLLOUT | POLLWRNORM;
-	if (!ps->dev)
+	if (!connected(ps->dev))
 		mask |= POLLERR | POLLHUP;
 	return mask;
 }
diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
--- a/drivers/usb/core/hcd.c	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/core/hcd.c	Sun Apr 25 23:06:52 2004
@@ -171,10 +171,10 @@
 	0x01,       /*  __u8  bNumInterfaces; (1) */
 	0x01,       /*  __u8  bConfigurationValue; */
 	0x00,       /*  __u8  iConfiguration; */
-	0x40,       /*  __u8  bmAttributes; 
-				 Bit 7: Bus-powered,
+	0xc0,       /*  __u8  bmAttributes; 
+				 Bit 7: must be set,
 				     6: Self-powered,
-				     5 Remote-wakwup,
+				     5: Remote wakeup,
 				     4..0: resvd */
 	0x00,       /*  __u8  MaxPower; */
       
@@ -218,10 +218,10 @@
 	0x01,       /*  __u8  bNumInterfaces; (1) */
 	0x01,       /*  __u8  bConfigurationValue; */
 	0x00,       /*  __u8  iConfiguration; */
-	0x40,       /*  __u8  bmAttributes; 
-				 Bit 7: Bus-powered,
+	0xc0,       /*  __u8  bmAttributes; 
+				 Bit 7: must be set,
 				     6: Self-powered,
-				     5 Remote-wakwup,
+				     5: Remote wakeup,
 				     4..0: resvd */
 	0x00,       /*  __u8  MaxPower; */
       
@@ -324,13 +324,15 @@
 /* Root hub control transfers execute synchronously */
 static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
 {
-	struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet;
+	struct usb_ctrlrequest *cmd;
  	u16		typeReq, wValue, wIndex, wLength;
 	const u8	*bufp = 0;
 	u8		*ubuf = urb->transfer_buffer;
 	int		len = 0;
+	int		patch_wakeup = 0;
 	unsigned long	flags;
 
+	cmd = (struct usb_ctrlrequest *) urb->setup_packet;
 	typeReq  = (cmd->bRequestType << 8) | cmd->bRequest;
 	wValue   = le16_to_cpu (cmd->wValue);
 	wIndex   = le16_to_cpu (cmd->wIndex);
@@ -347,13 +349,21 @@
 	/* DEVICE REQUESTS */
 
 	case DeviceRequest | USB_REQ_GET_STATUS:
-		// DEVICE_REMOTE_WAKEUP
-		ubuf [0] = 1; // selfpowered
+		ubuf [0] = (hcd->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP)
+				| (1 << USB_DEVICE_SELF_POWERED);
 		ubuf [1] = 0;
-			/* FALLTHROUGH */
+		break;
 	case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
+		if (wValue == USB_DEVICE_REMOTE_WAKEUP)
+			hcd->remote_wakeup = 0;
+		else
+			goto error;
+		break;
 	case DeviceOutRequest | USB_REQ_SET_FEATURE:
-		dev_dbg (hcd->self.controller, "no device features yet yet\n");
+		if (hcd->can_wakeup && wValue == USB_DEVICE_REMOTE_WAKEUP)
+			hcd->remote_wakeup = 1;
+		else
+			goto error;
 		break;
 	case DeviceRequest | USB_REQ_GET_CONFIGURATION:
 		ubuf [0] = 1;
@@ -379,6 +389,8 @@
 				bufp = fs_rh_config_descriptor;
 				len = sizeof fs_rh_config_descriptor;
 			}
+			if (hcd->can_wakeup)
+				patch_wakeup = 1;
 			break;
 		case USB_DT_STRING << 8:
 			urb->actual_length = rh_string (
@@ -444,6 +456,11 @@
 		urb->actual_length = len;
 		// always USB_DIR_IN, toward host
 		memcpy (ubuf, bufp, len);
+
+		/* report whether RH hardware supports remote wakeup */
+		if (patch_wakeup)
+			((struct usb_config_descriptor *)ubuf)->bmAttributes
+				|= USB_CONFIG_ATT_WAKEUP;
 	}
 
 	/* any errors get returned through the urb completion */
@@ -762,10 +779,22 @@
 	set_bit (devnum, usb_dev->bus->devmap.devicemap);
 	usb_dev->state = USB_STATE_ADDRESS;
 
+	usb_dev->epmaxpacketin[0] = usb_dev->epmaxpacketout[0] = 64;
+	retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
+	if (retval != sizeof usb_dev->descriptor) {
+		dev_dbg (parent_dev, "can't read %s device descriptor %d\n",
+				usb_dev->dev.bus_id, retval);
+		return (retval < 0) ? retval : -EMSGSIZE;
+	}
+
+	(void) usb_get_dev (usb_dev);
+	down (&usb_dev->serialize);
 	retval = usb_new_device (usb_dev);
 	if (retval)
 		dev_err (parent_dev, "can't register root hub for %s, %d\n",
 				usb_dev->dev.bus_id, retval);
+	up (&usb_dev->serialize);
+	usb_put_dev (usb_dev);
 	return retval;
 }
 EXPORT_SYMBOL (usb_register_root_hub);
diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
--- a/drivers/usb/core/hcd.h	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/core/hcd.h	Sun Apr 25 23:06:52 2004
@@ -74,6 +74,8 @@
 	 */
 	struct hc_driver	*driver;	/* hw-specific hooks */
 	unsigned		saw_irq : 1;
+	unsigned		can_wakeup:1;	/* hw supports wakeup? */
+	unsigned		remote_wakeup:1;/* sw should use wakeup? */
 	int			irq;		/* irq allocated */
 	void			*regs;		/* device memory/io */
 
@@ -344,9 +346,16 @@
 extern int usb_register_root_hub (struct usb_device *usb_dev,
 		struct device *parent_dev);
 
-/* for portability to 2.4, hcds should call this */
 static inline int hcd_register_root (struct usb_hcd *hcd)
 {
+	/* hcd->driver->start() reported can_wakeup, probably with
+	 * assistance from board's boot firmware.
+	 * NOTE:  normal devices won't enable wakeup by default.
+	 */
+	if (hcd->can_wakeup)
+		dev_dbg (hcd->self.controller, "supports USB remote wakeup\n");
+	hcd->remote_wakeup = hcd->can_wakeup;
+
 	return usb_register_root_hub (
 		hcd_to_bus (hcd)->root_hub, hcd->self.controller);
 }
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/core/hub.c	Sun Apr 25 23:06:52 2004
@@ -373,12 +373,13 @@
 	struct usb_device *dev;
 	int i;
 
-	/* Enable power to the ports */
-	dev_dbg(hubdev(interface_to_usbdev(hub->intf)),
-		"enabling power on all ports\n");
-	dev = interface_to_usbdev(hub->intf);
-	for (i = 0; i < hub->descriptor->bNbrPorts; i++)
-		set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
+	/* if hub supports power switching, enable power on each port */
+	if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2) {
+		dev_dbg(&hub->intf->dev, "enabling power on all ports\n");
+		dev = interface_to_usbdev(hub->intf);
+		for (i = 0; i < hub->descriptor->bNbrPorts; i++)
+			set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
+	}
 
 	/* Wait for power to be enabled */
 	wait_ms(hub->descriptor->bPwrOn2PwrGood * 2);
@@ -545,8 +546,25 @@
 
 	dev_dbg(hub_dev, "power on to power good time: %dms\n",
 		hub->descriptor->bPwrOn2PwrGood * 2);
-	dev_dbg(hub_dev, "hub controller current requirement: %dmA\n",
-		hub->descriptor->bHubContrCurrent);
+
+	/* power budgeting mostly matters with bus-powered hubs,
+	 * and battery-powered root hubs (may provide just 8 mA).
+	 */
+	ret = usb_get_status(dev, USB_RECIP_DEVICE, 0, &hubstatus);
+	if (ret < 0) {
+		message = "can't get hubdev status";
+		goto fail;
+	}
+	cpu_to_le16s(&hubstatus);
+	if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
+		dev_dbg(hub_dev, "hub controller current requirement: %dmA\n",
+			hub->descriptor->bHubContrCurrent);
+		hub->power_budget = (501 - hub->descriptor->bHubContrCurrent)
+					/ 2;
+		dev_dbg(hub_dev, "%dmA bus power budget for children\n",
+			hub->power_budget * 2);
+	}
+
 
 	ret = hub_hub_status(hub, &hubstatus, &hubchange);
 	if (ret < 0) {
@@ -554,12 +572,11 @@
 		goto fail;
 	}
 
-	/* FIXME implement per-port power budgeting;
-	 * enable it for bus-powered hubs.
-	 */
-	dev_dbg(hub_dev, "local power source is %s\n",
-		(hubstatus & HUB_STATUS_LOCAL_POWER)
-		? "lost (inactive)" : "good");
+	/* local power status reports aren't always correct */
+	if (dev->actconfig->desc.bmAttributes & USB_CONFIG_ATT_SELFPOWER)
+		dev_dbg(hub_dev, "local power source is %s\n",
+			(hubstatus & HUB_STATUS_LOCAL_POWER)
+			? "lost (inactive)" : "good");
 
 	if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_OCPM) == 0)
 		dev_dbg(hub_dev, "%sover-current condition exists\n",
@@ -611,6 +628,8 @@
 	return ret;
 }
 
+static unsigned highspeed_hubs;
+
 static void hub_disconnect(struct usb_interface *intf)
 {
 	struct usb_hub *hub = usb_get_intfdata (intf);
@@ -620,6 +639,9 @@
 	if (!hub)
 		return;
 
+	if (interface_to_usbdev(intf)->speed == USB_SPEED_HIGH)
+		highspeed_hubs--;
+
 	usb_set_intfdata (intf, NULL);
 	spin_lock_irqsave(&hub_event_lock, flags);
 	hub->urb_complete = &urb_complete;
@@ -731,6 +753,9 @@
 
 	usb_set_intfdata (intf, hub);
 
+	if (dev->speed == USB_SPEED_HIGH)
+		highspeed_hubs++;
+
 	if (hub_configure(hub, endpoint) >= 0)
 		return 0;
 
@@ -841,8 +866,11 @@
 	return ret;
 }
 
-#define HUB_RESET_TRIES		5
-#define HUB_PROBE_TRIES		2
+#define PORT_RESET_TRIES	5
+#define SET_ADDRESS_TRIES	2
+#define GET_DESCRIPTOR_TRIES	2
+#define SET_CONFIG_TRIES	2
+
 #define HUB_ROOT_RESET_TIME	50	/* times are in msec */
 #define HUB_SHORT_RESET_TIME	10
 #define HUB_LONG_RESET_TIME	200
@@ -907,7 +935,7 @@
 	int i, status;
 
 	/* Reset the port */
-	for (i = 0; i < HUB_RESET_TRIES; i++) {
+	for (i = 0; i < PORT_RESET_TRIES; i++) {
 		set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET);
 
 		/* return on disconnect or reset */
@@ -1003,40 +1031,20 @@
 	return ((portstatus&USB_PORT_STAT_CONNECTION)) ? 0 : 1;
 }
 
-static void hub_port_connect_change(struct usb_hub *hubstate, int port,
-					u16 portstatus, u16 portchange)
+/* reset device, (re)assign address, get device descriptor.
+ * device connection is stable, no more debouncing needed.
+ * returns device in USB_STATE_ADDRESS, except on error.
+ * on error return, device is no longer usable (ref dropped).
+ *
+ * caller owns dev->serialize for the device, guarding against
+ * config changes and disconnect processing.
+ */
+static int
+hub_port_init (struct usb_device *hub, struct usb_device *dev, int port)
 {
-	struct usb_device *hub = interface_to_usbdev(hubstate->intf);
-	struct usb_device *dev;
-	unsigned int delay = HUB_SHORT_RESET_TIME;
-	int i;
-
-	dev_dbg (&hubstate->intf->dev,
-		"port %d, status %x, change %x, %s\n",
-		port + 1, portstatus, portchange, portspeed (portstatus));
-
-	/* Clear the connection change status */
-	clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION);
-
-	/* Disconnect any existing devices under this port */
-	if (hub->children[port])
-		usb_disconnect(&hub->children[port]);
-
-	/* Return now if nothing is connected */
-	if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
-		if (portstatus & USB_PORT_STAT_ENABLE)
-			hub_port_disable(hub, port);
-
-		return;
-	}
-
-	if (hub_port_debounce(hub, port)) {
-		dev_err (&hubstate->intf->dev,
-			"connect-debounce failed, port %d disabled\n",
-			port+1);
-		hub_port_disable(hub, port);
-		return;
-	}
+	int			i, j, retval = -ENODEV;
+	unsigned		delay = HUB_SHORT_RESET_TIME;
+	enum usb_device_speed	oldspeed = dev->speed;
 
 	/* root hub ports have a slightly longer reset period
 	 * (from USB 2.0 spec, section 7.1.7.5)
@@ -1046,31 +1054,53 @@
 
 	/* Some low speed devices have problems with the quick delay, so */
 	/*  be a bit pessimistic with those devices. RHbug #23670 */
-	if (portstatus & USB_PORT_STAT_LOW_SPEED)
+	if (oldspeed == USB_SPEED_LOW)
 		delay = HUB_LONG_RESET_TIME;
 
 	down(&usb_address0_sem);
 
-	for (i = 0; i < HUB_PROBE_TRIES; i++) {
-
-		/* Allocate a new device struct */
-		dev = usb_alloc_dev(hub, hub->bus, port);
-		if (!dev) {
-			dev_err (&hubstate->intf->dev,
-				"couldn't allocate usb_device\n");
-			break;
-		}
-
-		dev->state = USB_STATE_POWERED;
-
-		/* Reset the device, and detect its speed */
-		if (hub_port_reset(hub, port, dev, delay)) {
-			usb_put_dev(dev);
-			break;
-		}
-
-		/* Find a new address for it */
+	/* Reset the device; full speed may morph to high speed */
+	switch (hub_port_reset(hub, port, dev, delay)) {
+	case 0:			/* success, speed is known */
+		break;
+	case 1:			/* disconnect, give to companion */
+		retval = -EBUSY;
+		/* FALL THROUGH */
+	default:		/* error */
+		goto fail;
+	}
+	if (oldspeed != USB_SPEED_UNKNOWN && oldspeed != dev->speed) {
+		dev_dbg(&dev->dev, "device reset changed speed!\n");
+		goto fail;
+	}
+  
+	/* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
+	 * it's fixed size except for full speed devices.
+	 */
+	switch (dev->speed) {
+	case USB_SPEED_HIGH:		/* fixed at 64 */
+		i = 64;
+		break;
+	case USB_SPEED_FULL:		/* 8, 16, 32, or 64 */
+		/* to determine the ep0 maxpacket size, read the first 8
+		 * bytes from the device descriptor to get bMaxPacketSize0;
+		 * then correct our initial (small) guess.
+		 */
+		// FALLTHROUGH
+	case USB_SPEED_LOW:		/* fixed at 8 */
+		i = 8;
+		break;
+	default:
+		goto fail;
+	}
+	dev->epmaxpacketin [0] = i;
+	dev->epmaxpacketout[0] = i;
+ 
+	/* set the address */
+	if (dev->devnum <= 0) {
 		usb_choose_address(dev);
+		if (dev->devnum <= 0)
+			goto fail;
 
 		/* Set up TT records, if needed  */
 		if (hub->tt) {
@@ -1078,12 +1108,21 @@
 			dev->ttport = hub->ttport;
 		} else if (dev->speed != USB_SPEED_HIGH
 				&& hub->speed == USB_SPEED_HIGH) {
+			struct usb_hub	*hubstate;
+ 
+			hubstate = usb_get_intfdata (hub->actconfig
+							->interface[0]);
 			dev->tt = &hubstate->tt;
 			dev->ttport = port + 1;
 		}
 
-		dev_info (&dev->dev,
-			"new %s speed USB device using address %d\n",
+		/* force the right log message (below) at low speed */
+		oldspeed = USB_SPEED_UNKNOWN;
+	}
+ 
+	dev_info (&dev->dev,
+			"%s %s speed USB device using address %d\n",
+			(oldspeed == USB_SPEED_UNKNOWN) ? "new" : "reset",
 			({ char *speed; switch (dev->speed) {
 			case USB_SPEED_LOW:	speed = "low";	break;
 			case USB_SPEED_FULL:	speed = "full";	break;
@@ -1091,23 +1130,258 @@
 			default: 		speed = "?";	break;
 			}; speed;}),
 			dev->devnum);
+ 
+	/* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way?
+	 * Because device hardware and firmware is sometimes buggy in
+	 * this area, and this is how Linux has done it for ages.
+	 * Change it cautiously.
+	 *
+	 * NOTE:  Windows gets the descriptor first, seemingly to help
+	 * work around device bugs like "can't use addresses with bit 3
+	 * set in certain configurations".  Yes, really.
+	 */
+	for (i = 0; i < GET_DESCRIPTOR_TRIES; ++i) {
+		for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
+			retval = usb_set_address(dev);
+			if (retval >= 0)
+				break;
+			wait_ms(200);
+		}
+		if (retval < 0) {
+			dev_err(&dev->dev,
+				"device not accepting address %d, error %d\n",
+				dev->devnum, retval);
+ fail:
+			hub_port_disable(hub, port);
+			clear_bit(dev->devnum, dev->bus->devmap.devicemap);
+			dev->devnum = -1;
+			usb_put_dev(dev);
+			up(&usb_address0_sem);
+			return retval;
+		}
+ 
+		/* cope with hardware quirkiness:
+		 *  - let SET_ADDRESS settle, some device hardware wants it
+		 *  - read ep0 maxpacket even for high and low speed,
+  		 */
+		wait_ms(10);
+		retval = usb_get_device_descriptor(dev, 8);
+		if (retval >= 8)
+			break;
+		wait_ms(100);
+	}
+	if (retval != 8) {
+		dev_err(&dev->dev, "device descriptor read/%s, error %d\n",
+				"8", retval);
+		if (retval >= 0)
+			retval = -EMSGSIZE;
+		goto fail;
+	}
+	if (dev->speed == USB_SPEED_FULL
+			&& (dev->epmaxpacketin [0]
+				!= dev->descriptor.bMaxPacketSize0)) {
+		usb_disable_endpoint(dev, 0);
+		usb_endpoint_running(dev, 0, 1);
+		usb_endpoint_running(dev, 0, 0);
+		dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;
+		dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
+	}
+  
+	retval = usb_get_device_descriptor(dev, USB_DT_DEVICE_SIZE);
+	if (retval < (signed)sizeof(dev->descriptor)) {
+		dev_err(&dev->dev, "device descriptor read/%s, error %d\n",
+			"all", retval);
+		if (retval >= 0)
+			retval = -ENOMSG;
+		goto fail;
+	}
 
-		/* Run it through the hoops (find a driver, etc) */
-		if (usb_new_device(dev) == 0) {
-			hub->children[port] = dev;
-			goto done;
+	/* now dev is visible to other tasks */
+	hub->children[port] = dev;
+
+	up(&usb_address0_sem);
+	return 0;
+}
+
+static void
+check_highspeed (struct usb_hub *hub, struct usb_device *dev, int port)
+{
+	struct usb_qualifier_descriptor	*qual;
+	int				status;
+
+	qual = kmalloc (sizeof *qual, SLAB_KERNEL);
+	if (qual == 0)
+		return;
+
+	status = usb_get_descriptor (dev, USB_DT_DEVICE_QUALIFIER, 0,
+			qual, sizeof *qual);
+	if (status == sizeof *qual) {
+		dev_info(&dev->dev, "not running at top speed; "
+			"connect to a high speed hub\n");
+		/* hub LEDs are probably harder to miss than syslog */
+		if (hub->has_indicators) {
+			hub->indicator[port] = INDICATOR_GREEN_BLINK;
+			schedule_work (&hub->leds);
 		}
+	}
+	kfree (qual);
+}
 
-		/* Free the configuration if there was an error */
-		usb_put_dev(dev);
+static unsigned
+hub_power_remaining (struct usb_hub *hubstate, struct usb_device *hub)
+{
+	int remaining;
+	unsigned i;
 
-		/* Switch to a long reset time */
-		delay = HUB_LONG_RESET_TIME;
+	remaining = hubstate->power_budget;
+	if (!remaining)		/* self-powered */
+		return 0;
+
+	for (i = 0; i < hub->maxchild; i++) {
+		struct usb_device	*dev = hub->children[i];
+		int			delta;
+
+		if (!dev)
+			continue;
+
+		if (dev->actconfig)
+			delta = dev->actconfig->desc.bMaxPower;
+		else
+			delta = 50;
+		// dev_dbg(&dev->dev, "budgeted %dmA\n", 2 * delta);
+		remaining -= delta;
+	}
+	if (remaining < 0) {
+		dev_warn(&hubstate->intf->dev,
+			"%dmA over power budget!\n",
+			-2 * remaining);
+		remaining = 0;
 	}
+	return remaining;
+}
+ 
+static void hub_port_connect_change(struct usb_hub *hubstate, int port,
+					u16 portstatus, u16 portchange)
+{
+	struct usb_device *hub = interface_to_usbdev(hubstate->intf);
+	int status, i;
+ 
+	dev_dbg (&hubstate->intf->dev,
+		"port %d, status %04x, change %04x, %s\n",
+		port + 1, portstatus, portchange, portspeed (portstatus));
+ 
+	/* Clear the connection change status */
+	clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION);
 
-	hub_port_disable(hub, port);
+	if (hubstate->has_indicators) {
+		set_port_led(hub, hubstate, port + 1, HUB_LED_AUTO);
+		hubstate->indicator[port] = INDICATOR_AUTO;
+	}
+ 
+	/* Disconnect any existing devices under this port */
+	if (hub->children[port])
+		usb_disconnect(&hub->children[port]);
+ 
+	/* Return now if nothing is connected */
+	if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
+		if (portstatus & USB_PORT_STAT_ENABLE)
+  			goto done;
+		return;
+	}
+  
+	if (hub_port_debounce(hub, port)) {
+		dev_err (&hubstate->intf->dev,
+			"connect-debounce failed, port %d disabled\n",
+			port+1);
+		goto done;
+	}
+
+	for (i = 0; i < SET_CONFIG_TRIES; i++) {
+		struct usb_device *dev;
+
+		/* reallocate for each attempt, since references
+		 * to the previous one can escape in various ways
+		 */
+		dev = usb_alloc_dev(hub, hub->bus, port);
+		if (!dev) {
+			dev_err (&hubstate->intf->dev,
+				"couldn't allocate port %d usb_device\n", port+1);
+			goto done;
+		}
+		dev->state = USB_STATE_POWERED;
+	  
+		/* hub can tell if it's lowspeed already:  D- pullup (not D+) */
+		if (portstatus & USB_PORT_STAT_LOW_SPEED)
+			dev->speed = USB_SPEED_LOW;
+		else
+			dev->speed = USB_SPEED_UNKNOWN;
+
+		/* reset, set address, get descriptor, add to hub's children */
+		down (&dev->serialize);
+		status = hub_port_init(hub, dev, port);
+		if (status == -EBUSY)
+			break;
+		if (status < 0)
+			continue;
+
+		/* consecutive bus-powered hubs aren't reliable; they can
+		 * violate the voltage drop budget.  if the new child has
+		 * a "powered" LED, users should notice we didn't enable it
+		 * (without reading syslog), even without per-port LEDs
+		 * on the parent.
+		 */
+		if (dev->descriptor.bDeviceClass == USB_CLASS_HUB
+				&& hubstate->power_budget) {
+			u16	devstat;
+
+			status = usb_get_status(dev, USB_RECIP_DEVICE, 0,
+					&devstat);
+			if (status < 0) {
+				dev_dbg(&dev->dev, "get status %d ?\n", status);
+				continue;
+			}
+			cpu_to_le16s(&hubstatus);
+			if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
+				dev_err(&dev->dev,
+					"can't connect bus-powered hub "
+					"to this port\n");
+				if (hubstate->has_indicators) {
+					hubstate->indicator[port] =
+						INDICATOR_AMBER_BLINK;
+					schedule_work (&hubstate->leds);
+				}
+				hub->children[port] = NULL;
+				usb_put_dev(dev);
+				hub_port_disable(hub, port);
+				return;
+			}
+		}
+ 
+		/* check for devices running slower than they could */
+		if (dev->descriptor.bcdUSB >= 0x0200
+				&& dev->speed == USB_SPEED_FULL
+				&& highspeed_hubs != 0)
+			check_highspeed (hubstate, dev, port);
+
+		/* Run it through the hoops (find a driver, etc) */
+		status = usb_new_device(dev);
+		if (status != 0) {
+			hub->children[port] = NULL;
+			continue;
+		}
+		up (&dev->serialize);
+
+		status = hub_power_remaining(hubstate, hub);
+		if (status)
+			dev_dbg(&hubstate->intf->dev,
+				"%dmA power budget left\n",
+				2 * status);
+
+		return;
+	}
+ 
 done:
-	up(&usb_address0_sem);
+	hub_port_disable(hub, port);
 }
 
 static void hub_events(void)
@@ -1285,9 +1559,6 @@
 	.id_table =	hub_id_table,
 };
 
-/*
- * This should be a separate module.
- */
 int usb_hub_init(void)
 {
 	pid_t pid;
diff -Nru a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
--- a/drivers/usb/core/hub.h	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/core/hub.h	Sun Apr 25 23:06:52 2004
@@ -209,6 +209,8 @@
 	struct semaphore	khubd_sem;
 	struct usb_tt		tt;		/* Transaction Translator */
 
+	u8			power_budget;	/* in 2mA units; or zero */
+
 	unsigned		has_indicators:1;
 	enum hub_led_mode	indicator[USB_MAXCHILDREN];
 	struct work_struct	leds;
diff -Nru a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
--- a/drivers/usb/core/inode.c	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/core/inode.c	Sun Apr 25 23:06:52 2004
@@ -717,9 +717,6 @@
 	while (!list_empty(&dev->filelist)) {
 		ds = list_entry(dev->filelist.next, struct dev_state, list);
 		list_del_init(&ds->list);
-		down_write(&ds->devsem);
-		ds->dev = NULL;
-		up_write(&ds->devsem);
 		if (ds->discsignr) {
 			sinfo.si_signo = SIGPIPE;
 			sinfo.si_errno = EPIPE;
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/core/usb.c	Sun Apr 25 23:06:52 2004
@@ -1064,92 +1064,29 @@
 }
 
 /*
- * By the time we get here, we chose a new device address
- * and is in the default state. We need to identify the thing and
- * get the ball rolling..
+ * usb_new_device - perform initial device setup (usbcore-internal)
+ * @dev: newly addressed device (in ADDRESS state)
  *
- * Returns 0 for success, != 0 for error.
+ * This is called with devices which have been enumerated, but not yet
+ * configured.  The device descriptor is available, but not descriptors
+ * for any device configuration.  The caller owns dev->serialize, and
+ * the device is not visible through sysfs or other filesystem code.
+ *
+ * Returns 0 for success (device is configured and listed, with its
+ * interfaces, in sysfs); else a negative errno value.  On error, one
+ * reference count to the device has been dropped.
  *
  * This call is synchronous, and may not be used in an interrupt context.
  *
  * Only the hub driver should ever call this; root hub registration
  * uses it only indirectly.
  */
-#define NEW_DEVICE_RETRYS	2
-#define SET_ADDRESS_RETRYS	2
 int usb_new_device(struct usb_device *dev)
 {
-	int err = -EINVAL;
+	int err;
 	int i;
-	int j;
 	int config;
 
-	/* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
-	 * it's fixed size except for full speed devices.
-	 */
-	switch (dev->speed) {
-	case USB_SPEED_HIGH:		/* fixed at 64 */
-		i = 64;
-		break;
-	case USB_SPEED_FULL:		/* 8, 16, 32, or 64 */
-		/* to determine the ep0 maxpacket size, read the first 8
-		 * bytes from the device descriptor to get bMaxPacketSize0;
-		 * then correct our initial (small) guess.
-		 */
-		// FALLTHROUGH
-	case USB_SPEED_LOW:		/* fixed at 8 */
-		i = 8;
-		break;
-	default:
-		goto fail;
-	}
-	dev->epmaxpacketin [0] = i;
-	dev->epmaxpacketout[0] = i;
-
-	for (i = 0; i < NEW_DEVICE_RETRYS; ++i) {
-
-		for (j = 0; j < SET_ADDRESS_RETRYS; ++j) {
-			err = usb_set_address(dev);
-			if (err >= 0)
-				break;
-			wait_ms(200);
-		}
-		if (err < 0) {
-			dev_err(&dev->dev,
-				"device not accepting address %d, error %d\n",
-				dev->devnum, err);
-			goto fail;
-		}
-
-		wait_ms(10);	/* Let the SET_ADDRESS settle */
-
-		/* high and low speed devices don't need this... */
-		err = usb_get_device_descriptor(dev, 8);
-		if (err >= 8)
-			break;
-		wait_ms(100);
-	}
-
-	if (err < 8) {
-		dev_err(&dev->dev, "device descriptor read/8, error %d\n", err);
-		goto fail;
-	}
-	if (dev->speed == USB_SPEED_FULL) {
-		usb_disable_endpoint(dev, 0);
-		usb_endpoint_running(dev, 0, 1);
-		usb_endpoint_running(dev, 0, 0);
-		dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;
-		dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
-	}
-
-	/* USB device state == addressed ... still not usable */
-
-	err = usb_get_device_descriptor(dev, sizeof(dev->descriptor));
-	if (err != (signed)sizeof(dev->descriptor)) {
-		dev_err(&dev->dev, "device descriptor read/all, error %d\n", err);
-		goto fail;
-	}
-
 	err = usb_get_configuration(dev);
 	if (err < 0) {
 		dev_err(&dev->dev, "can't read configurations, error %d\n",
@@ -1170,13 +1107,10 @@
 		usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
 #endif
 
-	down(&dev->serialize);
-
 	/* put device-specific files into sysfs */
 	err = device_add (&dev->dev);
 	if (err) {
 		dev_err(&dev->dev, "can't device_add, error %d\n", err);
-		up(&dev->serialize);
 		goto fail;
 	}
 	usb_create_driverfs_dev_files (dev);
@@ -1211,7 +1145,6 @@
 			dev->descriptor.bNumConfigurations);
 	}
 	err = usb_set_configuration(dev, config);
-	up(&dev->serialize);
 	if (err) {
 		dev_err(&dev->dev, "can't set config #%d, error %d\n",
 			config, err);
@@ -1226,9 +1159,10 @@
 
 	return 0;
 fail:
-	dev->state = USB_STATE_DEFAULT;
+	dev->state = USB_STATE_NOTATTACHED;
 	clear_bit(dev->devnum, dev->bus->devmap.devicemap);
 	dev->devnum = -1;
+	usb_put_dev(dev);
 	return err;
 }
 
diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
--- a/drivers/usb/host/uhci-hcd.c	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/host/uhci-hcd.c	Sun Apr 25 23:06:52 2004
@@ -157,8 +157,8 @@
 	return td;
 }
 
-static inline void uhci_fill_td(struct uhci_td *td, __u32 status,
-		__u32 token, __u32 buffer)
+static inline void uhci_fill_td(struct uhci_td *td, u32 status,
+		u32 token, u32 buffer)
 {
 	td->status = cpu_to_le32(status);
 	td->token = cpu_to_le32(token);
@@ -184,11 +184,11 @@
 		list_add_tail(&td->fl_list, &ftd->fl_list);
 
 		td->link = ltd->link;
-		mb();
+		wmb();
 		ltd->link = cpu_to_le32(td->dma_handle);
 	} else {
 		td->link = uhci->fl->frame[framenum];
-		mb();
+		wmb();
 		uhci->fl->frame[framenum] = cpu_to_le32(td->dma_handle);
 		uhci->fl->frame_cpu[framenum] = td;
 	}
@@ -218,7 +218,7 @@
 		ptd->link = td->link;
 	}
 
-	mb();
+	wmb();
 	td->link = UHCI_PTR_TERM;
 
 	list_del_init(&td->fl_list);
@@ -332,17 +332,7 @@
 	/* Grab the last QH */
 	lqh = list_entry(skelqh->list.prev, struct uhci_qh, list);
 
-	/*
-	 * Patch this endpoint's URB's QHs to point to the next skelqh:
-	 *    skelqh --> ... lqh --> newqh --> next skelqh
-	 * Do this first, so the HC always sees the right QH after this one.
-	 */
-	list_for_each (tmp, &urbp->queue_list) {
-		struct urb_priv *turbp =
-			list_entry(tmp, struct urb_priv, queue_list);
-
-		turbp->qh->link = lqh->link;
-	}
+	/* Point to the next skelqh */
 	urbp->qh->link = lqh->link;
 	wmb();				/* Ordering is important */
 
@@ -362,15 +352,15 @@
 	 *
 	 * The HC could see (and use!) any of these as we write them.
 	 */
+	lqh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH;
 	if (lqh->urbp) {
 		list_for_each (tmp, &lqh->urbp->queue_list) {
 			struct urb_priv *turbp =
 				list_entry(tmp, struct urb_priv, queue_list);
 
-			turbp->qh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH;
+			turbp->qh->link = lqh->link;
 		}
 	}
-	lqh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH;
 
 	list_add_tail(&urbp->qh->list, &skelqh->list);
 }
@@ -382,7 +372,7 @@
 static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
 	struct uhci_qh *pqh;
-	__u32 newlink;
+	u32 newlink;
 
 	if (!qh)
 		return;
@@ -423,7 +413,7 @@
 				turbp->qh->link = newlink;
 			}
 		}
-		mb();
+		wmb();
 
 		/* Leave qh->link in case the HC is on the QH now, it will */
 		/* continue the rest of the schedule */
@@ -510,7 +500,7 @@
 	/* All qh's in the queue need to link to the next queue */
 	urbp->qh->link = eurbp->qh->link;
 
-	mb();			/* Make sure we flush everything */
+	wmb();			/* Make sure we flush everything */
 
 	lltd->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH;
 
@@ -1044,9 +1034,13 @@
 			usb_pipeout(urb->pipe));
 	}
 
-	/* Set the flag on the last packet */
-	if (!(urb->transfer_flags & URB_NO_INTERRUPT))
-		td->status |= cpu_to_le32(TD_CTRL_IOC);
+	/* Set the interrupt-on-completion flag on the last packet.
+	 * A more-or-less typical 4 KB URB (= size of one memory page)
+	 * will require about 3 ms to transfer; that's a little on the
+	 * fast side but not enough to justify delaying an interrupt
+	 * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT
+	 * flag setting. */
+	td->status |= cpu_to_le32(TD_CTRL_IOC);
 
 	qh = uhci_alloc_qh(uhci, urb->dev);
 	if (!qh)
@@ -1786,6 +1780,9 @@
 
 	spin_unlock(&uhci->schedule_lock);
 
+	/* Wake up anyone waiting for an URB to complete */
+	wake_up_all(&uhci->waitqh);
+
 	return IRQ_HANDLED;
 }
 
@@ -2086,6 +2083,8 @@
 
 	INIT_LIST_HEAD(&uhci->complete_list);
 
+	init_waitqueue_head(&uhci->waitqh);
+
 	uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
 			&dma_handle, 0);
 	if (!uhci->fl) {
@@ -2296,6 +2295,9 @@
 	uhci_free_pending_qhs(uhci);
 	uhci_free_pending_tds(uhci);
 	spin_unlock_irq(&uhci->schedule_lock);
+
+	/* Wake up anyone waiting for an URB to complete */
+	wake_up_all(&uhci->waitqh);
 	
 	release_uhci(uhci);
 }
@@ -2361,6 +2363,46 @@
 	kfree(hcd_to_uhci(hcd));
 }
 
+/* Are there any URBs for a particular device/endpoint on a given list? */
+static int urbs_for_ep_list(struct list_head *head,
+		struct hcd_dev *hdev, int ep)
+{
+	struct urb_priv *urbp;
+
+	list_for_each_entry(urbp, head, urb_list) {
+		struct urb *urb = urbp->urb;
+
+		if (hdev == urb->dev->hcpriv && ep ==
+				(usb_pipeendpoint(urb->pipe) |
+				 usb_pipein(urb->pipe)))
+			return 1;
+	}
+	return 0;
+}
+
+/* Are there any URBs for a particular device/endpoint? */
+static int urbs_for_ep(struct uhci_hcd *uhci, struct hcd_dev *hdev, int ep)
+{
+	int rc;
+
+	spin_lock_irq(&uhci->schedule_lock);
+	rc = (urbs_for_ep_list(&uhci->urb_list, hdev, ep) ||
+			urbs_for_ep_list(&uhci->complete_list, hdev, ep) ||
+			urbs_for_ep_list(&uhci->urb_remove_list, hdev, ep));
+	spin_unlock_irq(&uhci->schedule_lock);
+	return rc;
+}
+
+/* Wait until all the URBs for a particular device/endpoint are gone */
+static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd,
+		struct hcd_dev *hdev, int endpoint)
+{
+	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+
+	wait_event_interruptible(uhci->waitqh,
+			!urbs_for_ep(uhci, hdev, endpoint));
+}
+
 static int uhci_hcd_get_frame_number(struct usb_hcd *hcd)
 {
 	return uhci_get_current_frame_number(hcd_to_uhci(hcd));
@@ -2390,6 +2432,7 @@
 	.urb_enqueue =		uhci_urb_enqueue,
 	.urb_dequeue =		uhci_urb_dequeue,
 
+	.endpoint_disable =	uhci_hcd_endpoint_disable,
 	.get_frame_number =	uhci_hcd_get_frame_number,
 
 	.hub_status_data =	uhci_hub_status_data,
diff -Nru a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
--- a/drivers/usb/host/uhci-hcd.h	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/host/uhci-hcd.h	Sun Apr 25 23:06:52 2004
@@ -80,7 +80,7 @@
 #define CAN_SCHEDULE_FRAMES	1000	/* how far future frames can be scheduled */
 
 struct uhci_frame_list {
-	__u32 frame[UHCI_NUMFRAMES];
+	u32 frame[UHCI_NUMFRAMES];
 
 	void *frame_cpu[UHCI_NUMFRAMES];
 
@@ -105,8 +105,8 @@
  */
 struct uhci_qh {
 	/* Hardware fields */
-	__u32 link;			/* Next queue */
-	__u32 element;			/* Queue element pointer */
+	u32 link;			/* Next queue */
+	u32 element;			/* Queue element pointer */
 
 	/* Software fields */
 	dma_addr_t dma_handle;
@@ -185,10 +185,10 @@
  */
 struct uhci_td {
 	/* Hardware fields */
-	__u32 link;
-	__u32 status;
-	__u32 token;
-	__u32 buffer;
+	u32 link;
+	u32 status;
+	u32 token;
+	u32 buffer;
 
 	/* Software fields */
 	dma_addr_t dma_handle;
@@ -370,6 +370,8 @@
 	int rh_numports;
 
 	struct timer_list stall_timer;
+
+	wait_queue_head_t waitqh;		/* endpoint_disable waiters */
 };
 
 struct urb_priv {
diff -Nru a/drivers/usb/media/ibmcam.c b/drivers/usb/media/ibmcam.c
--- a/drivers/usb/media/ibmcam.c	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/media/ibmcam.c	Sun Apr 25 23:06:52 2004
@@ -3647,7 +3647,7 @@
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
 	struct uvd *uvd = NULL;
-	int i, nas, model=0, canvasX=0, canvasY=0;
+	int ix, i, nas, model=0, canvasX=0, canvasY=0;
 	int actInterface=-1, inactInterface=-1, maxPS=0;
 	__u8 ifnum = intf->altsetting->desc.bInterfaceNumber;
 	unsigned char video_ep = 0;
@@ -3718,7 +3718,7 @@
 	} while (0);
 
 	/* Validate found interface: must have one ISO endpoint */
-	nas = dev->actconfig->interface[ifnum]->num_altsetting;
+	nas = intf->num_altsetting;
 	if (debug > 0)
 		info("Number of alternate settings=%d.", nas);
 	if (nas < 2) {
@@ -3726,11 +3726,12 @@
 		return -ENODEV;
 	}
 	/* Validate all alternate settings */
-	for (i=0; i < nas; i++) {
+	for (ix=0; ix < nas; ix++) {
 		const struct usb_host_interface *interface;
 		const struct usb_endpoint_descriptor *endpoint;
 
-		interface = &dev->actconfig->interface[ifnum]->altsetting[i];
+		interface = &intf->altsetting[ix];
+		i = interface->desc.bAlternateSetting;
 		if (interface->desc.bNumEndpoints != 1) {
 			err("Interface %d. has %u. endpoints!",
 			    ifnum, (unsigned)(interface->desc.bNumEndpoints));
diff -Nru a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c
--- a/drivers/usb/media/konicawc.c	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/media/konicawc.c	Sun Apr 25 23:06:52 2004
@@ -381,9 +381,15 @@
 	int i, errFlag;
 	struct konicawc *cam = (struct konicawc *)uvd->user_data;
 	int pktsz;
-	struct usb_host_interface *interface;
+	struct usb_interface *intf;
+	struct usb_host_interface *interface = NULL;
 
-	interface = &dev->actconfig->interface[uvd->iface]->altsetting[spd_to_iface[cam->speed]];
+	intf = usb_ifnum_to_if(dev, uvd->iface);
+	if (intf)
+		interface = usb_altnum_to_altsetting(intf,
+				spd_to_iface[cam->speed]);
+	if (!interface)
+		return -ENXIO;
 	pktsz = interface->endpoint[1].desc.wMaxPacketSize;
 	DEBUG(1, "pktsz = %d", pktsz);
 	if (!CAMERA_IS_OPERATIONAL(uvd)) {
@@ -721,7 +727,7 @@
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
 	struct uvd *uvd = NULL;
-	int i, nas;
+	int ix, i, nas;
 	int actInterface=-1, inactInterface=-1, maxPS=0;
 	unsigned char video_ep = 0;
 
@@ -741,11 +747,12 @@
 		return -ENODEV;
 	}
 	/* Validate all alternate settings */
-	for (i=0; i < nas; i++) {
+	for (ix=0; ix < nas; ix++) {
 		const struct usb_host_interface *interface;
 		const struct usb_endpoint_descriptor *endpoint;
 
-		interface = &intf->altsetting[i];
+		interface = &intf->altsetting[ix];
+		i = interface->desc.bAlternateSetting;
 		if (interface->desc.bNumEndpoints != 2) {
 			err("Interface %d. has %u. endpoints!",
 			    interface->desc.bInterfaceNumber,
diff -Nru a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
--- a/drivers/usb/media/ov511.c	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/media/ov511.c	Sun Apr 25 23:06:52 2004
@@ -5603,8 +5603,16 @@
 
 	if (ov->bridge == BRG_OV518)
 	{
-		struct usb_interface *ifp = ov->dev->config[0].interface[0];
-		__u16 mxps = ifp->altsetting[7].endpoint[0].desc.wMaxPacketSize;
+		struct usb_interface *ifp;
+		struct usb_host_interface *alt;
+		__u16 mxps = 0;
+
+		ifp = usb_ifnum_to_if(ov->dev, 0);
+		if (ifp) {
+			alt = usb_altnum_to_altsetting(ifp, 7);
+			if (alt)
+				mxps = alt->endpoint[0].desc.wMaxPacketSize;
+		}
 
 		/* Some OV518s have packet numbering by default, some don't */
 		if (mxps == 897)
@@ -5805,7 +5813,7 @@
 	if (dev->descriptor.bNumConfigurations != 1)
 		return -ENODEV;
 
-	idesc = &intf->altsetting[0].desc;
+	idesc = &intf->cur_altsetting->desc;
 
 	if (idesc->bInterfaceClass != 0xFF)
 		return -ENODEV;
diff -Nru a/drivers/usb/media/pwc-if.c b/drivers/usb/media/pwc-if.c
--- a/drivers/usb/media/pwc-if.c	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/media/pwc-if.c	Sun Apr 25 23:06:52 2004
@@ -789,7 +789,8 @@
 	struct urb *urb;
 	int i, j, ret;
 
-	struct usb_host_interface *idesc;
+	struct usb_interface *intf;
+	struct usb_host_interface *idesc = NULL;
 
 	if (pdev == NULL)
 		return -EFAULT;
@@ -801,7 +802,9 @@
 	/* Get the current alternate interface, adjust packet size */
 	if (!udev->actconfig)
 		return -EFAULT;
-	idesc = &udev->actconfig->interface[0]->altsetting[pdev->valternate];
+	intf = usb_ifnum_to_if(udev, 0);
+	if (intf)
+		idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
 	if (!idesc)
 		return -EFAULT;
 
diff -Nru a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c
--- a/drivers/usb/media/se401.c	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/media/se401.c	Sun Apr 25 23:06:52 2004
@@ -1326,7 +1326,7 @@
         if (dev->descriptor.bNumConfigurations != 1)
                 return -ENODEV;
 
-        interface = &intf->altsetting[0].desc;
+        interface = &intf->cur_altsetting->desc;
 
         /* Is it an se401? */
         if (dev->descriptor.idVendor == 0x03e8 &&
diff -Nru a/drivers/usb/media/ultracam.c b/drivers/usb/media/ultracam.c
--- a/drivers/usb/media/ultracam.c	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/media/ultracam.c	Sun Apr 25 23:06:52 2004
@@ -513,7 +513,7 @@
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
 	struct uvd *uvd = NULL;
-	int i, nas;
+	int ix, i, nas;
 	int actInterface=-1, inactInterface=-1, maxPS=0;
 	unsigned char video_ep = 0;
 
@@ -540,11 +540,12 @@
 		return -ENODEV;
 	}
 	/* Validate all alternate settings */
-	for (i=0; i < nas; i++) {
+	for (ix=0; ix < nas; ix++) {
 		const struct usb_host_interface *interface;
 		const struct usb_endpoint_descriptor *endpoint;
 
-		interface = &intf->altsetting[i];
+		interface = &intf->altsetting[ix];
+		i = interface->desc.bAlternateSetting;
 		if (interface->desc.bNumEndpoints != 1) {
 			err("Interface %d. has %u. endpoints!",
 			    interface->desc.bInterfaceNumber,
diff -Nru a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c
--- a/drivers/usb/media/vicam.c	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/media/vicam.c	Sun Apr 25 23:06:52 2004
@@ -1303,7 +1303,7 @@
 
 	printk(KERN_INFO "ViCam based webcam connected\n");
 
-	interface = &intf->altsetting[0];
+	interface = intf->cur_altsetting;
 
 	DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n",
 	       interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints));
diff -Nru a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
--- a/drivers/usb/misc/legousbtower.c	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/misc/legousbtower.c	Sun Apr 25 23:06:52 2004
@@ -704,7 +704,7 @@
 	dev->interrupt_out_urb = NULL;
 
 
-	iface_desc = &interface->altsetting[0];
+	iface_desc = interface->cur_altsetting;
 
 	/* set up the endpoint information */
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
diff -Nru a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
--- a/drivers/usb/misc/usbtest.c	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/misc/usbtest.c	Sun Apr 25 23:06:52 2004
@@ -802,6 +802,7 @@
 				switch (status) {
 				case -EINPROGRESS:
 				case -EBUSY:
+				case -EIDRM:
 					continue;
 				default:
 					dbg ("urb unlink --> %d", status);
@@ -1038,8 +1039,6 @@
 	if (!status)
 		status = usb_submit_urb (urb, SLAB_ATOMIC);
 	if (status) {
-		if (status == -ECONNRESET || status == -ENOENT)
-			status = 0;
 		urb->status = status;
 		complete ((struct completion *) urb->context);
 	}
@@ -1077,8 +1076,9 @@
 	wait_ms (jiffies % (2 * INTERRUPT_RATE));
 retry:
 	retval = usb_unlink_urb (urb);
-	if (retval == -EBUSY) {
+	if (retval == -EBUSY || retval == -EIDRM) {
 		/* we can't unlink urbs while they're completing.
+		 * or if they've completed, and we haven't resubmitted.
 		 * "normal" drivers would prevent resubmission, but
 		 * since we're testing unlink paths, we can't.
 		 */
diff -Nru a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
--- a/drivers/usb/misc/uss720.c	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/misc/uss720.c	Sun Apr 25 23:06:52 2004
@@ -553,7 +553,7 @@
 	i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2);
 	printk(KERN_DEBUG "uss720: set inteface result %d\n", i);
 
-	interface = &intf->altsetting[2];
+	interface = intf->cur_altsetting;
 
 	/*
 	 * Allocate parport interface 
diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
--- a/drivers/usb/net/usbnet.c	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/net/usbnet.c	Sun Apr 25 23:06:52 2004
@@ -928,8 +928,8 @@
  */
 static int generic_cdc_bind (struct usbnet *dev, struct usb_interface *intf)
 {
-	u8				*buf = intf->altsetting->extra;
-	int				len = intf->altsetting->extralen;
+	u8				*buf = intf->cur_altsetting->extra;
+	int				len = intf->cur_altsetting->extralen;
 	struct usb_interface_descriptor	*d;
 	struct cdc_state		*info = (void *) &dev->data;
 	int				status;
@@ -955,7 +955,7 @@
 	/* this assumes that if there's a non-RNDIS vendor variant
 	 * of cdc-acm, it'll fail RNDIS requests cleanly.
 	 */
-	rndis = (intf->altsetting->desc.bInterfaceProtocol == 0xff);
+	rndis = (intf->cur_altsetting->desc.bInterfaceProtocol == 0xff);
 
 	memset (info, 0, sizeof *info);
 	info->control = intf;
@@ -1025,7 +1025,7 @@
 			}
 
 			/* a data interface altsetting does the real i/o */
-			d = &info->data->altsetting->desc;
+			d = &info->data->cur_altsetting->desc;
 			if (d->bInterfaceClass != USB_CLASS_CDC_DATA) {
 				dev_dbg (&intf->dev, "slave class %u\n",
 					d->bInterfaceClass);
diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
--- a/drivers/usb/storage/unusual_devs.h	Sun Apr 25 23:06:52 2004
+++ b/drivers/usb/storage/unusual_devs.h	Sun Apr 25 23:06:52 2004
@@ -438,22 +438,6 @@
 		US_FL_SINGLE_LUN ),
 #endif
 
-/* Following three Minolta cameras reported by Martin Pool
- * <mbp@sourcefrog.net>.  Originally discovered by Kedar Petankar,
- * Matthew Geier, Mikael Lofj"ard, Marcel de Boer.
- */
-UNUSUAL_DEV( 0x0686, 0x4006, 0x0001, 0x0001,
-		"Minolta",
-		"DiMAGE 7",
-		US_SC_SCSI, US_PR_DEVICE, NULL,
-		0 ),
-
-UNUSUAL_DEV( 0x0686, 0x400f, 0x0001, 0x0001,
-		"Minolta",
-		"DiMAGE 7Hi",
-		US_SC_SCSI, US_PR_DEVICE, NULL,
-		0 ),
-
 /* Submitted by Benny Sjostrand <benny@hostmobility.com> */
 UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001,
 		"Minolta",
@@ -688,7 +672,7 @@
 UNUSUAL_DEV(  0x0a16, 0x8888, 0x0100, 0x0100,
 		"IBM",
 		"IBM USB Memory Key",
-		US_SC_SCSI, US_PR_BULK, NULL,
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* This Pentax still camera is not conformant
diff -Nru a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
--- a/include/linux/usbdevice_fs.h	Sun Apr 25 23:06:52 2004
+++ b/include/linux/usbdevice_fs.h	Sun Apr 25 23:06:52 2004
@@ -154,7 +154,6 @@
 
 struct dev_state {
 	struct list_head list;      /* state list */
-	struct rw_semaphore devsem; /* protects modifications to dev (dev == NULL indicating disconnect) */ 
 	struct usb_device *dev;
 	struct file *file;
 	spinlock_t lock;            /* protects the async urb lists */