bk://kernel.bkbits.net/gregkh/linux/usb-2.6
greg@kroah.com|ChangeSet|20040804045238|03790 greg

# This is a BitKeeper generated diff -Nru style patch.
#
# 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/03 21:52:38-07:00 greg@kroah.com 
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/net/usbnet.c
#   2004/08/03 21:51:50-07:00 greg@kroah.com +1 -1
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/net/pegasus.c
#   2004/08/03 21:51:50-07:00 greg@kroah.com +2 -2
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/misc/tiglusb.c
#   2004/08/03 21:51:50-07:00 greg@kroah.com +1 -1
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/misc/legousbtower.c
#   2004/08/03 21:51:49-07:00 greg@kroah.com +7 -7
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/usbvideo.c
#   2004/08/03 21:51:49-07:00 greg@kroah.com +1 -1
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/ultracam.c
#   2004/08/03 21:51:50-07:00 greg@kroah.com +8 -8
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/stv680.c
#   2004/08/03 21:51:50-07:00 greg@kroah.com +3 -3
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/se401.c
#   2004/08/03 21:51:50-07:00 greg@kroah.com +2 -2
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/pwc-if.c
#   2004/08/03 21:51:50-07:00 greg@kroah.com +16 -18
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/ov511.c
#   2004/08/03 21:51:51-07:00 greg@kroah.com +35 -35
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/konicawc.c
#   2004/08/03 21:51:50-07:00 greg@kroah.com +9 -9
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/dabusb.c
#   2004/08/03 21:51:50-07:00 greg@kroah.com +1 -1
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/input/kbtab.c
#   2004/08/03 21:51:50-07:00 greg@kroah.com +3 -4
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/input/aiptek.c
#   2004/08/03 21:51:49-07:00 greg@kroah.com +2 -2
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/host/uhci-hcd.c
#   2004/08/03 21:51:51-07:00 greg@kroah.com +1 -1
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/host/ohci-omap.c
#   2004/08/03 21:51:50-07:00 greg@kroah.com +1 -1
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/host/hc_sl811.c
#   2004/08/03 21:51:49-07:00 greg@kroah.com +4 -4
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/class/usblp.c
#   2004/08/03 21:51:49-07:00 greg@kroah.com +1 -1
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/class/usb-midi.c
#   2004/08/03 21:51:50-07:00 greg@kroah.com +10 -10
#   USB: convert a lot of usb drivers from MODULE_PARM to module_param
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/08/03 07:11:34-07:00 greg@kroah.com 
#   USB: replace old usb-skeleton driver with a rewritten and simpler version.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/usb-skeleton.c
#   2004/08/03 07:11:11-07:00 greg@kroah.com +139 -483
#   USB: replace old usb-skeleton driver with a rewritten and simpler version.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/08/02 16:24:51-07:00 greg@kroah.com 
#   [PATCH] USB: fix build error from previous patch.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/message.c
#   2004/08/02 16:22:54-07:00 greg@kroah.com +1 -1
#   USB: fix build error from previous patch.
# 
# ChangeSet
#   2004/08/02 16:24:29-07:00 david-b@pacbell.net 
#   [PATCH] USB: hid intervals
#   
#   I noticed the HID driver had some potential misbehavior ...
#   
#   
#   Bugfix handling for HID devices at high speed (interrupt interval encoding
#   is log2 not linear), and for interrupt OUT transfers (use the interval
#   the hardware actually supports).
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/input/hid-core.c
#   2004/07/23 06:29:18-07:00 david-b@pacbell.net +8 -2
#   USB: hid intervals
# 
# ChangeSet
#   2004/08/02 16:24:07-07:00 david-b@pacbell.net 
#   [PATCH] USB: usb_get_descriptor, more error checks
#   
#   I've had different versions of this floating around for a while;
#   basically, the goal is to be more robust against devices that
#   misbehave by returning garbage descriptors in certain cases.
#   
#   Add an extra check when fetching descriptors:  the type must be
#   correct.  This guards against different types of firmware (or maybe
#   hardware) errors than the two checks already being made.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/message.c
#   2004/07/14 05:05:11-07:00 david-b@pacbell.net +7 -2
#   USB: usb_get_descriptor, more error checks
# 
# ChangeSet
#   2004/08/02 14:47:27-07:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: cleanups, mostly
#   
#   This patch is originally from Christoph Hellwig.
#   
#   This patch coverts from Scsi_Foo typefs to struct scsi_cmnd, and moved from
#   the SCSI data direction constants to the DMA ones.
#   
#   It also switches to the proper (or so they tell me) use of <scsi/*.h>
#   headers.  This also includes some additional reshuffling to avoid useless
#   headers in the usb-storage local headers (to improve compile time).
#   
#   Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/storage/usb.h
#   2004/07/20 16:30:35-07:00 mdharm-usb@one-eyed-alien.net +4 -5
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/usb.c
#   2004/07/20 16:30:34-07:00 mdharm-usb@one-eyed-alien.net +6 -1
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/transport.h
#   2004/07/20 16:30:38-07:00 mdharm-usb@one-eyed-alien.net +6 -5
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/transport.c
#   2004/07/20 16:30:37-07:00 mdharm-usb@one-eyed-alien.net +18 -13
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/shuttle_usbat.h
#   2004/07/20 16:30:37-07:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/shuttle_usbat.c
#   2004/07/20 16:30:36-07:00 mdharm-usb@one-eyed-alien.net +23 -19
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/sddr55.h
#   2004/07/20 16:30:36-07:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/sddr55.c
#   2004/07/20 16:30:33-07:00 mdharm-usb@one-eyed-alien.net +24 -20
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/sddr09.h
#   2004/07/20 16:30:35-07:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/sddr09.c
#   2004/07/20 16:30:33-07:00 mdharm-usb@one-eyed-alien.net +12 -9
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/scsiglue.h
#   2004/07/20 16:30:26-07:00 mdharm-usb@one-eyed-alien.net +3 -5
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/scsiglue.c
#   2004/07/20 16:30:25-07:00 mdharm-usb@one-eyed-alien.net +18 -11
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/protocol.h
#   2004/07/20 16:30:25-07:00 mdharm-usb@one-eyed-alien.net +10 -10
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/protocol.c
#   2004/07/20 16:30:24-07:00 mdharm-usb@one-eyed-alien.net +14 -11
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/jumpshot.h
#   2004/07/20 16:30:24-07:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/jumpshot.c
#   2004/07/20 16:30:23-07:00 mdharm-usb@one-eyed-alien.net +11 -7
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/isd200.h
#   2004/07/20 16:30:23-07:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/isd200.c
#   2004/07/20 16:30:22-07:00 mdharm-usb@one-eyed-alien.net +38 -33
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/freecom.h
#   2004/07/20 16:30:21-07:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/freecom.c
#   2004/07/20 16:30:21-07:00 mdharm-usb@one-eyed-alien.net +11 -7
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/dpcm.h
#   2004/07/20 16:30:20-07:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/dpcm.c
#   2004/07/20 16:30:20-07:00 mdharm-usb@one-eyed-alien.net +5 -1
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/debug.h
#   2004/07/20 16:30:19-07:00 mdharm-usb@one-eyed-alien.net +3 -3
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/debug.c
#   2004/07/20 16:30:18-07:00 mdharm-usb@one-eyed-alien.net +7 -1
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/datafab.h
#   2004/07/20 16:30:17-07:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: cleanups, mostly
# 
# drivers/usb/storage/datafab.c
#   2004/07/20 16:30:17-07:00 mdharm-usb@one-eyed-alien.net +11 -8
#   USB Storage: cleanups, mostly
# 
# ChangeSet
#   2004/08/02 14:47:07-07:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: improve debugging output in usb-storage
#   
#   This patch started life as as294.  All I did was to regenerate it to apply
#   cleanly against current kernels.
#   
#   This just adds a couple of lines to the debugging output with some useful
#   information, and removes some lines that nobody has looked at in a very
#   long time.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/storage/usb.c
#   2004/08/01 10:17:28-07:00 mdharm-usb@one-eyed-alien.net +9 -10
#   USB Storage: improve debugging output in usb-storage
# 
# ChangeSet
#   2004/08/02 14:46:49-07:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: fix Genesys Logic based on info from vendor
#   
#   In theory, this is the fix we need to make Genesys Logic devices work.
#   This patch started life as as343, which was created based on some
#   information which a user finally coaxed out of Genesys Logic.  Limited
#   end-user testing gives good results.
#   
#   As we expected, it's a bug in their device.  This is really a workaround
#   for what is almost certainly a timing problem.  Apparently, the 'popular'
#   OSes don't push the device as hard as Linux does.
#   
#   Although it is likely that this workaround is not needed for all Genesys
#   devices, Genesys was unable/unwilling to provide us with the explicit list
#   of VID/PIDs which required this -- thus we apply it to all Genesys devices.
#   
#   We have lots of good reports with max_sectors set to 128 with these
#   devices, but the official recommendation is to set that to 64.  End-users
#   can experiment with higher values (for higher performance) via the runtime
#   sysfs interface to that parameter.
#   
#   I would like to give special thanks to the users who hounded Genesys into
#   giving up this information, and to Alan Stern for not giving up on this
#   vendor long after I had.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/storage/usb.h
#   2004/08/01 10:32:35-07:00 mdharm-usb@one-eyed-alien.net +4 -0
#   USB Storage: fix Genesys Logic based on info from vendor
# 
# drivers/usb/storage/transport.c
#   2004/08/01 10:32:35-07:00 mdharm-usb@one-eyed-alien.net +6 -0
#   USB Storage: fix Genesys Logic based on info from vendor
# 
# drivers/usb/storage/scsiglue.c
#   2004/08/01 10:32:35-07:00 mdharm-usb@one-eyed-alien.net +8 -10
#   USB Storage: fix Genesys Logic based on info from vendor
# 
# ChangeSet
#   2004/08/02 14:46:24-07:00 oliver@neukum.org 
#   [PATCH] USB: ACM USB modem on Kernel 2.6.8-rc2
#   
#   this adds a workaround for a broken USB modem.
#   
#   
#   Signed-Off-By: Oliver Neukum <oliver@neukum.name>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/class/cdc-acm.c
#   2004/08/02 12:40:30-07:00 oliver@neukum.org +17 -11
#   USB: ACM USB modem on Kernel 2.6.8-rc2
# 
# ChangeSet
#   2004/08/02 14:29:51-07:00 nacc@us.ibm.com 
#   [PATCH] USB: usbnet: replace schedule_timeout() with msleep()
#   
#   Use msleep() instead of schedule_timeout() to guarantee the task delays
#   for the desired time. Delete unused UNLINK_TIMEOUT_JIFFIES #define.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/net/usbnet.c
#   2004/07/28 12:33:16-07:00 nacc@us.ibm.com +2 -3
#   USB: usbnet: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2004/08/02 14:29:08-07:00 nacc@us.ibm.com 
#   [PATCH] USB: auerswald: replace schedule_timeout() with msleep()
#   
#   Use msleep() instead of schedule_timeout() to
#   guarantee the task delays for the desired time.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/misc/auerswald.c
#   2004/07/05 18:12:12-07:00 nacc@us.ibm.com +1 -2
#   USB: auerswald: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2004/08/02 14:28:02-07:00 nacc@us.ibm.com 
#   [PATCH] USB: ov511: replace schedule_timeout() with msleep()
#   
#   Use msleep() instead of schedule_timeout() to
#   guarantee the task delays for the desired time.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Mark McClelland <mark@alpha.dyndns.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/ov511.c
#   2004/07/13 13:29:29-07:00 nacc@us.ibm.com +3 -3
#   USB: ov511: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2004/08/02 14:26:44-07:00 nacc@us.ibm.com 
#   [PATCH] USB: pxa2xx_udc.c: replace schedule_timeout() with msleep()
#   
#   Use msleep() instead of schedule_timeout() to
#   guarantee the task delays for the desired time.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/pxa2xx_udc.c
#   2004/07/13 13:31:07-07:00 nacc@us.ibm.com +1 -1
#   USB: pxa2xx_udc.c: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2004/08/02 14:25:50-07:00 da-x@gmx.net 
#   [PATCH] d_unhash consolidation
#   
#   This removes a copy of d_unhash() from drivers/usb/core/inode.c and
#   and exports d_unhash() from fs/namei.c as dentry_unhash().
#   Tested - compiled and running.
#   
#   Signed-off-by: Dan Aloni <da-x@gmx.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# include/linux/fs.h
#   2004/07/24 05:52:42-07:00 da-x@gmx.net +5 -0
#   d_unhash consolidation
# 
# fs/namei.c
#   2004/07/24 06:14:13-07:00 da-x@gmx.net +4 -3
#   d_unhash consolidation
# 
# drivers/usb/core/inode.c
#   2004/07/24 06:13:27-07:00 da-x@gmx.net +1 -18
#   d_unhash consolidation
# 
# 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
# 
# ChangeSet
#   2004/07/30 16:55:46-07:00 greg@kroah.com 
#   USB: fix build error in the cyberjack driver
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/cyberjack.c
#   2004/07/30 16:55:16-07:00 greg@kroah.com +1 -0
#   USB: fix build error in the cyberjack driver
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/07/30 16:38:58-07:00 luca.risolia@studio.unibo.it 
#   [PATCH] USB: New entry in MAINTAINERS
#   
#   I forgot to add an entry in MAINTAINERS about the new SN9C10[12] driver.
#   
#   Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# MAINTAINERS
#   2004/07/15 04:04:07-07:00 luca.risolia@studio.unibo.it +7 -0
#   USB: New entry in MAINTAINERS
# 
# ChangeSet
#   2004/07/30 16:38:38-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: unusual_devs.h update
#   
#   In view of the comments below, I think we should modify this
#   unusual_devs.h entry to suppress the warning messages.  Please apply.
#   
#   
#   
#   On Mon, 28 Jun 2004, Joël Bourquard wrote:
#   
#   > There seem to be two different flavors of ISD-300 (ie: 05ab,0060)
#   > devices, one of which needs this entry to work, and the other doesn't.
#   >
#   > I have a 2 1/2'' HDD enclosure which (just like your device) doesn't
#   > need the entry (so when I plug it, I get the same warning as you).
#   >
#   > However, I also happen to own two 5 1/4'' CD-ROM enclosures, for which
#   > this entry *is* necessary. I tried again, very recently to remove my
#   > unusual_devs.h entry, and it prevented them from working.
#   >
#   > So, I think the entry should be kept (it does more good than harm), but
#   > maybe it could get some tweaking ? If there's a way to recognize these
#   > "CD-ROM enclosure" bridge chips and exclude the others, I'm all for it.
#   
#   
#   
#   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/07/19 04:26:41-07:00 stern@rowland.harvard.edu +6 -2
#   USB: unusual_devs.h update
# 
# ChangeSet
#   2004/07/30 16:38:21-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: unusual_devs.h update
#   
#   Just like in as347, we have another example of descriptors that vary from
#   device to device.  Please apply this patch to suppress the warning
#   message.
#   
#   On Fri, 16 Jul 2004, Ken Yap wrote:
#   
#   > Jul 16 21:44:20 media kernel: usb-storage: This device (090a,1001,0100 S 06 P 50) has an unneeded Protocol entry in unusual_devs.h
#   > Jul 16 21:44:20 media kernel:    Please send a copy of this message to <linux-usb-devel@lists.sourceforge.net>
#   
#   
#   
#   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/07/19 04:35:14-07:00 stern@rowland.harvard.edu +1 -1
#   USB: unusual_devs.h update
# 
# ChangeSet
#   2004/07/30 16:38:02-07:00 johann.cardon@free.fr 
#   [PATCH] USB: New unusual_devs.h entry
#   
#   Please merge this new entry for the unusual_devs.h database.
#   
#   From: Johann Cardon <johann.cardon@free.fr>
#   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/07/19 04:43:38-07:00 johann.cardon@free.fr +9 -0
#   USB: New unusual_devs.h entry
# 
# ChangeSet
#   2004/07/30 16:37:43-07:00 domen@coderock.org 
#   [PATCH] USB: use list_for_each() in core/devices.c
#   
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/devices.c
#   2004/07/11 05:41:36-07:00 domen@coderock.org +1 -1
#   USB: use list_for_each() in core/devices.c
# 
# ChangeSet
#   2004/07/30 16:37:24-07:00 domen@coderock.org 
#   [PATCH] USB: use list_for_each() in class/usb-midi.c
#   
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/class/usb-midi.c
#   2004/07/11 05:41:39-07:00 domen@coderock.org +3 -3
#   USB: use list_for_each() in class/usb-midi.c
# 
# ChangeSet
#   2004/07/30 16:37:05-07:00 domen@coderock.org 
#   [PATCH] USB: use list_for_each() in class/audio.c
#   
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/class/audio.c
#   2004/07/11 05:41:32-07:00 domen@coderock.org +6 -6
#   USB: use list_for_each() in class/audio.c
# 
# ChangeSet
#   2004/07/30 16:36:42-07:00 ganesh@veritas.com 
#   [PATCH] USB: fix for ipaq.c
#   
#   as per pete and greg's input, fixing only the uninitialized variable.
#   
#   Signed-off-by: Ganesh Varadarajan <ganesh@veritas.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/ipaq.c
#   2004/07/22 08:42:31-07:00 ganesh@veritas.com +1 -0
#   USB: fix for ipaq.c
# 
# ChangeSet
#   2004/07/30 16:36:24-07:00 phil@ipom.com 
#   [PATCH] USB: Debug fix in pl2303
#   
#   This is a simple patch to fix a debug statement where the arguements are
#   in the wrong order. Resending it with a CC to Greg and a signed-off-by line.
#   
#   Signed-off-by: Phil Dibowitz <phil@ipom.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/pl2303.c
#   2004/07/24 00:50:24-07:00 phil@ipom.com +1 -1
#   USB: Debug fix in pl2303
# 
# ChangeSet
#   2004/07/30 16:36:03-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Remove unneeded unusual_devs.h entry
#   
#   According to Jonas Fährmann, the very first entry in unusual_devs.h isn't
#   needed.  In fact, I can't tell why it was there in the first place...
#   unless some earlier device in the product line had incorrect descriptor
#   values.
#   
#   
#   On Mon, 26 Jul 2004, Jonas Fährmann wrote:
#   
#   > usb-storage: This device (03ee,0000,0045 S 02 P 00) has unneeded SubClass and Protocol entries in unusual_devs.h
#   >    Please send a copy of this message to <linux-usb-devel@lists.sourceforge.net>
#   
#   
#   
#   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/07/27 04:39:20-07:00 stern@rowland.harvard.edu +0 -5
#   USB: Remove unneeded unusual_devs.h entry
# 
# ChangeSet
#   2004/07/30 16:35:44-07:00 abbotti@mev.co.uk 
#   [PATCH] USB: Add support for FT2232C chip to ftdi_sio
#   
#   This patch adds support for the FTDI FT2232C USB to dual serial port
#   converter to the ftdi_sio driver.
#   
#   The patch is based on a fork of the 2.4 ftdi_sio driver by Steven
#   Turner of FTDI, and a preliminary port of these changes to the 2.6
#   ftdi_sio driver by Rus V. Brushkoff.  I've tidied it up and fixed a
#   couple of things.
#   
#   I don't have a FT2232C to test it with, but Steven Turner of FTDI
#   has tested it.  He mentioned a couple of known problems with the
#   driver, but nothing to do with this patch.
#   
#   
#   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/07/27 11:12:46-07:00 abbotti@mev.co.uk +17 -0
#   USB: Add support for FT2232C chip to ftdi_sio
# 
# drivers/usb/serial/ftdi_sio.c
#   2004/07/27 11:12:46-07:00 abbotti@mev.co.uk +102 -13
#   USB: Add support for FT2232C chip to ftdi_sio
# 
# ChangeSet
#   2004/07/30 16:35:24-07:00 abbotti@mev.co.uk 
#   [PATCH] USB: ftdi_sio doesn't re-assert DTR modem control line
#   
#   I've dredged up another old ftdi_sio patch that I never Cc'd to you
#   the first time.  Please see Nathan's description below.
#   
#   It applies okay against your usb-2.6 tree, with or without the patch
#   I posted yesterday to support the FT2232C chip and neither patch
#   invalidates the other in any way.
#   
#   
#   On 25/06/2004 21:56, Croy, Nathan wrote:
#   > SUMMARY
#   > =======
#   > ftdi_sio never reasserts modem control lines once the baud has been set to
#   > B0.
#   >
#   > DESCRIPTION
#   > ===========
#   > Setting the baud to B0 (hangup) drops DTR.  When the baud is raised again,
#   > DTR is not raised.  This can cause a modem to ignore any commands sent to it
#   > until the device is closed and reopened.  This renders minicom (and other
#   > software) useless, unless you instruct the modem to ignore DTR.
#   >
#   > The following patch is intended to make ftdi_sio act like other serial
#   > devices I have used (i.e. the standard serial ports (/dev/ttyS*) and
#   > stallion ports (/dev/ttyE*)).  Upon setting the baud to something other than
#   > B0, it ensures the modem control lines are set back to the way they were
#   > when the port was opened.
#   >
#   > Thanks to Ian Abbott for confirming my suspicions:
#   > http://sourceforge.net/mailarchive/forum.php?thread_id=4984710&forum_id=12120
#   
#   Nathan's email suffered from a line-folding bug (blame M$,
#   probably!), so his patch came out corrupted. I'm reposting an
#   uncorrupted version.
#   
#   
#   Signed off by: Ian Abbott <abbotti@mev.co.uk>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/ftdi_sio.c
#   2004/06/24 05:29:22-07:00 abbotti@mev.co.uk +7 -0
#   USB: ftdi_sio doesn't re-assert DTR modem control line
# 
# ChangeSet
#   2004/07/30 16:35:06-07:00 laforge@netfilter.org 
#   [PATCH] USB: Hackish fix for cyberjack driver
#   
#   The following patch is in use by REINER-SCT customres for some time and
#   works for them in about 90% of all cases.  I would really appreciate
#   this going in before 2.6.8-final, since the device doesn't work at all
#   with current 2.6.x driver.
#   
#   Changes:
#   - bump version number
#   - open interrupt endpoint in startup() rather than open
#   
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/cyberjack.c
#   2004/07/28 08:40:57-07:00 laforge@netfilter.org +16 -17
#   USB: Hackish fix for cyberjack driver
# 
# ChangeSet
#   2004/07/30 16:34:47-07:00 akpm@osdl.org 
#   [PATCH] USB: gcc-3.5 fixes
#   
#   From: Andi Kleen <ak@muc.de>
#   
#   Trivial gcc-3.5 build fixes.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/class/usblp.c
#   2004/07/10 17:52:27-07:00 akpm@osdl.org +1 -1
#   USB: gcc-3.5 fixes
# 
# ChangeSet
#   2004/07/30 16:34:27-07:00 david-b@pacbell.net 
#   [PATCH] USB: usb hub docs and locktree()
#   
#   Please merge; the CONFIG_USB_SUSPEND patch depends on it.
#   
#   This hub patch:
#   
#    - updates internal docs about locking, matching current usage
#      for device state spinlock and dev->serialize semaphore
#   
#    - adds locktree() to use with signaling that affect everything
#      downstream of a given device ... right now just khubd uses it,
#      but usb_reset_device() should too (not just with hub resets...)
#   
#    - adds hub_quiesce()/hub_reactivate() ... former is used now
#      during shutdown, both are needed in suspend/resume paths
#   
#   Net change in behavior for current systems should be nothing.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/hub.h
#   2004/07/29 01:31:30-07:00 david-b@pacbell.net +2 -0
#   USB: usb hub docs and locktree()
# 
# drivers/usb/core/hub.c
#   2004/07/29 03:00:59-07:00 david-b@pacbell.net +105 -21
#   USB: usb hub docs and locktree()
# 
# ChangeSet
#   2004/07/30 16:34:04-07:00 david-b@pacbell.net 
#   [PATCH] USB: add CONFIG_USB_SUSPEND
#   
#   This is the core of the USB_SUSPEND functionality.  Please merge.
#   
#   This adds an experimental CONFIG_USB_SUSPEND option, which supports the
#   USB "suspend" state.  Linux-USB hosts have previously ignored that state.
#   
#       -	New driver API calls, usb_suspend_device() and its
#   	sibling usb_resume_device().
#   
#       -	Access to those calls through sysfs, such as
#   		echo -n 2 > power/state
#   		echo -n 0 > power/state
#   
#   That can be used to reduce the power consumption of any given USB device,
#   then re-activate it later.  Eventually, most USB device drivers should
#   probably suspend idle USB devices.
#   
#   One problem with this patch:  USB drivers without suspend() callbacks
#   may badly misbehave.  Right now only hub drivers know suspend().  If the
#   driver core didn't self-deadlock when we try it, unbinding those drivers
#   from those devices (then re-enumerating on resume) would be perfect...
#   the current compromise is just to emit a warning message.
#   
#   In conjunction with host controller driver support (already merged for
#   OHCI and EHCI), PCI host controllers will issue the PME# wakeup signal
#   when a USB keyboard starts remote wakeup signaling.  (But the keyboard
#   wasn't usable later, since HID doesn't try to suspend.)
#   
#   I understand some ACPI patches are circulating, and maybe already in
#   the MM tree, to make a suspended system wake up given PME# signaling.
#   It'd be great if someone made that work transparently with USB, but
#   for now I'm told it'll need some sysfs setup first.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/hub.c
#   2004/07/29 03:00:59-07:00 david-b@pacbell.net +484 -1
#   USB: add CONFIG_USB_SUSPEND
# 
# drivers/usb/core/Kconfig
#   2004/07/29 01:31:44-07:00 david-b@pacbell.net +11 -0
#   USB: add CONFIG_USB_SUSPEND
# 
# Documentation/DocBook/usb.tmpl
#   2004/07/29 01:42:14-07:00 david-b@pacbell.net +1 -0
#   USB: add CONFIG_USB_SUSPEND
# 
# ChangeSet
#   2004/07/30 16:33:45-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Make removable-LUN support a non-test option in the g_file_storage driver
#   
#   This patch follows the suggestions sent by Todd Fischer and Diego Dompe
#   for making removable-LUN support part of the normal non-testing version of
#   the g_file_storage driver.  It also moves LUN device registration to the
#   correct place and eliminates a code path that stalls the bulk-out pipe in
#   a racy way.
#   
#   There are also some smaller changes: update some comments, add initial
#   debugging support for USB suspend/resume, and miscellaneous code cleanups.
#   Last but not least, the driver has been sufficiently stable for
#   sufficiently long that it's fair to remove the "(DEVELOPMENT)" warning in
#   Kconfig.
#   
#   
#   
#   Sent-by: Todd Fischer <toddf@cadenux.com>
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/file_storage.c
#   2004/07/28 04:17:49-07:00 stern@rowland.harvard.edu +94 -75
#   USB: Make removable-LUN support a non-test option in the g_file_storage driver
# 
# drivers/usb/gadget/Kconfig
#   2004/07/28 04:08:24-07:00 stern@rowland.harvard.edu +2 -2
#   USB: Make removable-LUN support a non-test option in the g_file_storage driver
# 
# ChangeSet
#   2004/07/30 16:33:20-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Fix NULL-pointer bug in dummy_hcd
#   
#   This patch fixes a NULL-pointer-dereference bug in the dummy_hcd driver.
#   It also makes the code slightly more elegant and removes an unnecessary
#   buffer-overflow test.  Unfortunately it's still a little bit racy, but
#   this is a fault it shares with other gadget controller drivers, like
#   net2280.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/dummy_hcd.c
#   2004/07/29 05:10:55-07:00 stern@rowland.harvard.edu +4 -5
#   USB: Fix NULL-pointer bug in dummy_hcd
# 
diff -Nru a/Documentation/DocBook/usb.tmpl b/Documentation/DocBook/usb.tmpl
--- a/Documentation/DocBook/usb.tmpl	2004-08-04 17:58:04 -07:00
+++ b/Documentation/DocBook/usb.tmpl	2004-08-04 17:58:04 -07:00
@@ -251,6 +251,7 @@
 !Edrivers/usb/core/message.c
 !Edrivers/usb/core/file.c
 !Edrivers/usb/core/usb.c
+!Edrivers/usb/core/hub.c
     </chapter>
 
     <chapter><title>Host Controller APIs</title>
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	2004-08-04 17:58:03 -07:00
+++ b/MAINTAINERS	2004-08-04 17:58:03 -07:00
@@ -2299,6 +2299,13 @@
 W:	http://www.connecttech.com
 S:	Supported
 
+USB SN9C10[12] DRIVER
+P:	Luca Risolia
+M:	luca.risolia@studio.unibo.it
+L:	linux-usb-devel@lists.sourceforge.net
+W:	http://go.lamarinapunto.com
+S:	Maintained
+
 USB SUBSYSTEM
 P:	Greg Kroah-Hartman
 M:	greg@kroah.com
diff -Nru a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
--- a/drivers/usb/class/audio.c	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/class/audio.c	2004-08-04 17:58:04 -07:00
@@ -1954,9 +1954,9 @@
 	struct usb_audio_state *s;
 
 	down(&open_sem);
-	for (devs = audiodevs.next; devs != &audiodevs; devs = devs->next) {
+	list_for_each(devs, &audiodevs) {
 		s = list_entry(devs, struct usb_audio_state, audiodev);
-		for (mdevs = s->mixerlist.next; mdevs != &s->mixerlist; mdevs = mdevs->next) {
+		list_for_each(mdevs, &s->mixerlist) {
 			ms = list_entry(mdevs, struct usb_mixerdev, list);
 			if (ms->dev_mixer == minor)
 				goto mixer_found;
@@ -2644,9 +2644,9 @@
 
 	for (;;) {
 		down(&open_sem);
-		for (devs = audiodevs.next; devs != &audiodevs; devs = devs->next) {
+		list_for_each(devs, &audiodevs) {
 			s = list_entry(devs, struct usb_audio_state, audiodev);
-			for (adevs = s->audiolist.next; adevs != &s->audiolist; adevs = adevs->next) {
+			list_for_each(adevs, &s->audiolist) {
 				as = list_entry(adevs, struct usb_audiodev, list);
 				if (!((as->dev_audio ^ minor) & ~0xf))
 					goto device_found;
@@ -3835,7 +3835,7 @@
 	usb_set_intfdata (intf, NULL);
 
 	/* deregister all audio and mixer devices, so no new processes can open this device */
-	for(list = s->audiolist.next; list != &s->audiolist; list = list->next) {
+	list_for_each(list, &s->audiolist) {
 		as = list_entry(list, struct usb_audiodev, list);
 		usbin_disc(as);
 		usbout_disc(as);
@@ -3847,7 +3847,7 @@
 		}
 		as->dev_audio = -1;
 	}
-	for(list = s->mixerlist.next; list != &s->mixerlist; list = list->next) {
+	list_for_each(list, &s->mixerlist) {
 		ms = list_entry(list, struct usb_mixerdev, list);
 		if (ms->dev_mixer >= 0) {
 			unregister_sound_mixer(ms->dev_mixer);
diff -Nru a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
--- a/drivers/usb/class/cdc-acm.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/class/cdc-acm.c	2004-08-04 17:58:03 -07:00
@@ -583,19 +583,25 @@
 	}
 
 	if (!union_header) {
-		dev_dbg(&intf->dev,"No union descriptor, giving up\n");
-		return -ENODEV;
-	}
-
-	control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0);
-	data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0));
-	if (!control_interface || !data_interface) {
-		dev_dbg(&intf->dev,"no interfaces\n");
-		return -ENODEV;
+		if (call_interface_num > 0) {
+			dev_dbg(&intf->dev,"No union descriptor, using call management descriptor\n");
+			data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num));
+			control_interface = intf;
+		} else {
+			dev_dbg(&intf->dev,"No union descriptor, giving up\n");
+			return -ENODEV;
+		}
+	} else {
+		control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0);
+		data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0));
+		if (!control_interface || !data_interface) {
+			dev_dbg(&intf->dev,"no interfaces\n");
+			return -ENODEV;
+		}
 	}
 	
-	if (data_interface_num != call_interface_num)
-		dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported.");
+		if (data_interface_num != call_interface_num)
+			dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported.");
 
 	if (usb_interface_claimed(data_interface)) { /* valid in this context */
 		dev_dbg(&intf->dev,"The data interface isn't available\n");
diff -Nru a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c
--- a/drivers/usb/class/usb-midi.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/class/usb-midi.c	2004-08-04 17:58:03 -07:00
@@ -55,39 +55,39 @@
 /* ------------------------------------------------------------------------- */
 
 static int singlebyte = 0;
-MODULE_PARM(singlebyte,"i");
+module_param(singlebyte, int, 0);
 MODULE_PARM_DESC(singlebyte,"Enable sending MIDI messages with single message packet");
 
 static int maxdevices = 4;
-MODULE_PARM(maxdevices,"i");
+module_param(maxdevices, int, 0);
 MODULE_PARM_DESC(maxdevices,"Max number of allocatable MIDI device");
 
 static int uvendor     = -1;
-MODULE_PARM(uvendor,"i");
+module_param(uvendor, int, 0);
 MODULE_PARM_DESC(uvendor, "The USB Vendor ID of a semi-compliant interface");
 
 static int uproduct    = -1;
-MODULE_PARM(uproduct,"i");
+module_param(uproduct, int, 0);
 MODULE_PARM_DESC(uproduct, "The USB Product ID of a semi-compliant interface");
 
 static int uinterface  = -1;
-MODULE_PARM(uinterface,"i");
+module_param(uinterface, int, 0);
 MODULE_PARM_DESC(uinterface, "The Interface number of a semi-compliant interface");
 
 static int ualt        = -1;
-MODULE_PARM(ualt,"i");
+module_param(ualt, int, 0);
 MODULE_PARM_DESC(ualt, "The optional alternative setting of a semi-compliant interface");
 
 static int umin        = -1;
-MODULE_PARM(umin,"i");
+module_param(umin, int, 0);
 MODULE_PARM_DESC(umin, "The input endpoint of a semi-compliant interface");
 
 static int umout       = -1;
-MODULE_PARM(umout,"i");
+module_param(umout, int, 0);
 MODULE_PARM_DESC(umout, "The output endpoint of a semi-compliant interface");
 
 static int ucable      = -1;
-MODULE_PARM(ucable,"i");
+module_param(ucable, int, 0);
 MODULE_PARM_DESC(ucable, "The cable number used for a semi-compliant interface");
 
 /** Note -- the usb_string() returns only Latin-1 characters.
@@ -95,7 +95,7 @@
  * unicode16LE-to-JIS routine is needed to wrap around usb_get_string().
  **/
 static unsigned short ulangid      = 0x0409; /** 0x0411 for Japanese **/
-MODULE_PARM(ulangid,"h");
+module_param(ulangid, ushort, 0);
 MODULE_PARM_DESC(ulangid, "The optional preferred USB Language ID for all devices");
 
 MODULE_AUTHOR("NAGANO Daisuke <breeze.nagano@nifty.ne.jp>");
@@ -823,9 +823,9 @@
 
 	for(;;) {
 		down(&open_sem);
-		for (devs = mididevs.next; devs != &mididevs; devs = devs->next) {
+		list_for_each(devs, &mididevs) {
 			s = list_entry(devs, struct usb_midi_state, mididev);
-			for (mdevs = s->midiDevList.next; mdevs != &s->midiDevList; mdevs = mdevs->next) {
+			list_for_each(mdevs, &s->midiDevList) {
 				m = list_entry(mdevs, struct usb_mididev, list);
 				if ( !((m->dev_midi ^ minor) & ~0xf) )
 					goto device_found;
@@ -2018,7 +2018,7 @@
 	s->usbdev = NULL;
 	usb_set_intfdata (intf, NULL);
 
-	for ( list = s->midiDevList.next; list != &s->midiDevList; list = list->next ) {
+	list_for_each(list, &s->midiDevList) {
 		m = list_entry(list, struct usb_mididev, list);
 		wake_up(&(m->min.ep->wait));
 		wake_up(&(m->mout.ep->wait));
diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
--- a/drivers/usb/class/usblp.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/class/usblp.c	2004-08-04 17:58:03 -07:00
@@ -221,7 +221,7 @@
 static int usblp_cache_device_id_string(struct usblp *usblp);
 
 /* forward reference to make our lives easier */
-extern struct usb_driver usblp_driver;
+static struct usb_driver usblp_driver;
 
 /*
  * Functions for usblp control messages.
@@ -1208,6 +1208,6 @@
 
 MODULE_AUTHOR( DRIVER_AUTHOR );
 MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_PARM(proto_bias, "i");
+module_param(proto_bias, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(proto_bias, "Favourite protocol number");
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
--- a/drivers/usb/core/Kconfig	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/core/Kconfig	2004-08-04 17:58:04 -07:00
@@ -60,3 +60,14 @@
 
 	  If you are unsure about this, say N here.
 
+config USB_SUSPEND
+	bool "USB suspend/resume (EXPERIMENTAL)"
+	depends on USB && PM && EXPERIMENTAL
+	help
+	  If you say Y here, you can use driver calls or the sysfs
+	  "power/state" file to suspend or resume individual USB
+	  peripherals.  There are many related features, such as
+	  remote wakeup and driver-specific suspend processing, that
+	  may not yet work as expected.
+
+	  If you are unsure about this, say N here.
diff -Nru a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
--- a/drivers/usb/core/devices.c	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/core/devices.c	2004-08-04 17:58:04 -07:00
@@ -584,7 +584,7 @@
 
 	/* enumerate busses */
 	down (&usb_bus_list_lock);
-	for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) {
+	list_for_each(buslist, &usb_bus_list) {
 		/* print devices for this bus */
 		bus = list_entry(buslist, struct usb_bus, bus_list);
 
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/core/hub.c	2004-08-04 17:58:03 -07:00
@@ -36,7 +36,7 @@
 #include "hcd.h"
 #include "hub.h"
 
-/* Protect all struct usb_device state members */
+/* Protect struct usb_device state and children members */
 static spinlock_t device_state_lock = SPIN_LOCK_UNLOCKED;
 
 /* Wakes up khubd */
@@ -143,7 +143,7 @@
 	unsigned		changed = 0;
 	int			cursor = -1;
 
-	if (hdev->state != USB_STATE_CONFIGURED)
+	if (hdev->state != USB_STATE_CONFIGURED || hub->quiescing)
 		return;
 
 	for (i = 0; i < hub->descriptor->bNbrPorts; i++) {
@@ -269,6 +269,9 @@
 	spin_unlock(&hub_event_lock);
 
 resubmit:
+	if (hub->quiescing)
+		return;
+
 	if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0
 			&& status != -ENODEV && status != -EPERM)
 		dev_err (&hub->intf->dev, "resubmit --> %d\n", status);
@@ -623,6 +626,33 @@
 
 static unsigned highspeed_hubs;
 
+static void hub_quiesce(struct usb_hub *hub)
+{
+	/* stop khubd and related activity */
+	hub->quiescing = 1;
+	usb_kill_urb(hub->urb);
+	if (hub->has_indicators)
+		cancel_delayed_work(&hub->leds);
+	if (hub->has_indicators || hub->tt.hub)
+		flush_scheduled_work();
+}
+
+#ifdef	CONFIG_USB_SUSPEND
+
+static void hub_reactivate(struct usb_hub *hub)
+{
+	int	status;
+
+	hub->quiescing = 0;
+	status = usb_submit_urb(hub->urb, GFP_NOIO);
+	if (status < 0)
+		dev_err(&hub->intf->dev, "reactivate --> %d\n", status);
+	if (hub->has_indicators && blinkenlights)
+		schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
+}
+
+#endif
+
 static void hub_disconnect(struct usb_interface *intf)
 {
 	struct usb_hub *hub = usb_get_intfdata (intf);
@@ -637,22 +667,14 @@
 
 	usb_set_intfdata (intf, NULL);
 
-	if (hub->urb) {
-		usb_kill_urb(hub->urb);
-		usb_free_urb(hub->urb);
-		hub->urb = NULL;
-	}
+	hub_quiesce(hub);
+	usb_free_urb(hub->urb);
+	hub->urb = NULL;
 
 	spin_lock_irq(&hub_event_lock);
 	list_del_init(&hub->event_list);
 	spin_unlock_irq(&hub_event_lock);
 
-	/* assuming we used keventd, it must quiesce too */
-	if (hub->has_indicators)
-		cancel_delayed_work (&hub->leds);
-	if (hub->has_indicators || hub->tt.hub)
-		flush_scheduled_work ();
-
 	if (hub->descriptor) {
 		kfree(hub->descriptor);
 		hub->descriptor = NULL;
@@ -772,6 +794,7 @@
 	}
 }
 
+/* caller has locked the hub */
 static int hub_reset(struct usb_hub *hub)
 {
 	struct usb_device *hdev = hub->hdev;
@@ -801,6 +824,7 @@
 	return 0;
 }
 
+/* caller has locked the hub */
 /* FIXME!  This routine should be subsumed into hub_reset */
 static void hub_start_disconnect(struct usb_device *hdev)
 {
@@ -832,12 +856,65 @@
 	udev->state = USB_STATE_NOTATTACHED;
 }
 
+/* grab device/port lock, returning index of that port (zero based).
+ * protects the upstream link used by this device from concurrent
+ * tree operations like suspend, resume, reset, and disconnect, which
+ * apply to everything downstream of a given port.
+ */
+static int locktree(struct usb_device *udev)
+{
+	int			t;
+	struct usb_device	*hdev;
+
+	if (!udev)
+		return -ENODEV;
+
+	/* root hub is always the first lock in the series */
+	hdev = udev->parent;
+	if (!hdev) {
+		down(&udev->serialize);
+		return 0;
+	}
+
+	/* on the path from root to us, lock everything from
+	 * top down, dropping parent locks when not needed
+	 *
+	 * NOTE: if disconnect were to ignore the locking, we'd need
+	 * to get extra refcounts to everything since hdev->children
+	 * and udev->parent could be invalidated while we work...
+	 */
+	t = locktree(hdev);
+	if (t < 0)
+		return t;
+	spin_lock_irq(&device_state_lock);
+	for (t = 0; t < hdev->maxchild; t++) {
+		if (hdev->children[t] == udev) {
+			/* everything is fail-fast once disconnect
+			 * processing starts
+			 */
+			if (udev->state == USB_STATE_NOTATTACHED)
+				break;
+
+			/* when everyone grabs locks top->bottom,
+			 * non-overlapping work may be concurrent
+			 */
+			spin_unlock_irq(&device_state_lock);
+			down(&udev->serialize);
+			up(&hdev->serialize);
+			return t;
+		}
+	}
+	spin_unlock_irq(&device_state_lock);
+	up(&hdev->serialize);
+	return -ENODEV;
+}
+
 /**
  * usb_set_device_state - change a device's current state (usbcore-internal)
  * @udev: pointer to device whose state should be changed
  * @new_state: new state value to be stored
  *
- * udev->state is _not_ protected by the udev->serialize semaphore.  This
+ * udev->state is _not_ protected by the device lock.  This
  * is so that devices can be marked as disconnected as soon as possible,
  * without having to wait for the semaphore to be released.  Instead,
  * changes to the state must be protected by the device_state_lock spinlock.
@@ -897,7 +974,7 @@
 
 /**
  * usb_disconnect - disconnect a device (usbcore-internal)
- * @pdev: pointer to device being disconnected
+ * @pdev: pointer to device being disconnected, into a locked hub
  * Context: !in_interrupt ()
  *
  * Something got disconnected. Get rid of it, and all of its children.
@@ -921,7 +998,8 @@
 	}
 
 	/* mark the device as inactive, so any further urb submissions for
-	 * this device will fail.
+	 * this device (and any of its children) will fail immediately.
+	 * this quiesces everyting except pending urbs.
 	 */
 	usb_set_device_state(udev, USB_STATE_NOTATTACHED);
 
@@ -940,6 +1018,7 @@
 
 	/* deallocate hcd/hardware state ... nuking all pending urbs and
 	 * cleaning up all state associated with the current configuration
+	 * so that the hardware is now fully quiesced.
 	 */
 	usb_disable_device(udev, 0);
 
@@ -952,7 +1031,7 @@
 	usbfs_remove_device(udev);
 	usb_remove_sysfs_dev_files(udev);
 
-	/* Avoid races with recursively_mark_NOTATTACHED() */
+	/* Avoid races with recursively_mark_NOTATTACHED() and locktree() */
 	spin_lock_irq(&device_state_lock);
 	*pdev = NULL;
 	spin_unlock_irq(&device_state_lock);
@@ -1203,6 +1282,7 @@
 		if (status == -ENOTCONN || status == 0) {
 			clear_port_feature(hdev,
 				port + 1, USB_PORT_FEAT_C_RESET);
+			/* FIXME need disconnect() for NOTATTACHED device */
 			usb_set_device_state(udev, status
 					? USB_STATE_NOTATTACHED
 					: USB_STATE_DEFAULT);
@@ -1226,9 +1306,11 @@
 {
 	int ret;
 
-	if (hdev->children[port])
+	if (hdev->children[port]) {
+		/* FIXME need disconnect() for NOTATTACHED device */
 		usb_set_device_state(hdev->children[port],
 				USB_STATE_NOTATTACHED);
+	}
 	ret = clear_port_feature(hdev, port + 1, USB_PORT_FEAT_ENABLE);
 	if (ret)
 		dev_err(hubdev(hdev), "cannot disable port %d (err = %d)\n",
@@ -1239,7 +1321,490 @@
 
 #ifdef	CONFIG_USB_SUSPEND
 
-	/* no USB_SUSPEND yet! */
+/*
+ * Selective port suspend reduces power; most suspended devices draw
+ * less than 500 uA.  It's also used in OTG, along with remote wakeup.
+ * All devices below the suspended port are also suspended.
+ *
+ * Devices leave suspend state when the host wakes them up.  Some devices
+ * also support "remote wakeup", where the device can activate the USB
+ * tree above them to deliver data, such as a keypress or packet.  In
+ * some cases, this wakes the USB host.
+ */
+static int hub_port_suspend(struct usb_device *hdev, int port)
+{
+	int			status;
+	struct usb_device	*udev;
+
+	udev = hdev->children[port - 1];
+	// dev_dbg(hubdev(hdev), "suspend port %d\n", port);
+
+	/* enable remote wakeup when appropriate; this lets the device
+	 * wake up the upstream hub (including maybe the root hub).
+	 *
+	 * NOTE:  OTG devices may issue remote wakeup (or SRP) even when
+	 * we don't explicitly enable it here.
+	 */
+	if (udev->actconfig
+			// && FIXME (remote wakeup enabled on this bus)
+			// ... currently assuming it's always appropriate
+			&& (udev->actconfig->desc.bmAttributes
+				& USB_CONFIG_ATT_WAKEUP) != 0) {
+		status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+				USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
+				USB_DEVICE_REMOTE_WAKEUP, 0,
+				NULL, 0,
+				USB_CTRL_SET_TIMEOUT);
+		if (status)
+			dev_dbg(&udev->dev,
+				"won't remote wakeup, status %d\n",
+				status);
+	}
+
+	/* see 7.1.7.6 */
+	status = set_port_feature(hdev, port, USB_PORT_FEAT_SUSPEND);
+	if (status) {
+		dev_dbg(hubdev(hdev),
+			"can't suspend port %d, status %d\n",
+			port, status);
+		/* paranoia:  "should not happen" */
+		(void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+				USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
+				USB_DEVICE_REMOTE_WAKEUP, 0,
+				NULL, 0,
+				USB_CTRL_SET_TIMEOUT);
+	} else {
+		/* device has up to 10 msec to fully suspend */
+		dev_dbg(&udev->dev, "usb suspend\n");
+		udev->state = USB_STATE_SUSPENDED;
+		msleep(10);
+	}
+	return status;
+}
+
+/*
+ * Devices on USB hub ports have only one "suspend" state, corresponding
+ * to ACPI D2 (PM_SUSPEND_MEM), "may cause the device to lose some context".
+ * State transitions include:
+ *
+ *   - suspend, resume ... when the VBUS power link stays live
+ *   - suspend, disconnect ... VBUS lost
+ *
+ * Once VBUS drop breaks the circuit, the port it's using has to go through
+ * normal re-enumeration procedures, starting with enabling VBUS power.
+ * Other than re-initializing the hub (plug/unplug, except for root hubs),
+ * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
+ * timer, no SRP, no requests through sysfs.
+ */
+static int __usb_suspend_device (struct usb_device *udev, int port, u32 state)
+{
+	int	status;
+
+	if (port < 0)
+		return port;
+
+	/* NOTE:  udev->serialize released on all real returns! */
+
+	if (state <= udev->dev.power.power_state
+			|| state < PM_SUSPEND_MEM
+			|| udev->state == USB_STATE_SUSPENDED
+			|| udev->state == USB_STATE_NOTATTACHED) {
+		up(&udev->serialize);
+		return 0;
+	}
+
+	/* suspend interface drivers; if this is a hub, it
+	 * suspends the child devices
+	 */
+	if (udev->actconfig) {
+		int	i;
+
+		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+			struct usb_interface	*intf;
+			struct usb_driver	*driver;
+
+			intf = udev->actconfig->interface[i];
+			if (state <= intf->dev.power.power_state)
+				continue;
+			if (!intf->dev.driver)
+				continue;
+			driver = to_usb_driver(intf->dev.driver);
+
+			if (driver->suspend) {
+				status = driver->suspend(intf, state);
+				if (intf->dev.power.power_state != state
+						|| status)
+					dev_err(&intf->dev,
+						"suspend %d fail, code %d\n",
+						state, status);
+			}
+
+			/* only drivers with suspend() can ever resume();
+			 * and after power loss, even they won't.
+			 * bus_rescan_devices() can rebind drivers later.
+			 *
+			 * FIXME the PM core self-deadlocks when unbinding
+			 * drivers during suspend/resume ... everything grabs
+			 * dpm_sem (not a spinlock, ugh).  we want to unbind,
+			 * since we know every driver's probe/disconnect works
+			 * even for drivers that can't suspend.
+			 */
+			if (!driver->suspend || state > PM_SUSPEND_MEM) {
+#if 1
+				dev_warn(&intf->dev, "resume is unsafe!\n");
+#else
+				down_write(&usb_bus_type.rwsem);
+				device_release_driver(&intf->dev);
+				up_write(&usb_bus_type.rwsem);
+#endif
+			}
+		}
+	}
+
+	/*
+	 * FIXME this needs port power off call paths too, to help force
+	 * USB into the "generic" PM model.  At least for devices on
+	 * ports that aren't using ganged switching (usually root hubs).
+	 *
+	 * NOTE: SRP-capable links should adopt more aggressive poweroff
+	 * policies (when HNP doesn't apply) once we have mechanisms to
+	 * turn power back on!  (Likely not before 2.7...)
+	 */
+	if (state > PM_SUSPEND_MEM) {
+		dev_warn(&udev->dev, "no poweroff yet, suspending instead\n");
+		state = PM_SUSPEND_MEM;
+	}
+
+	/* "global suspend" of the HC-to-USB interface (root hub), or
+	 * "selective suspend" of just one hub-device link.
+	 */
+	if (!udev->parent) {
+		struct usb_bus	*bus = udev->bus;
+		if (bus && bus->op->hub_suspend)
+			status = bus->op->hub_suspend (bus);
+		else
+			status = -EOPNOTSUPP;
+	} else
+		status = hub_port_suspend(udev->parent, port + 1);
+
+	if (status == 0)
+		udev->dev.power.power_state = state;
+	up(&udev->serialize);
+	return status;
+}
+
+/**
+ * usb_suspend_device - suspend a usb device
+ * @udev: device that's no longer in active use
+ * @state: PM_SUSPEND_MEM to suspend
+ * Context: must be able to sleep; device not locked
+ *
+ * Suspends a USB device that isn't in active use, conserving power.
+ * Devices may wake out of a suspend, if anything important happens,
+ * using the remote wakeup mechanism.  They may also be taken out of
+ * suspend by the host, using usb_resume_device().  It's also routine
+ * to disconnect devices while they are suspended.
+ *
+ * Suspending OTG devices may trigger HNP, if that's been enabled
+ * between a pair of dual-role devices.  That will change roles, such
+ * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral.
+ *
+ * Returns 0 on success, else negative errno.
+ */
+int usb_suspend_device(struct usb_device *udev, u32 state)
+{
+	return __usb_suspend_device(udev, locktree(udev), state);
+}
+
+/*
+ * hardware resume signaling is finished, either because of selective
+ * resume (by host) or remote wakeup (by device) ... now see what changed
+ * in the tree that's rooted at this device.
+ */
+static int finish_port_resume(struct usb_device *udev)
+{
+	int	status;
+	u16	devstatus;
+
+	/* caller owns udev->serialize */
+	dev_dbg(&udev->dev, "usb resume\n");
+	udev->dev.power.power_state = PM_SUSPEND_ON;
+
+	/* usb ch9 identifies four variants of SUSPENDED, based on what
+	 * state the device resumes to.  Linux currently won't see the
+	 * first two on the host side; they'd be inside hub_port_init()
+	 * during many timeouts, but khubd can't suspend until later.
+	 */
+	udev->state = udev->actconfig
+		? USB_STATE_CONFIGURED
+		: USB_STATE_ADDRESS;
+
+ 	/* 10.5.4.5 says be sure devices in the tree are still there.
+ 	 * For now let's assume the device didn't go crazy on resume,
+	 * and device drivers will know about any resume quirks.
+	 */
+	status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
+	if (status < 0)
+		dev_dbg(&udev->dev,
+			"gone after usb resume? status %d\n",
+			status);
+	else if (udev->actconfig) {
+		unsigned	i;
+
+		le16_to_cpus(&devstatus);
+		if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
+			status = usb_control_msg(udev,
+					usb_sndctrlpipe(udev, 0),
+					USB_REQ_CLEAR_FEATURE,
+						USB_RECIP_DEVICE,
+					USB_DEVICE_REMOTE_WAKEUP, 0,
+					NULL, 0,
+					USB_CTRL_SET_TIMEOUT);
+			if (status) {
+				dev_dbg(&udev->dev, "disable remote "
+					"wakeup, status %d\n", status);
+				status = 0;
+			}
+		}
+
+		/* resume interface drivers; if this is a hub, it
+		 * resumes the child devices
+		 */
+		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+			struct usb_interface	*intf;
+			struct usb_driver	*driver;
+
+			intf = udev->actconfig->interface[i];
+			if (intf->dev.power.power_state == PM_SUSPEND_ON)
+				continue;
+			if (!intf->dev.driver) {
+				/* FIXME maybe force to alt 0 */
+				continue;
+			}
+			driver = to_usb_driver(intf->dev.driver);
+
+			/* bus_rescan_devices() may rebind drivers */
+			if (!driver->resume)
+				continue;
+
+			/* can we do better than just logging errors? */
+			status = driver->resume(intf);
+			if (intf->dev.power.power_state != PM_SUSPEND_ON
+					|| status)
+				dev_dbg(&intf->dev,
+					"resume fail, state %d code %d\n",
+					intf->dev.power.power_state, status);
+		}
+		status = 0;
+
+	} else if (udev->devnum <= 0) {
+		dev_dbg(&udev->dev, "bogus resume!\n");
+		status = -EINVAL;
+	}
+	return status;
+}
+
+static int
+hub_port_resume(struct usb_device *hdev, int port)
+{
+	int			status;
+	struct usb_device	*udev;
+
+	udev = hdev->children[port - 1];
+	// dev_dbg(hubdev(hdev), "resume port %d\n", port);
+
+	/* see 7.1.7.7; affects power usage, but not budgeting */
+	status = clear_port_feature(hdev, port, USB_PORT_FEAT_SUSPEND);
+	if (status) {
+		dev_dbg(&hdev->actconfig->interface[0]->dev,
+			"can't resume port %d, status %d\n",
+			port, status);
+	} else {
+		u16		devstatus;
+		u16		portchange;
+
+		/* drive resume for at least 20 msec */
+		dev_dbg(&udev->dev, "RESUME\n");
+		msleep(25);
+
+#define LIVE_FLAGS	( USB_PORT_STAT_POWER \
+			| USB_PORT_STAT_ENABLE \
+			| USB_PORT_STAT_CONNECTION)
+
+		/* Virtual root hubs can trigger on GET_PORT_STATUS to
+		 * stop resume signaling.  Then finish the resume
+		 * sequence.
+		 */
+		devstatus = portchange = 0;
+		status = hub_port_status(hdev, port - 1,
+				&devstatus, &portchange);
+		if (status < 0
+				|| (devstatus & LIVE_FLAGS) != LIVE_FLAGS
+				|| (devstatus & USB_PORT_STAT_SUSPEND) != 0
+				) {
+			dev_dbg(&hdev->actconfig->interface[0]->dev,
+				"port %d status %04x.%04x after resume, %d\n",
+				port, portchange, devstatus, status);
+		} else {
+			/* TRSMRCY = 10 msec */
+			msleep(10);
+			status = finish_port_resume(udev);
+		}
+	}
+	if (status < 0)
+		status = hub_port_disable(hdev, port);
+
+	return status;
+}
+
+static int hub_resume (struct usb_interface *intf);
+
+/**
+ * usb_resume_device - re-activate a suspended usb device
+ * @udev: device to re-activate
+ * Context: must be able to sleep; device not locked
+ *
+ * This will re-activate the suspended device, increasing power usage
+ * while letting drivers communicate again with its endpoints.
+ * USB resume explicitly guarantees that the power session between
+ * the host and the device is the same as it was when the device
+ * suspended.
+ *
+ * Returns 0 on success, else negative errno.
+ */
+int usb_resume_device(struct usb_device *udev)
+{
+	int			port, status;
+
+	port = locktree(udev);
+	if (port < 0)
+		return port;
+
+	/* "global resume" of the HC-to-USB interface (root hub), or
+	 * selective resume of one hub-to-device port
+	 */
+	if (!udev->parent) {
+		struct usb_bus	*bus = udev->bus;
+		if (bus && bus->op->hub_resume)
+			status = bus->op->hub_resume (bus);
+		else
+			status = -EOPNOTSUPP;
+		if (status == 0) {
+			/* TRSMRCY = 10 msec */
+			msleep(10);
+			status = hub_resume (bus->root_hub
+					->actconfig->interface[0]);
+		}
+	} else if (udev->state == USB_STATE_SUSPENDED) {
+		status = hub_port_resume(udev->parent, port + 1);
+	} else {
+		status = 0;
+		udev->dev.power.power_state = PM_SUSPEND_ON;
+	}
+	if (status < 0) {
+		dev_dbg(&udev->dev, "can't resume, status %d\n",
+			status);
+	}
+
+	up(&udev->serialize);
+
+	/* rebind drivers that had no suspend() */
+	bus_rescan_devices(&usb_bus_type);
+
+	return status;
+}
+
+static int remote_wakeup(struct usb_device *udev)
+{
+	int	status = 0;
+
+	/* don't repeat RESUME sequence if this device
+	 * was already woken up by some other task
+	 */
+	down(&udev->serialize);
+	if (udev->state == USB_STATE_SUSPENDED) {
+		dev_dbg(&udev->dev, "RESUME (wakeup)\n");
+		/* TRSMRCY = 10 msec */
+		msleep(10);
+		status = finish_port_resume(udev);
+	}
+	up(&udev->serialize);
+	return status;
+}
+
+static int hub_suspend(struct usb_interface *intf, u32 state)
+{
+	struct usb_hub		*hub = usb_get_intfdata (intf);
+	struct usb_device	*hdev = hub->hdev;
+	unsigned		port;
+	int			status;
+
+	/* stop khubd and related activity */
+	hub_quiesce(hub);
+
+	/* then suspend every port */
+	for (port = 0; port < hdev->maxchild; port++) {
+		struct usb_device	*udev;
+
+		udev = hdev->children [port];
+		if (!udev)
+			continue;
+		down(&udev->serialize);
+		status = __usb_suspend_device(udev, port, state);
+		if (status < 0)
+			dev_dbg(&intf->dev, "suspend port %d --> %d\n",
+				port, status);
+	}
+
+	intf->dev.power.power_state = state;
+	return 0;
+}
+
+static int hub_resume(struct usb_interface *intf)
+{
+	struct usb_device	*hdev = interface_to_usbdev(intf);
+	struct usb_hub		*hub = usb_get_intfdata (intf);
+	unsigned		port;
+	int			status;
+
+	for (port = 0; port < hdev->maxchild; port++) {
+		struct usb_device	*udev;
+		u16			portstat, portchange;
+
+		udev = hdev->children [port];
+		status = hub_port_status(hdev, port, &portstat, &portchange);
+		if (status == 0) {
+			if (portchange & USB_PORT_STAT_C_SUSPEND) {
+				clear_port_feature(hdev, port + 1,
+					USB_PORT_FEAT_C_SUSPEND);
+				portchange &= ~USB_PORT_STAT_C_SUSPEND;
+			}
+
+			/* let khubd handle disconnects etc */
+			if (portchange)
+				continue;
+		}
+
+		if (!udev)
+			continue;
+		down (&udev->serialize);
+		if (portstat & USB_PORT_STAT_SUSPEND)
+			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)
+				dev_dbg(&intf->dev, "resume port %d --> %d\n",
+					port, status);
+		}
+		up(&udev->serialize);
+	}
+	intf->dev.power.power_state = PM_SUSPEND_ON;
+
+	hub_reactivate(hub);
+	return 0;
+}
 
 #else	/* !CONFIG_USB_SUSPEND */
 
@@ -1574,6 +2139,7 @@
  *	a port enable-change occurs (often caused by EMI);
  *	usb_reset_device() encounters changed descriptors (as from
  *		a firmware download)
+ * caller already locked the hub
  */
 static void hub_port_connect_change(struct usb_hub *hub, int port,
 					u16 portstatus, u16 portchange)
@@ -1780,7 +2346,8 @@
 
 		/* Lock the device, then check to see if we were
 		 * disconnected while waiting for the lock to succeed. */
-		down(&hdev->serialize);
+		if (locktree(hdev) < 0)
+			break;
 		if (hdev->state != USB_STATE_CONFIGURED ||
 				!hdev->actconfig ||
 				hub != usb_get_intfdata(
@@ -2034,7 +2601,7 @@
 }
 
 /**
- * usb_reset_devce - perform a USB port reset to reinitialize a device
+ * usb_reset_device - perform a USB port reset to reinitialize a device
  * @udev: device to reset (not in SUSPENDED or NOTATTACHED state)
  *
  * WARNING - don't reset any device unless drivers for all of its
@@ -2123,7 +2690,7 @@
 		struct usb_interface *intf = udev->actconfig->interface[i];
 		struct usb_interface_descriptor *desc;
 
-		/* set_interface resets host side toggle and halt status even
+		/* set_interface resets host side toggle even
 		 * for altsetting zero.  the interface may have no driver.
 		 */
 		desc = &intf->cur_altsetting->desc;
diff -Nru a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
--- a/drivers/usb/core/hub.h	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/core/hub.h	2004-08-04 17:58:03 -07:00
@@ -214,6 +214,8 @@
 
 	u8			power_budget;	/* in 2mA units; or zero */
 
+	unsigned		quiescing:1;
+
 	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	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/core/inode.c	2004-08-04 17:58:03 -07:00
@@ -345,30 +345,13 @@
 	return 0;
 }
 
-static void d_unhash(struct dentry *dentry)
-{
-	dget(dentry);
-	spin_lock(&dcache_lock);
-	switch (atomic_read(&dentry->d_count)) {
-	default:
-		spin_unlock(&dcache_lock);
-		shrink_dcache_parent(dentry);
-		spin_lock(&dcache_lock);
-		if (atomic_read(&dentry->d_count) != 2)
-			break;
-	case 2:
-		__d_drop(dentry);
-	}
-	spin_unlock(&dcache_lock);
-}
-
 static int usbfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
 	int error = -ENOTEMPTY;
 	struct inode * inode = dentry->d_inode;
 
 	down(&inode->i_sem);
-	d_unhash(dentry);
+	dentry_unhash(dentry);
 	if (usbfs_empty(dentry)) {
 		dentry->d_inode->i_nlink -= 2;
 		dput(dentry);
diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
--- a/drivers/usb/core/message.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/core/message.c	2004-08-04 17:58:03 -07:00
@@ -577,8 +577,13 @@
 				USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
 				(type << 8) + index, 0, buf, size,
 				HZ * USB_CTRL_GET_TIMEOUT);
-		if (!(result == 0 || result == -EPIPE))
-			break;
+		if (result == 0 || result == -EPIPE)
+			continue;
+		if (result > 1 && ((u8 *)buf)[1] != type) {
+			result = -EPROTO;
+			continue;
+		}
+		break;
 	}
 	return result;
 }
diff -Nru a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
--- a/drivers/usb/gadget/Kconfig	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/gadget/Kconfig	2004-08-04 17:58:03 -07:00
@@ -275,7 +275,7 @@
 	  dynamically linked module called "gadgetfs".
 
 config USB_FILE_STORAGE
-	tristate "File-backed Storage Gadget (DEVELOPMENT)"
+	tristate "File-backed Storage Gadget"
 	# we don't support the SA1100 because of its limitations
 	depends on USB_GADGET_SA1100 = n
 	help
@@ -288,7 +288,7 @@
 	  dynamically linked module called "g_file_storage".
 
 config USB_FILE_STORAGE_TEST
-	bool "File-backed Storage Gadget test version"
+	bool "File-backed Storage Gadget testing version"
 	depends on USB_FILE_STORAGE
 	default n
 	help
diff -Nru a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
--- a/drivers/usb/gadget/dummy_hcd.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/gadget/dummy_hcd.c	2004-08-04 17:58:03 -07:00
@@ -596,14 +596,13 @@
 
 /* "function" sysfs attribute */
 static ssize_t
-show_function (struct device *_dev, char *buf)
+show_function (struct device *dev, char *buf)
 {
-	struct dummy	*dum = the_controller;
+	struct dummy	*dum = gadget_dev_to_dummy (dev);
 
-	if (!dum->driver->function
-			|| strlen (dum->driver->function) > PAGE_SIZE)
+	if (!dum->driver || !dum->driver->function)
 		return 0;
-	return snprintf (buf, PAGE_SIZE, "%s\n", dum->driver->function);
+	return scnprintf (buf, PAGE_SIZE, "%s\n", dum->driver->function);
 }
 DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
 
diff -Nru a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
--- a/drivers/usb/gadget/file_storage.c	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/gadget/file_storage.c	2004-08-04 17:58:04 -07:00
@@ -46,17 +46,16 @@
  *
  * Backing storage is provided by a regular file or a block device, specified
  * by the "file" module parameter.  Access can be limited to read-only by
- * setting the optional "ro" module parameter.
+ * setting the optional "ro" module parameter.  The gadget will indicate that
+ * it has removable media if the optional "removable" module parameter is set.
  *
  * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),
  * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected
  * by the optional "transport" module parameter.  It also supports the
  * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03),
  * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by
- * the optional "protocol" module parameter.  For testing purposes the
- * gadget will indicate that it has removable media if the optional
- * "removable" module parameter is set.  In addition, the default Vendor ID,
- * Product ID, and release number can be overridden.
+ * the optional "protocol" module parameter.  In addition, the default
+ * Vendor ID, Product ID, and release number can be overridden.
  *
  * There is support for multiple logical units (LUNs), each of which has
  * its own backing file.  The number of LUNs can be set using the optional
@@ -79,13 +78,13 @@
  *					the files or block devices used for
  *					backing storage
  *	ro=b[,b...]		Default false, booleans for read-only access
+ *	removable		Default false, boolean for removable media
  *	luns=N			Default N = number of filenames, number of
  *					LUNs to support
  *	transport=XXX		Default BBB, transport name (CB, CBI, or BBB)
  *	protocol=YYY		Default SCSI, protocol name (RBC, 8020 or
  *					ATAPI, QIC, UFI, 8070, or SCSI;
  *					also 1 - 6)
- *	removable		Default false, boolean for removable media
  *	vendor=0xVVVV		Default 0x0525 (NetChip), USB Vendor ID
  *	product=0xPPPP		Default 0xa4a5 (FSG), USB Product ID
  *	release=0xRRRR		Override the USB release number (bcdDevice)
@@ -97,16 +96,16 @@
  *					boolean to permit the driver to halt
  *					bulk endpoints
  *
- * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file" and "ro"
- * options are available; default values are used for everything else.
+ * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro",
+ * "removable", and "luns" options are available; default values are used
+ * for everything else.
  *
  * The pathnames of the backing files and the ro settings are available in
  * the attribute files "file" and "ro" in the lun<n> subdirectory of the
- * gadget's sysfs directory.  If CONFIG_USB_FILE_STORAGE_TEST and the
- * "removable" option are both set, writing to these files will simulate
- * ejecting/loading the medium (writing an empty line means eject) and
- * adjusting a write-enable tab.  Changes to the ro setting are not allowed
- * when the medium is loaded.
+ * gadget's sysfs directory.  If the "removable" option is set, writing to
+ * these files will simulate ejecting/loading the medium (writing an empty
+ * line means eject) and adjusting a write-enable tab.  Changes to the ro
+ * setting are not allowed when the medium is loaded.
  *
  * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
  */
@@ -178,7 +177,10 @@
  * Bulk-only specification requires a stall.  In such cases the driver
  * will halt the endpoint and set a flag indicating that it should clear
  * the halt in software during the next device reset.  Hopefully this
- * will permit everything to work correctly.
+ * will permit everything to work correctly.  Furthermore, although the
+ * specification allows the bulk-out endpoint to halt when the host sends
+ * too much data, implementing this would cause an unavoidable race.
+ * The driver will always use the "no-stall" approach for OUT transfers.
  *
  * One subtle point concerns sending status-stage responses for ep0
  * requests.  Some of these requests, such as device reset, can involve
@@ -246,7 +248,7 @@
 
 #define DRIVER_DESC		"File-backed Storage Gadget"
 #define DRIVER_NAME		"g_file_storage"
-#define DRIVER_VERSION		"21 March 2004"
+#define DRIVER_VERSION		"28 July 2004"
 
 static const char longname[] = DRIVER_DESC;
 static const char shortname[] = DRIVER_NAME;
@@ -371,14 +373,17 @@
 module_param_array(ro, bool, mod_data.num_ros, S_IRUGO);
 MODULE_PARM_DESC(ro, "true to force read-only");
 
+module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
+MODULE_PARM_DESC(luns, "number of LUNs");
 
-/* In the non-TEST version, only the file and ro module parameters
+module_param_named(removable, mod_data.removable, bool, S_IRUGO);
+MODULE_PARM_DESC(removable, "true to simulate removable media");
+
+
+/* In the non-TEST version, only the module parameters listed above
  * are available. */
 #ifdef CONFIG_USB_FILE_STORAGE_TEST
 
-module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
-MODULE_PARM_DESC(luns, "number of LUNs");
-
 module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO);
 MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)");
 
@@ -386,9 +391,6 @@
 MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, "
 		"8070, or SCSI)");
 
-module_param_named(removable, mod_data.removable, bool, S_IRUGO);
-MODULE_PARM_DESC(removable, "true to simulate removable media");
-
 module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO);
 MODULE_PARM_DESC(vendor, "USB Vendor ID");
 
@@ -525,11 +527,6 @@
  * parts of the driver that aren't used in the non-TEST version.  Even gcc
  * can recognize when a test of a constant expression yields a dead code
  * path.
- *
- * Also, in the non-TEST version, open_backing_file() is only used during
- * initialization and the sysfs attribute store_xxx routines aren't used
- * at all.  We will define NORMALLY_INIT to mark them as __init so they
- * don't occupy kernel code space unnecessarily.
  */
 
 #ifdef CONFIG_USB_FILE_STORAGE_TEST
@@ -537,16 +534,12 @@
 #define transport_is_bbb()	(mod_data.transport_type == USB_PR_BULK)
 #define transport_is_cbi()	(mod_data.transport_type == USB_PR_CBI)
 #define protocol_is_scsi()	(mod_data.protocol_type == USB_SC_SCSI)
-#define backing_file_is_open(curlun)	((curlun)->filp != NULL)
-#define NORMALLY_INIT
 
 #else
 
 #define transport_is_bbb()	1
 #define transport_is_cbi()	0
 #define protocol_is_scsi()	1
-#define backing_file_is_open(curlun)	1
-#define NORMALLY_INIT		__init
 
 #endif /* CONFIG_USB_FILE_STORAGE_TEST */
 
@@ -567,6 +560,8 @@
 	struct device	dev;
 };
 
+#define backing_file_is_open(curlun)	((curlun)->filp != NULL)
+
 static inline struct lun *dev_to_lun(struct device *dev)
 {
 	return container_of(dev, struct lun, dev);
@@ -659,6 +654,7 @@
 	unsigned long		atomic_bitflags;
 #define REGISTERED		0
 #define CLEAR_BULK_HALTS	1
+#define SUSPENDED		2
 
 	struct usb_ep		*bulk_in;
 	struct usb_ep		*bulk_out;
@@ -1041,8 +1037,6 @@
 		function = fs_function;
 
 	len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);
-	if (len < 0)
-		return len;
 	((struct usb_config_descriptor *) buf)->bDescriptorType = type;
 	return len;
 }
@@ -1172,9 +1166,10 @@
 	wakeup_thread(fsg);
 }
 
+
+#ifdef CONFIG_USB_FILE_STORAGE_TEST
 static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
 {
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
 	struct fsg_dev		*fsg = (struct fsg_dev *) ep->driver_data;
 	struct fsg_buffhd	*bh = (struct fsg_buffhd *) req->context;
 
@@ -1190,17 +1185,21 @@
 	bh->state = BUF_STATE_EMPTY;
 	spin_unlock(&fsg->lock);
 	wakeup_thread(fsg);
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
 }
 
+#else
+static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
+{}
+#endif /* CONFIG_USB_FILE_STORAGE_TEST */
+
 
 /*-------------------------------------------------------------------------*/
 
 /* Ep0 class-specific handlers.  These always run in_irq. */
 
+#ifdef CONFIG_USB_FILE_STORAGE_TEST
 static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
 {
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
 	struct usb_request	*req = fsg->ep0req;
 	static u8		cbi_reset_cmnd[6] = {
 			SC_SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
@@ -1238,9 +1237,13 @@
 
 	spin_unlock(&fsg->lock);
 	wakeup_thread(fsg);
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
 }
 
+#else
+static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+{}
+#endif /* CONFIG_USB_FILE_STORAGE_TEST */
+
 
 static int class_setup_req(struct fsg_dev *fsg,
 		const struct usb_ctrlrequest *ctrl)
@@ -1465,8 +1468,8 @@
 	/* Respond with data/status or defer until later? */
 	if (rc >= 0 && rc != DELAYED_STATUS) {
 		fsg->ep0req->length = rc;
-		fsg->ep0req->zero = rc < ctrl->wLength
-				&& (rc % gadget->ep0->maxpacket) == 0;
+		fsg->ep0req->zero = (rc < ctrl->wLength &&
+				(rc % gadget->ep0->maxpacket) == 0);
 		fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
 				"ep0-in" : "ep0-out");
 		rc = ep0_queue(fsg);
@@ -2443,14 +2446,19 @@
 			rc = -EINTR;
 		}
 
-		/* We haven't processed all the incoming data.  If we are
-		 * allowed to stall, halt the bulk-out endpoint and cancel
-		 * any outstanding requests. */
+		/* We haven't processed all the incoming data.  Even though
+		 * we may be allowed to stall, doing so would cause a race.
+		 * The controller may already have ACK'ed all the remaining
+		 * bulk-out packets, in which case the host wouldn't see a
+		 * STALL.  Not realizing the endpoint was halted, it wouldn't
+		 * clear the halt -- leading to problems later on. */
+#if 0
 		else if (mod_data.can_stall) {
 			fsg_set_halt(fsg, fsg->bulk_out);
 			raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
 			rc = -EINTR;
 		}
+#endif
 
 		/* We can't stall.  Read in the excess data and throw it
 		 * all away. */
@@ -2513,7 +2521,7 @@
 
 	} else if (mod_data.transport_type == USB_PR_CB) {
 
-		/* Control-Bulk transport has no status stage! */
+		/* Control-Bulk transport has no status phase! */
 		return 0;
 
 	} else {			// USB_PR_CBI
@@ -2603,8 +2611,10 @@
 	fsg->residue = fsg->usb_amount_left = fsg->data_size;
 
 	/* Conflicting data directions is a phase error */
-	if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0)
-		goto phase_error;
+	if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) {
+		fsg->phase_error = 1;
+		return -EINVAL;
+	}
 
 	/* Verify the length of the command itself */
 	if (cmnd_size != fsg->cmnd_size) {
@@ -2613,8 +2623,10 @@
 		 * with cbw->Length == 12 (it should be 6). */
 		if (fsg->cmnd[0] == SC_REQUEST_SENSE && fsg->cmnd_size == 12)
 			cmnd_size = fsg->cmnd_size;
-		else
-			goto phase_error;
+		else {
+			fsg->phase_error = 1;
+			return -EINVAL;
+		}
 	}
 
 	/* Check that the LUN values are oonsistent */
@@ -2674,10 +2686,6 @@
 	}
 
 	return 0;
-
-phase_error:
-	fsg->phase_error = 1;
-	return -EINVAL;
 }
 
 
@@ -3424,8 +3432,7 @@
 /* If the next two routines are called while the gadget is registered,
  * the caller must own fsg->filesem for writing. */
 
-static int NORMALLY_INIT open_backing_file(struct lun *curlun,
-		const char *filename)
+static int open_backing_file(struct lun *curlun, const char *filename)
 {
 	int				ro;
 	struct file			*filp = NULL;
@@ -3550,8 +3557,7 @@
 }
 
 
-ssize_t NORMALLY_INIT store_ro(struct device *dev, const char *buf,
-		size_t count)
+ssize_t store_ro(struct device *dev, const char *buf, size_t count)
 {
 	ssize_t		rc = count;
 	struct lun	*curlun = dev_to_lun(dev);
@@ -3575,8 +3581,7 @@
 	return rc;
 }
 
-ssize_t NORMALLY_INIT store_file(struct device *dev, const char *buf,
-		size_t count)
+ssize_t store_file(struct device *dev, const char *buf, size_t count)
 {
 	struct lun	*curlun = dev_to_lun(dev);
 	struct fsg_dev	*fsg = (struct fsg_dev *) dev_get_drvdata(dev);
@@ -3805,9 +3810,8 @@
 		goto out;
 	}
 
-	/* Create the LUNs and open their backing files.  We can't register
-	 * the LUN devices until the gadget itself is registered, which
-	 * doesn't happen until after fsg_bind() returns. */
+	/* Create the LUNs, open their backing files, and register the
+	 * LUN devices in sysfs. */
 	fsg->luns = kmalloc(i * sizeof(struct lun), GFP_KERNEL);
 	if (!fsg->luns) {
 		rc = -ENOMEM;
@@ -3825,6 +3829,15 @@
 		snprintf(curlun->dev.bus_id, BUS_ID_SIZE,
 				"%s-lun%d", gadget->dev.bus_id, i);
 
+		if ((rc = device_register(&curlun->dev)) != 0)
+			INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
+		else {
+			curlun->registered = 1;
+			curlun->dev.release = lun_release;
+			device_create_file(&curlun->dev, &dev_attr_ro);
+			device_create_file(&curlun->dev, &dev_attr_file);
+		}
+
 		if (file[i] && *file[i]) {
 			if ((rc = open_backing_file(curlun, file[i])) != 0)
 				goto out;
@@ -3974,6 +3987,25 @@
 
 /*-------------------------------------------------------------------------*/
 
+static void fsg_suspend(struct usb_gadget *gadget)
+{
+	struct fsg_dev		*fsg = get_gadget_data(gadget);
+
+	DBG(fsg, "suspend\n");
+	set_bit(SUSPENDED, &fsg->atomic_bitflags);
+}
+
+static void fsg_resume(struct usb_gadget *gadget)
+{
+	struct fsg_dev		*fsg = get_gadget_data(gadget);
+
+	DBG(fsg, "resume\n");
+	clear_bit(SUSPENDED, &fsg->atomic_bitflags);
+}
+
+
+/*-------------------------------------------------------------------------*/
+
 static struct usb_gadget_driver		fsg_driver = {
 #ifdef CONFIG_USB_GADGET_DUALSPEED
 	.speed		= USB_SPEED_HIGH,
@@ -3985,6 +4017,8 @@
 	.unbind		= fsg_unbind,
 	.disconnect	= fsg_disconnect,
 	.setup		= fsg_setup,
+	.suspend	= fsg_suspend,
+	.resume		= fsg_resume,
 
 	.driver		= {
 		.name		= (char *) shortname,
@@ -4024,8 +4058,6 @@
 {
 	int		rc;
 	struct fsg_dev	*fsg;
-	int		i;
-	struct lun	*curlun;
 
 	if ((rc = fsg_alloc()) != 0)
 		return rc;
@@ -4035,19 +4067,6 @@
 		return rc;
 	}
 	set_bit(REGISTERED, &fsg->atomic_bitflags);
-
-	/* Register the LUN devices and their attribute files */
-	for (i = 0; i < fsg->nluns; ++i) {
-		curlun = &fsg->luns[i];
-		if ((rc = device_register(&curlun->dev)) != 0)
-			INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
-		else {
-			curlun->registered = 1;
-			curlun->dev.release = lun_release;
-			device_create_file(&curlun->dev, &dev_attr_ro);
-			device_create_file(&curlun->dev, &dev_attr_file);
-		}
-	}
 
 	/* Tell the thread to start working */
 	complete(&fsg->thread_notifier);
diff -Nru a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
--- a/drivers/usb/gadget/pxa2xx_udc.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/gadget/pxa2xx_udc.c	2004-08-04 17:58:03 -07:00
@@ -1508,7 +1508,7 @@
 	/* caller must be able to sleep in order to cope
 	 * with startup transients.
 	 */
-	schedule_timeout(HZ/10);
+	msleep(100);
 
 	/* enable suspend/resume and reset irqs */
 	udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM);
diff -Nru a/drivers/usb/host/hc_sl811.c b/drivers/usb/host/hc_sl811.c
--- a/drivers/usb/host/hc_sl811.c	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/host/hc_sl811.c	2004-08-04 17:58:04 -07:00
@@ -106,14 +106,14 @@
 
 static int sofWaitCnt = 0;
 
-MODULE_PARM (urb_debug, "i");
+module_param(urb_debug, int, 0);
 MODULE_PARM_DESC (urb_debug, "debug urb messages, default is 0 (no)");
 
-MODULE_PARM (base_addr, "i");
+module_param(base_addr, int, 0);
 MODULE_PARM_DESC (base_addr, "sl811 base address 0xd3800000");
-MODULE_PARM (data_reg_addr, "i");
+module_param(data_reg_addr, int, 0);
 MODULE_PARM_DESC (data_reg_addr, "sl811 data register address 0xd3810000");
-MODULE_PARM (irq, "i");
+module_param(irq, int, 0);
 MODULE_PARM_DESC (irq, "IRQ 34 (default)");
 
 static int hc_reset (hci_t * hci);
diff -Nru a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
--- a/drivers/usb/host/ohci-omap.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/host/ohci-omap.c	2004-08-04 17:58:03 -07:00
@@ -658,7 +658,7 @@
 	return ret;
 }
 
-MODULE_PARM(hmc_mode, "hmc_mode");
+module_param(hmc_mode, int, 0);
 
 static void __exit ohci_hcd_omap_cleanup (void)
 {
diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
--- a/drivers/usb/host/uhci-hcd.c	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/host/uhci-hcd.c	2004-08-04 17:58:04 -07:00
@@ -82,7 +82,7 @@
 #else
 static int debug = 0;
 #endif
-MODULE_PARM(debug, "i");
+module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug level");
 static char *errbuf;
 #define ERRBUF_LEN    (32 * 1024)
diff -Nru a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
--- a/drivers/usb/input/aiptek.c	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/input/aiptek.c	2004-08-04 17:58:04 -07:00
@@ -2289,9 +2289,9 @@
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(programmableDelay, "i");
+module_param(programmableDelay, int, 0);
 MODULE_PARM_DESC(programmableDelay, "delay used during tablet programming");
-MODULE_PARM(jitterDelay, "i");
+module_param(jitterDelay, int, 0);
 MODULE_PARM_DESC(jitterDelay, "stylus/mouse settlement delay");
 
 module_init(aiptek_init);
diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
--- a/drivers/usb/input/hid-core.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/input/hid-core.c	2004-08-04 17:58:03 -07:00
@@ -1619,11 +1619,17 @@
 
 		struct usb_endpoint_descriptor *endpoint;
 		int pipe;
+		int interval;
 
 		endpoint = &interface->endpoint[n].desc;
 		if ((endpoint->bmAttributes & 3) != 3)		/* Not an interrupt endpoint */
 			continue;
 
+		/* handle potential highspeed HID correctly */
+		interval = endpoint->bInterval;
+		if (dev->speed == USB_SPEED_HIGH)
+			interval = 1 << (interval - 1);
+
 		if (endpoint->bEndpointAddress & USB_DIR_IN) {
 			int len;
 
@@ -1636,7 +1642,7 @@
 			if (len > HID_BUFFER_SIZE)
 				len = HID_BUFFER_SIZE;
 			usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, len,
-					 hid_irq_in, hid, endpoint->bInterval);
+					 hid_irq_in, hid, interval);
 			hid->urbin->transfer_dma = hid->inbuf_dma;
 			hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 		} else {
@@ -1646,7 +1652,7 @@
 				goto fail;
 			pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress);
 			usb_fill_int_urb(hid->urbout, dev, pipe, hid->outbuf, 0,
-					  hid_irq_out, hid, 1);
+					 hid_irq_out, hid, interval);
 			hid->urbout->transfer_dma = hid->outbuf_dma;
 			hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 		}
diff -Nru a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c
--- a/drivers/usb/input/kbtab.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/input/kbtab.c	2004-08-04 17:58:03 -07:00
@@ -26,10 +26,9 @@
 
 #define USB_VENDOR_ID_KBGEAR	0x084e
 
-static int       kb_pressure_click = 0x10;
-MODULE_PARM     (kb_pressure_click,"i");
-MODULE_PARM_DESC(kb_pressure_click,
-		 "pressure threshold for clicks");
+static int kb_pressure_click = 0x10;
+module_param(kb_pressure_click, int, 0);
+MODULE_PARM_DESC(kb_pressure_click, "pressure threshold for clicks");
 
 struct kbtab {
 	signed char *data;
diff -Nru a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c
--- a/drivers/usb/media/dabusb.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/media/dabusb.c	2004-08-04 17:58:03 -07:00
@@ -868,7 +868,7 @@
 MODULE_DESCRIPTION( DRIVER_DESC );
 MODULE_LICENSE("GPL");
 
-MODULE_PARM (buffers, "i");
+module_param(buffers, int, 0);
 MODULE_PARM_DESC (buffers, "Number of buffers (default=256)");
 
 module_init (dabusb_init);
diff -Nru a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c
--- a/drivers/usb/media/konicawc.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/media/konicawc.c	2004-08-04 17:58:03 -07:00
@@ -68,7 +68,7 @@
 /* Some default values for initial camera settings,
    can be set by modprobe */
 
-static enum frame_sizes size;	
+static int size;	
 static int speed = 6;		/* Speed (fps) 0 (slowest) to 6 (fastest) */
 static int brightness =	MAX_BRIGHTNESS/2;
 static int contrast =	MAX_CONTRAST/2;
@@ -928,23 +928,23 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_PARM(speed, "i");
+module_param(speed, int, 0);
 MODULE_PARM_DESC(speed, "Initial speed: 0 (slowest) - 6 (fastest)");
-MODULE_PARM(size, "i");
+module_param(size, int, 0);
 MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 160x136 2: 176x144 3: 320x240");
-MODULE_PARM(brightness, "i");
+module_param(brightness, int, 0);
 MODULE_PARM_DESC(brightness, "Initial brightness 0 - 108");
-MODULE_PARM(contrast, "i");
+module_param(contrast, int, 0);
 MODULE_PARM_DESC(contrast, "Initial contrast 0 - 108");
-MODULE_PARM(saturation, "i");
+module_param(saturation, int, 0);
 MODULE_PARM_DESC(saturation, "Initial saturation 0 - 108");
-MODULE_PARM(sharpness, "i");
+module_param(sharpness, int, 0);
 MODULE_PARM_DESC(sharpness, "Initial brightness 0 - 108");
-MODULE_PARM(whitebal, "i");
+module_param(whitebal, int, 0);
 MODULE_PARM_DESC(whitebal, "Initial white balance 0 - 363");
 
 #ifdef CONFIG_USB_DEBUG
-MODULE_PARM(debug, "i");
+module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
 #endif
 
diff -Nru a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
--- a/drivers/usb/media/ov511.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/media/ov511.c	2004-08-04 17:58:03 -07:00
@@ -119,78 +119,78 @@
 static int mirror;
 static int ov518_color;
 
-MODULE_PARM(autobright, "i");
+module_param(autobright, int, 0);
 MODULE_PARM_DESC(autobright, "Sensor automatically changes brightness");
-MODULE_PARM(autogain, "i");
+module_param(autogain, int, 0);
 MODULE_PARM_DESC(autogain, "Sensor automatically changes gain");
-MODULE_PARM(autoexp, "i");
+module_param(autoexp, int, 0);
 MODULE_PARM_DESC(autoexp, "Sensor automatically changes exposure");
-MODULE_PARM(debug, "i");
+module_param(debug, int, 0);
 MODULE_PARM_DESC(debug,
   "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=max");
-MODULE_PARM(snapshot, "i");
+module_param(snapshot, int, 0);
 MODULE_PARM_DESC(snapshot, "Enable snapshot mode");
-MODULE_PARM(cams, "i");
+module_param(cams, int, 0);
 MODULE_PARM_DESC(cams, "Number of simultaneous cameras");
-MODULE_PARM(compress, "i");
+module_param(compress, int, 0);
 MODULE_PARM_DESC(compress, "Turn on compression");
-MODULE_PARM(testpat, "i");
+module_param(testpat, int, 0);
 MODULE_PARM_DESC(testpat,
   "Replace image with vertical bar testpattern (only partially working)");
-MODULE_PARM(dumppix, "i");
+module_param(dumppix, int, 0);
 MODULE_PARM_DESC(dumppix, "Dump raw pixel data");
-MODULE_PARM(led, "i");
+module_param(led, int, 0);
 MODULE_PARM_DESC(led,
   "LED policy (OV511+ or later). 0=off, 1=on (default), 2=auto (on when open)");
-MODULE_PARM(dump_bridge, "i");
+module_param(dump_bridge, int, 0);
 MODULE_PARM_DESC(dump_bridge, "Dump the bridge registers");
-MODULE_PARM(dump_sensor, "i");
+module_param(dump_sensor, int, 0);
 MODULE_PARM_DESC(dump_sensor, "Dump the sensor registers");
-MODULE_PARM(printph, "i");
+module_param(printph, int, 0);
 MODULE_PARM_DESC(printph, "Print frame start/end headers");
-MODULE_PARM(phy, "i");
+module_param(phy, int, 0);
 MODULE_PARM_DESC(phy, "Prediction range (horiz. Y)");
-MODULE_PARM(phuv, "i");
+module_param(phuv, int, 0);
 MODULE_PARM_DESC(phuv, "Prediction range (horiz. UV)");
-MODULE_PARM(pvy, "i");
+module_param(pvy, int, 0);
 MODULE_PARM_DESC(pvy, "Prediction range (vert. Y)");
-MODULE_PARM(pvuv, "i");
+module_param(pvuv, int, 0);
 MODULE_PARM_DESC(pvuv, "Prediction range (vert. UV)");
-MODULE_PARM(qhy, "i");
+module_param(qhy, int, 0);
 MODULE_PARM_DESC(qhy, "Quantization threshold (horiz. Y)");
-MODULE_PARM(qhuv, "i");
+module_param(qhuv, int, 0);
 MODULE_PARM_DESC(qhuv, "Quantization threshold (horiz. UV)");
-MODULE_PARM(qvy, "i");
+module_param(qvy, int, 0);
 MODULE_PARM_DESC(qvy, "Quantization threshold (vert. Y)");
-MODULE_PARM(qvuv, "i");
+module_param(qvuv, int, 0);
 MODULE_PARM_DESC(qvuv, "Quantization threshold (vert. UV)");
-MODULE_PARM(lightfreq, "i");
+module_param(lightfreq, int, 0);
 MODULE_PARM_DESC(lightfreq,
   "Light frequency. Set to 50 or 60 Hz, or zero for default settings");
-MODULE_PARM(bandingfilter, "i");
+module_param(bandingfilter, int, 0);
 MODULE_PARM_DESC(bandingfilter,
   "Enable banding filter (to reduce effects of fluorescent lighting)");
-MODULE_PARM(clockdiv, "i");
+module_param(clockdiv, int, 0);
 MODULE_PARM_DESC(clockdiv, "Force pixel clock divisor to a specific value");
-MODULE_PARM(packetsize, "i");
+module_param(packetsize, int, 0);
 MODULE_PARM_DESC(packetsize, "Force a specific isoc packet size");
-MODULE_PARM(framedrop, "i");
+module_param(framedrop, int, 0);
 MODULE_PARM_DESC(framedrop, "Force a specific frame drop register setting");
-MODULE_PARM(fastset, "i");
+module_param(fastset, int, 0);
 MODULE_PARM_DESC(fastset, "Allows picture settings to take effect immediately");
-MODULE_PARM(force_palette, "i");
+module_param(force_palette, int, 0);
 MODULE_PARM_DESC(force_palette, "Force the palette to a specific value");
-MODULE_PARM(backlight, "i");
+module_param(backlight, int, 0);
 MODULE_PARM_DESC(backlight, "For objects that are lit from behind");
-MODULE_PARM(unit_video, "1-" __MODULE_STRING(OV511_MAX_UNIT_VIDEO) "i");
-MODULE_PARM_DESC(unit_video,
-  "Force use of specific minor number(s). 0 is not allowed.");
-MODULE_PARM(remove_zeros, "i");
+/*module_param_array(unit_video, int, OV511_MAX_UNIT_VIDEO, 0); */
+/*MODULE_PARM_DESC(unit_video,
+  "Force use of specific minor number(s). 0 is not allowed."); */
+module_param(remove_zeros, int, 0);
 MODULE_PARM_DESC(remove_zeros,
   "Remove zero-padding from uncompressed incoming data");
-MODULE_PARM(mirror, "i");
+module_param(mirror, int, 0);
 MODULE_PARM_DESC(mirror, "Reverse image horizontally");
-MODULE_PARM(ov518_color, "i");
+module_param(ov518_color, int, 0);
 MODULE_PARM_DESC(ov518_color, "Enable OV518 color (experimental)");
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
@@ -1169,7 +1169,7 @@
 		return -EIO;
 
 	/* Wait for it to initialize */
-	schedule_timeout(1 + 150 * HZ / 1000);
+	msleep(150);
 
 	for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
 		if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) &&
@@ -1182,7 +1182,7 @@
 		if (i2c_w(ov, 0x12, 0x80) < 0)
 			return -EIO;
 		/* Wait for it to initialize */
-		schedule_timeout(1 + 150 * HZ / 1000);
+		msleep(150);
 		/* Dummy read to sync I2C */
 		if (i2c_r(ov, 0x00) < 0)
 			return -EIO;
@@ -4947,7 +4947,7 @@
 			return -1;
 
 		/* Wait for it to initialize */
-		schedule_timeout(1 + 150 * HZ / 1000);
+		msleep(150);
 
 		i = 0;
 		success = 0;
diff -Nru a/drivers/usb/media/pwc-if.c b/drivers/usb/media/pwc-if.c
--- a/drivers/usb/media/pwc-if.c	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/media/pwc-if.c	2004-08-04 17:58:04 -07:00
@@ -2009,33 +2009,35 @@
  * Initialization code & module stuff 
  */
 
-static char *size = NULL;
+static char size[PSZ_MAX];
 static int fps = 0;
 static int fbufs = 0;
 static int mbufs = 0;
 static int trace = -1;
 static int compression = -1;
-static int leds[2] = { -1, -1 };
 static char *dev_hint[MAX_DEV_HINTS] = { };
 
-MODULE_PARM(size, "s");
+module_param_string(size, size, PSZ_MAX, 0);
 MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
-MODULE_PARM(fps, "i");
+module_param(fps, int, 0);
 MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
-MODULE_PARM(fbufs, "i");
+module_param(fbufs, int, 0);
 MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
-MODULE_PARM(mbufs, "i");
+module_param(mbufs, int, 0);
 MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers");
-MODULE_PARM(trace, "i");
+module_param(trace, int, 0);
 MODULE_PARM_DESC(trace, "For debugging purposes");
-MODULE_PARM(power_save, "i");
+module_param(power_save, int, 0);
 MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
-MODULE_PARM(compression, "i");
+module_param(compression, int, 0);
 MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
-MODULE_PARM(leds, "2i");
-MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
-MODULE_PARM(dev_hint, "0-20s");
-MODULE_PARM_DESC(dev_hint, "Device node hints");
+module_param(led_on, int, 0);
+MODULE_PARM_DESC(led_on, "LED on time in milliseconds");
+module_param(led_off, int, 0);
+MODULE_PARM_DESC(led_off, "LED off time in milliseconds");
+/* Commented out, as you should be using udev instead of crud like this... */
+/* MODULE_PARM(dev_hint, "0-20s"); */
+/* MODULE_PARM_DESC(dev_hint, "Device node hints"); */
 
 MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
 MODULE_AUTHOR("Nemosoft Unv. <webcam@smcc.demon.nl>");
@@ -2060,7 +2062,7 @@
 		Info("Default framerate set to %d.\n", default_fps);
 	}
 
-	if (size) {
+	if (strlen(size)) {
 		/* string; try matching with array */
 		for (sz = 0; sz < PSZ_MAX; sz++) {
 			if (!strcmp(sizenames[sz], size)) { /* Found! */
@@ -2104,10 +2106,6 @@
 	}
 	if (power_save)
 		Info("Enabling power save on open/close.\n");
-	if (leds[0] >= 0)
-		led_on = leds[0];
-	if (leds[1] >= 0)
-		led_off = leds[1];
 
 	/* Big device node whoopla. Basicly, it allows you to assign a
 	   device node (/dev/videoX) to a camera, based on its type
diff -Nru a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c
--- a/drivers/usb/media/se401.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/media/se401.c	2004-08-04 17:58:03 -07:00
@@ -53,9 +53,9 @@
 MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
 MODULE_DESCRIPTION("SE401 USB Camera Driver");
 MODULE_LICENSE("GPL");
-MODULE_PARM(flickerless, "i");
+module_param(flickerless, int, 0);
 MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)");
-MODULE_PARM(video_nr, "i");
+module_param(video_nr, int, 0);
 
 static struct usb_driver se401_driver;
 
diff -Nru a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c
--- a/drivers/usb/media/stv680.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/media/stv680.c	2004-08-04 17:58:03 -07:00
@@ -93,11 +93,11 @@
 MODULE_AUTHOR (DRIVER_AUTHOR);
 MODULE_DESCRIPTION (DRIVER_DESC);
 MODULE_LICENSE ("GPL");
-MODULE_PARM (debug, "i");
+module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC (debug, "Debug enabled or not");
-MODULE_PARM (swapRGB_on, "i");
+module_param(swapRGB_on, int, 0);
 MODULE_PARM_DESC (swapRGB_on, "Red/blue swap: 1=always, 0=auto, -1=never");
-MODULE_PARM (video_nr, "i");
+module_param(video_nr, int, 0);
 
 /********************************************************************
  *
diff -Nru a/drivers/usb/media/ultracam.c b/drivers/usb/media/ultracam.c
--- a/drivers/usb/media/ultracam.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/media/ultracam.c	2004-08-04 17:58:03 -07:00
@@ -60,9 +60,9 @@
 static int init_hue = 128;
 static int hue_correction = 128;
 
-MODULE_PARM(debug, "i");
+module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
-MODULE_PARM(flags, "i");
+module_param(flags, int, 0);
 MODULE_PARM_DESC(flags,
 		"Bitfield: 0=VIDIOCSYNC, "
 		"1=B/W, "
@@ -71,18 +71,18 @@
 		"4=test pattern, "
 		"5=separate frames, "
 		"6=clean frames");
-MODULE_PARM(framerate, "i");
+module_param(framerate, int, 0);
 MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");
 
-MODULE_PARM(init_brightness, "i");
+module_param(init_brightness, int, 0);
 MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");
-MODULE_PARM(init_contrast, "i");
+module_param(init_contrast, int, 0);
 MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");
-MODULE_PARM(init_color, "i");
+module_param(init_color, int, 0);
 MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)");
-MODULE_PARM(init_hue, "i");
+module_param(init_hue, int, 0);
 MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");
-MODULE_PARM(hue_correction, "i");
+module_param(hue_correction, int, 0);
 MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");
 
 /*
diff -Nru a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c
--- a/drivers/usb/media/usbvideo.c	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/media/usbvideo.c	2004-08-04 17:58:04 -07:00
@@ -34,7 +34,7 @@
 #endif
 
 static int video_nr = -1;
-MODULE_PARM(video_nr, "i");
+module_param(video_nr, int, 0);
 
 /*
  * Local prototypes.
diff -Nru a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
--- a/drivers/usb/misc/auerswald.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/misc/auerswald.c	2004-08-04 17:58:03 -07:00
@@ -1976,8 +1976,7 @@
 	dbg ("Version is %X", cp->version);
 
 	/* allow some time to settle the device */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ/3);
+	msleep(334);
 
 	/* Try to get a suitable textual description of the device */
 	/* Device name:*/
diff -Nru a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
--- a/drivers/usb/misc/legousbtower.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/misc/legousbtower.c	2004-08-04 17:58:03 -07:00
@@ -103,7 +103,7 @@
 #define DRIVER_DESC "LEGO USB Tower Driver"
 
 /* Module parameters */
-MODULE_PARM(debug, "i");
+module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug enabled or not");
 
 /* The defaults are chosen to work with the latest versions of leJOS and NQC.
@@ -114,7 +114,7 @@
  * (417 for datalog uploads), and packet_timeout should be set.
  */
 static size_t read_buffer_size = 480;
-MODULE_PARM(read_buffer_size, "i");
+module_param(read_buffer_size, int, 0);
 MODULE_PARM_DESC(read_buffer_size, "Read buffer size");
 
 /* Some legacy software likes to send packets in one piece.
@@ -124,7 +124,7 @@
  * if the software is not prepared to wait long enough.
  */
 static size_t write_buffer_size = 480;
-MODULE_PARM(write_buffer_size, "i");
+module_param(write_buffer_size, int, 0);
 MODULE_PARM_DESC(write_buffer_size, "Write buffer size");
 
 /* Some legacy software expects reads to contain whole LASM packets.
@@ -138,7 +138,7 @@
  * Set it to 0 to disable.
  */
 static int packet_timeout = 50;
-MODULE_PARM(packet_timeout, "i");
+module_param(packet_timeout, int, 0);
 MODULE_PARM_DESC(packet_timeout, "Packet timeout in ms");
 
 /* Some legacy software expects blocking reads to time out.
@@ -146,7 +146,7 @@
  * Set it to 0 to disable.
  */
 static int read_timeout = 200;
-MODULE_PARM(read_timeout, "i");
+module_param(read_timeout, int, 0);
 MODULE_PARM_DESC(read_timeout, "Read timeout in ms");
 
 /* As of kernel version 2.6.4 ehci-hcd uses an
@@ -159,11 +159,11 @@
  * or set to 0 to use the standard interval from the endpoint descriptors.
  */
 static int interrupt_in_interval = 2;
-MODULE_PARM(interrupt_in_interval, "i");
+module_param(interrupt_in_interval, int, 0);
 MODULE_PARM_DESC(interrupt_in_interval, "Interrupt in interval in ms");
 
 static int interrupt_out_interval = 8;
-MODULE_PARM(interrupt_out_interval, "i");
+module_param(interrupt_out_interval, int, 0);
 MODULE_PARM_DESC(interrupt_out_interval, "Interrupt out interval in ms");
 
 /* Define these values to match your device */
diff -Nru a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c
--- a/drivers/usb/misc/tiglusb.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/misc/tiglusb.c	2004-08-04 17:58:03 -07:00
@@ -560,7 +560,7 @@
 MODULE_DESCRIPTION (DRIVER_DESC);
 MODULE_LICENSE (DRIVER_LICENSE);
 
-MODULE_PARM (timeout, "i");
+module_param(timeout, int, 0);
 MODULE_PARM_DESC (timeout, "Timeout in tenths of seconds (default=1.5 seconds)");
 
 /* --------------------------------------------------------------------- */
diff -Nru a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
--- a/drivers/usb/net/pegasus.c	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/net/pegasus.c	2004-08-04 17:58:04 -07:00
@@ -78,8 +78,8 @@
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
-MODULE_PARM(loopback, "i");
-MODULE_PARM(mii_mode, "i");
+module_param(loopback, bool, 0);
+module_param(mii_mode, bool, 0);
 MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)");
 MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0");
 
diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
--- a/drivers/usb/net/usbnet.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/net/usbnet.c	2004-08-04 17:58:03 -07:00
@@ -166,7 +166,7 @@
 #define CONTROL_TIMEOUT_JIFFIES ((CONTROL_TIMEOUT_MS * HZ)/1000)
 
 // between wakeups
-#define UNLINK_TIMEOUT_JIFFIES ((3  /*ms*/ * HZ)/1000)
+#define UNLINK_TIMEOUT_MS	3
 
 /*-------------------------------------------------------------------------*/
 
@@ -268,7 +268,7 @@
 
 /* use ethtool to change the level for any given device */
 static int msg_level = 1;
-MODULE_PARM (msg_level, "i");
+module_param (msg_level, int, 0);
 MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)");
 
 
@@ -2591,8 +2591,7 @@
 	while (skb_queue_len (&dev->rxq)
 			&& skb_queue_len (&dev->txq)
 			&& skb_queue_len (&dev->done)) {
-		set_current_state (TASK_UNINTERRUPTIBLE);
-		schedule_timeout (UNLINK_TIMEOUT_JIFFIES);
+		msleep(UNLINK_TIMEOUT_MS);
 		devdbg (dev, "waited for %d urb completions", temp);
 	}
 	dev->wait = NULL;
diff -Nru a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
--- a/drivers/usb/serial/cyberjack.c	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/serial/cyberjack.c	2004-08-04 17:58:04 -07:00
@@ -44,7 +44,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.0"
+#define DRIVER_VERSION "v1.01"
 #define DRIVER_AUTHOR "Matthias Bruestle"
 #define DRIVER_DESC "REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver"
 
@@ -111,6 +111,7 @@
 static int cyberjack_startup (struct usb_serial *serial)
 {
 	struct cyberjack_private *priv;
+	int i;
 
 	dbg("%s", __FUNCTION__);
 
@@ -128,6 +129,16 @@
 
 	init_waitqueue_head(&serial->port[0]->write_wait);
 
+	for (i = 0; i < serial->num_ports; ++i) {
+		int result;
+		serial->port[i]->interrupt_in_urb->dev = serial->dev;
+		result = usb_submit_urb(serial->port[i]->interrupt_in_urb, 
+					GFP_KERNEL);
+		if (result)
+			err(" usb_submit_urb(read int) failed");
+		dbg("%s - usb_submit_urb(int urb)", __FUNCTION__);
+	}
+
 	return( 0 );
 }
 
@@ -138,6 +149,7 @@
 	dbg("%s", __FUNCTION__);
 
 	for (i=0; i < serial->num_ports; ++i) {
+		usb_unlink_urb (serial->port[i]->interrupt_in_urb);
 		/* My special items, the standard routines free my urbs */
 		kfree(usb_get_serial_port_data(serial->port[i]));
 		usb_set_serial_port_data(serial->port[i], NULL);
@@ -168,17 +180,6 @@
 	priv->wrsent = 0;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	/* shutdown any bulk reads that might be going on */
-	usb_unlink_urb (port->write_urb);
-	usb_unlink_urb (port->read_urb);
-	usb_unlink_urb (port->interrupt_in_urb);
-
-	port->interrupt_in_urb->dev = port->serial->dev;
-	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
-	if (result)
-		err(" usb_submit_urb(read int) failed");
-	dbg("%s - usb_submit_urb(int urb)", __FUNCTION__);
-
 	return result;
 }
 
@@ -190,11 +191,6 @@
 		/* shutdown any bulk reads that might be going on */
 		usb_unlink_urb (port->write_urb);
 		usb_unlink_urb (port->read_urb);
-		usb_unlink_urb (port->interrupt_in_urb);
-		dbg("%s - usb_clear_halt", __FUNCTION__ );
-		usb_clear_halt(port->serial->dev, port->write_urb->pipe);
-		usb_clear_halt(port->serial->dev, port->read_urb->pipe);
-		usb_clear_halt(port->serial->dev, port->interrupt_in_urb->pipe);
 	}
 }
 
@@ -376,6 +372,10 @@
 	}
 
 	tty = port->tty;
+	if (!tty) {
+		dbg("%s - ignoring since device not open\n", __FUNCTION__);
+		return;
+	}
 	if (urb->actual_length) {
 		for (i = 0; i < urb->actual_length ; ++i) {
 			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
--- a/drivers/usb/serial/ftdi_sio.c	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/serial/ftdi_sio.c	2004-08-04 17:58:04 -07:00
@@ -17,6 +17,11 @@
  * See http://ftdi-usb-sio.sourceforge.net for upto date testing info
  *	and extra documentation
  *
+ * (21/Jul/2004) Ian Abbott
+ *      Incorporated Steven Turner's code to add support for the FT2232C chip.
+ *      The prelimilary port to the 2.6 kernel was by Rus V. Brushkoff.  I have
+ *      fixed a couple of things.
+ *
  * (27/May/2004) Ian Abbott
  *      Improved throttling code, mostly stolen from the WhiteHEAT driver.
  *
@@ -259,7 +264,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.4.0"
+#define DRIVER_VERSION "v1.4.1"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>"
 #define DRIVER_DESC "USB FTDI Serial Converters Driver"
 
@@ -489,11 +494,18 @@
 };
 
 
+static struct usb_device_id id_table_FT2232C[] = {
+	{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
+	{ }						/* Terminating entry */
+};
+
+
 static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
@@ -621,6 +633,8 @@
 	__u8 rx_flags;		/* receive state flags (throttling) */
 	spinlock_t rx_lock;	/* spinlock for receive state */
 
+	__u16 interface;	/* FT2232C port interface (0 for FT232/245) */
+
 	int force_baud;		/* if non-zero, force the baud rate to this value */
 	int force_rtscts;	/* if non-zero, force RTS-CTS to always be enabled */
 };
@@ -637,6 +651,7 @@
 static int  ftdi_SIO_startup		(struct usb_serial *serial);
 static int  ftdi_8U232AM_startup	(struct usb_serial *serial);
 static int  ftdi_FT232BM_startup	(struct usb_serial *serial);
+static int  ftdi_FT2232C_startup	(struct usb_serial *serial);
 static int  ftdi_USB_UIRT_startup	(struct usb_serial *serial);
 static int  ftdi_HE_TIRA1_startup	(struct usb_serial *serial);
 static void ftdi_shutdown		(struct usb_serial *serial);
@@ -739,6 +754,32 @@
 	.shutdown =		ftdi_shutdown,
 };
 
+static struct usb_serial_device_type ftdi_FT2232C_device = {
+	.owner =		THIS_MODULE,
+	.name =			"FTDI FT2232C Compatible",
+	.id_table =		id_table_FT2232C,
+	.num_interrupt_in =	0,
+	.num_bulk_in =		1,
+	.num_bulk_out =		1,
+	.num_ports =		1,
+	.open =			ftdi_open,
+	.close =		ftdi_close,
+	.throttle =		ftdi_throttle,
+	.unthrottle =		ftdi_unthrottle,
+	.write =		ftdi_write,
+	.write_room =		ftdi_write_room,
+	.chars_in_buffer =	ftdi_chars_in_buffer,
+	.read_bulk_callback =	ftdi_read_bulk_callback,
+	.write_bulk_callback =	ftdi_write_bulk_callback,
+	.tiocmget =             ftdi_tiocmget,
+	.tiocmset =             ftdi_tiocmset,
+	.ioctl =		ftdi_ioctl,
+	.set_termios =		ftdi_set_termios,
+	.break_ctl =		ftdi_break_ctl,
+	.attach =		ftdi_FT2232C_startup,
+	.shutdown =		ftdi_shutdown,
+};
+
 static struct usb_serial_device_type ftdi_USB_UIRT_device = {
 	.owner =		THIS_MODULE,
 	.name =			"USB-UIRT Infrared Tranceiver",
@@ -866,7 +907,7 @@
 			       usb_sndctrlpipe(port->serial->dev, 0),
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
-			       ftdi_high_or_low, 0, 
+			       ftdi_high_or_low, priv->interface, 
 			       buf, 0, WDR_TIMEOUT);
 
 	kfree(buf);
@@ -896,7 +937,7 @@
 			       usb_sndctrlpipe(port->serial->dev, 0),
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
-			       ftdi_high_or_low, 0, 
+			       ftdi_high_or_low, priv->interface, 
 			       buf, 0, WDR_TIMEOUT);
 
 	kfree(buf);
@@ -909,6 +950,7 @@
 
 static int change_speed(struct usb_serial_port *port)
 {
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	char *buf;
         __u16 urb_value;
 	__u16 urb_index;
@@ -922,6 +964,9 @@
 	urb_index_value = get_ftdi_divisor(port);
 	urb_value = (__u16)urb_index_value;
 	urb_index = (__u16)(urb_index_value >> 16);
+	if (priv->interface) {	/* FT2232C */
+		urb_index = (__u16)((urb_index << 8) | priv->interface);
+	}
 	
 	rv = usb_control_msg(port->serial->dev,
 			    usb_sndctrlpipe(port->serial->dev, 0),
@@ -1015,7 +1060,12 @@
 		}
 		break;
 	case FT232BM: /* FT232BM chip */
-		chip_name = "FT232BM";
+	case FT2232C: /* FT2232C chip */
+		if (priv->chip_type == FT2232C) {
+			chip_name = "FT2232C";
+		} else {
+			chip_name = "FT232BM";
+		}
 		if (baud <= 3000000) {
 			div_value = ftdi_232bm_baud_to_divisor(baud);
 		} else {
@@ -1231,6 +1281,35 @@
 	return (0);
 } /* ftdi_FT232BM_startup */
 
+/* Startup for the FT2232C chip */
+/* Called from usbserial:serial_probe */
+static int ftdi_FT2232C_startup (struct usb_serial *serial)
+{ /* ftdi_FT2232C_startup */
+	struct ftdi_private *priv;
+	int err;
+	int inter;
+
+	dbg("%s",__FUNCTION__);
+	err = ftdi_common_startup(serial);
+	if (err){
+		return (err);
+	}
+
+	priv = usb_get_serial_port_data(serial->port[0]);
+	priv->chip_type = FT2232C;
+	inter = serial->interface->altsetting->desc.bInterfaceNumber;
+
+	if (inter) {
+		priv->interface = INTERFACE_B;
+	}
+	else  {
+		priv->interface = INTERFACE_A;
+	}
+	priv->baud_base = 48000000 / 2; /* Would be / 16, but FT2232C supports multiple of 0.125 divisor fractions! */
+	
+	return (0);
+} /* ftdi_FT2232C_startup */
+
 /* Startup for the USB-UIRT device, which requires hardwired baudrate (38400 gets mapped to 312500) */
 /* Called from usbserial:serial_probe */
 static int ftdi_USB_UIRT_startup (struct usb_serial *serial)
@@ -1323,7 +1402,7 @@
 	usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, 
 			FTDI_SIO_RESET_SIO, 
-			0, buf, 0, WDR_TIMEOUT);
+			priv->interface, buf, 0, WDR_TIMEOUT);
 
 	/* Termios defaults are set by usb_serial_init. We don't change
 	   port->tty->termios - this would loose speed settings, etc.
@@ -1373,6 +1452,7 @@
 static void ftdi_close (struct usb_serial_port *port, struct file *filp)
 { /* ftdi_close */
 	unsigned int c_cflag = port->tty->termios->c_cflag;
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	char buf[1];
 
 	dbg("%s", __FUNCTION__);
@@ -1383,7 +1463,8 @@
 				    usb_sndctrlpipe(port->serial->dev, 0),
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-				    0, 0, buf, 0, WDR_TIMEOUT) < 0) {
+				    0, priv->interface, buf, 0,
+				    WDR_TIMEOUT) < 0) {
 			err("error from flowcontrol urb");
 		}	    
 
@@ -1796,7 +1877,7 @@
 	if (usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
 			    FTDI_SIO_SET_DATA_REQUEST, 
 			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
-			    urb_value , 0,
+			    urb_value , priv->interface,
 			    buf, 0, WDR_TIMEOUT) < 0) {
 		err("%s FAILED to enable/disable break state (state was %d)", __FUNCTION__,break_state);
 	}	   
@@ -1875,7 +1956,7 @@
 	if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			    FTDI_SIO_SET_DATA_REQUEST, 
 			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
-			    urb_value , 0,
+			    urb_value , priv->interface,
 			    buf, 0, 100) < 0) {
 		err("%s FAILED to set databits/stopbits/parity", __FUNCTION__);
 	}	   
@@ -1886,7 +1967,7 @@
 		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-				    0, 0, 
+				    0, priv->interface, 
 				    buf, 0, WDR_TIMEOUT) < 0) {
 			err("%s error from disable flowcontrol urb", __FUNCTION__);
 		}	    
@@ -1903,6 +1984,13 @@
 		if (change_speed(port)) {
 			err("%s urb failed to set baurdrate", __FUNCTION__);
 		}
+		/* Ensure  RTS and DTR are raised */
+		else if (set_dtr(port, HIGH) < 0){
+			err("%s Error from DTR HIGH urb", __FUNCTION__);
+		}
+		else if (set_rts(port, HIGH) < 0){
+			err("%s Error from RTS HIGH urb", __FUNCTION__);
+		}	
 	}
 
 	/* Set flow control */
@@ -1913,7 +2001,7 @@
 				    usb_sndctrlpipe(dev, 0),
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-				    0 , FTDI_SIO_RTS_CTS_HS,
+				    0 , (FTDI_SIO_RTS_CTS_HS | priv->interface),
 				    buf, 0, WDR_TIMEOUT) < 0) {
 			err("urb failed to set to rts/cts flow control");
 		}		
@@ -1939,7 +2027,8 @@
 					    usb_sndctrlpipe(dev, 0),
 					    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
 					    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-					    urb_value , FTDI_SIO_XON_XOFF_HS,
+					    urb_value , (FTDI_SIO_XON_XOFF_HS
+							 | priv->interface),
 					    buf, 0, WDR_TIMEOUT) < 0) {
 				err("urb failed to set to xon/xoff flow control");
 			}
@@ -1951,7 +2040,7 @@
 					    usb_sndctrlpipe(dev, 0),
 					    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
 					    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-					    0, 0, 
+					    0, priv->interface, 
 					    buf, 0, WDR_TIMEOUT) < 0) {
 				err("urb failed to clear flow control");
 			}				
@@ -1985,13 +2074,14 @@
 		break;
 	case FT8U232AM:
 	case FT232BM:
+	case FT2232C:
 		/* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same
 		   format as the data returned from the in point */
 		if ((ret = usb_control_msg(port->serial->dev, 
 					   usb_rcvctrlpipe(port->serial->dev, 0),
 					   FTDI_SIO_GET_MODEM_STATUS_REQUEST, 
 					   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
-					   0, 0, 
+					   0, priv->interface, 
 					   buf, 2, WDR_TIMEOUT)) < 0 ) {
 			err("%s Could not get modem status of device - err: %d", __FUNCTION__,
 			    ret);
@@ -2206,6 +2296,9 @@
 	retval = usb_serial_register(&ftdi_FT232BM_device);
 	if (retval)
 		goto failed_FT232BM_register;
+	retval = usb_serial_register(&ftdi_FT2232C_device);
+	if (retval)
+		goto failed_FT2232C_register;
 	retval = usb_serial_register(&ftdi_USB_UIRT_device);
 	if (retval)
 		goto failed_USB_UIRT_register;
@@ -2223,6 +2316,8 @@
 failed_HE_TIRA1_register:
 	usb_serial_deregister(&ftdi_USB_UIRT_device);
 failed_USB_UIRT_register:
+	usb_serial_deregister(&ftdi_FT2232C_device);
+failed_FT2232C_register:
 	usb_serial_deregister(&ftdi_FT232BM_device);
 failed_FT232BM_register:
 	usb_serial_deregister(&ftdi_8U232AM_device);
@@ -2241,6 +2336,7 @@
 	usb_deregister (&ftdi_driver);
 	usb_serial_deregister (&ftdi_HE_TIRA1_device);
 	usb_serial_deregister (&ftdi_USB_UIRT_device);
+	usb_serial_deregister (&ftdi_FT2232C_device);
 	usb_serial_deregister (&ftdi_FT232BM_device);
 	usb_serial_deregister (&ftdi_8U232AM_device);
 	usb_serial_deregister (&ftdi_SIO_device);
diff -Nru a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
--- a/drivers/usb/serial/ftdi_sio.h	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/serial/ftdi_sio.h	2004-08-04 17:58:04 -07:00
@@ -26,6 +26,7 @@
 #define FTDI_SIO_PID	0x8372	/* Product Id SIO application of 8U100AX  */
 #define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */
 #define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
+#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
 #define FTDI_RELAIS_PID	0xFA10  /* Relais device from Rudolf Gugler */
 #define FTDI_NF_RIC_VID	0x0DCD	/* Vendor Id */
 #define FTDI_NF_RIC_PID	0x0001	/* Product Id */
@@ -234,6 +235,21 @@
 #define FTDI_SIO_SET_EVENT_CHAR	6 /* Set the event character */
 #define FTDI_SIO_SET_ERROR_CHAR	7 /* Set the error character */
 
+/* Port interface code for FT2232C */
+#define INTERFACE_A		1
+#define INTERFACE_B		2
+
+
+/*
+ *   BmRequestType:  1100 0000b
+ *   bRequest:       FTDI_E2_READ
+ *   wValue:         0
+ *   wIndex:         Address of word to read
+ *   wLength:        2
+ *   Data:           Will return a word of data from E2Address
+ *
+ */
+
 /* Port Identifier Table */
 #define PIT_DEFAULT 		0 /* SIOA */
 #define PIT_SIOA		1 /* SIOA */
@@ -333,6 +349,7 @@
 	SIO = 1,
 	FT8U232AM = 2,
 	FT232BM = 3,
+	FT2232C = 4,
 } ftdi_chip_type_t;
 
 typedef enum {
diff -Nru a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
--- a/drivers/usb/serial/ipaq.c	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/serial/ipaq.c	2004-08-04 17:58:04 -07:00
@@ -188,6 +188,7 @@
 	usb_set_serial_port_data(port, priv);
 	priv->active = 0;
 	priv->queue_len = 0;
+	priv->free_len = 0;
 	INIT_LIST_HEAD(&priv->queue);
 	INIT_LIST_HEAD(&priv->freelist);
 
diff -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
--- a/drivers/usb/serial/pl2303.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/serial/pl2303.c	2004-08-04 17:58:03 -07:00
@@ -659,7 +659,7 @@
 		state = BREAK_OFF;
 	else
 		state = BREAK_ON;
-	dbg("%s - turning break %s", state==BREAK_OFF ? "off" : "on", __FUNCTION__);
+	dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on");
 
 	result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
 				  BREAK_REQUEST, BREAK_REQUEST_TYPE, state, 
diff -Nru a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
--- a/drivers/usb/storage/datafab.c	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/storage/datafab.c	2004-08-04 17:58:04 -07:00
@@ -50,16 +50,19 @@
  * in that routine.
  */
 
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "datafab.h"
 
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
 static int datafab_determine_lun(struct us_data *us,
 				 struct datafab_info *info);
 
@@ -388,7 +391,7 @@
 
 
 static int datafab_handle_mode_sense(struct us_data *us,
-				     Scsi_Cmnd * srb, 
+				     struct scsi_cmnd * srb, 
 				     int sense_6)
 {
 	static unsigned char rw_err_page[12] = {
@@ -498,7 +501,7 @@
 
 // Transport for the Datafab MDCFE-B
 //
-int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
+int datafab_transport(struct scsi_cmnd * srb, struct us_data *us)
 {
 	struct datafab_info *info;
 	int rc;
@@ -625,12 +628,12 @@
 
 	if (srb->cmnd[0] == MODE_SENSE) {
 		US_DEBUGP("datafab_transport:  MODE_SENSE_6 detected\n");
-		return datafab_handle_mode_sense(us, srb, TRUE);
+		return datafab_handle_mode_sense(us, srb, 1);
 	}
 
 	if (srb->cmnd[0] == MODE_SENSE_10) {
 		US_DEBUGP("datafab_transport:  MODE_SENSE_10 detected\n");
-		return datafab_handle_mode_sense(us, srb, FALSE);
+		return datafab_handle_mode_sense(us, srb, 0);
 	}
 
 	if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
diff -Nru a/drivers/usb/storage/datafab.h b/drivers/usb/storage/datafab.h
--- a/drivers/usb/storage/datafab.h	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/storage/datafab.h	2004-08-04 17:58:04 -07:00
@@ -24,7 +24,7 @@
 #ifndef _USB_DATAFAB_MDCFE_B_H
 #define _USB_DATAFAB_MDCFE_B_H
 
-extern int datafab_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int datafab_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 struct datafab_info {
 	unsigned long   sectors;	// total sector count
diff -Nru a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c
--- a/drivers/usb/storage/debug.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/debug.c	2004-08-04 17:58:03 -07:00
@@ -44,9 +44,15 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/cdrom.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "debug.h"
+#include "scsi.h"
+
 
-void usb_stor_show_command(Scsi_Cmnd *srb)
+void usb_stor_show_command(struct scsi_cmnd *srb)
 {
 	char *what = NULL;
 	int i;
diff -Nru a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h
--- a/drivers/usb/storage/debug.h	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/storage/debug.h	2004-08-04 17:58:04 -07:00
@@ -46,13 +46,13 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include "usb.h"
+
+struct scsi_cmnd;
 
 #define USB_STORAGE "usb-storage: "
 
 #ifdef CONFIG_USB_STORAGE_DEBUG
-void usb_stor_show_command(Scsi_Cmnd *srb);
+void usb_stor_show_command(struct scsi_cmnd *srb);
 void usb_stor_show_sense( unsigned char key,
 		unsigned char asc, unsigned char ascq );
 #define US_DEBUGP(x...) printk( KERN_DEBUG USB_STORAGE x )
diff -Nru a/drivers/usb/storage/dpcm.c b/drivers/usb/storage/dpcm.c
--- a/drivers/usb/storage/dpcm.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/dpcm.c	2004-08-04 17:58:03 -07:00
@@ -30,6 +30,10 @@
  */
 
 #include <linux/config.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
@@ -41,7 +45,7 @@
  * Transport for the Microtech DPCM-USB
  *
  */
-int dpcm_transport(Scsi_Cmnd *srb, struct us_data *us)
+int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
   int ret;
 
diff -Nru a/drivers/usb/storage/dpcm.h b/drivers/usb/storage/dpcm.h
--- a/drivers/usb/storage/dpcm.h	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/dpcm.h	2004-08-04 17:58:03 -07:00
@@ -29,6 +29,6 @@
 #ifndef _MICROTECH_DPCM_USB_H
 #define _MICROTECH_DPCM_USB_H
 
-extern int dpcm_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 #endif
diff -Nru a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
--- a/drivers/usb/storage/freecom.c	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/storage/freecom.c	2004-08-04 17:58:04 -07:00
@@ -29,12 +29,16 @@
  */
 
 #include <linux/config.h>
+#include <linux/hdreg.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "freecom.h"
-#include "linux/hdreg.h"
 
 #ifdef CONFIG_USB_STORAGE_DEBUG
 static void pdump (void *, int);
@@ -105,7 +109,7 @@
 #define FCM_STATUS_PACKET_LENGTH	4
 
 static int
-freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
+freecom_readdata (struct scsi_cmnd *srb, struct us_data *us,
 		unsigned int ipipe, unsigned int opipe, int count)
 {
 	struct freecom_xfer_wrap *fxfr =
@@ -139,7 +143,7 @@
 }
 
 static int
-freecom_writedata (Scsi_Cmnd *srb, struct us_data *us,
+freecom_writedata (struct scsi_cmnd *srb, struct us_data *us,
 		int unsigned ipipe, unsigned int opipe, int count)
 {
 	struct freecom_xfer_wrap *fxfr =
@@ -176,7 +180,7 @@
  * Transport for the Freecom USB/IDE adaptor.
  *
  */
-int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
+int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	struct freecom_cb_wrap *fcb;
 	struct freecom_status  *fst;
@@ -302,7 +306,7 @@
 	 * move in. */
 
 	switch (us->srb->sc_data_direction) {
-	case SCSI_DATA_READ:
+	case DMA_FROM_DEVICE:
 		/* catch bogus "read 0 length" case */
 		if (!length)
 			break;
@@ -334,7 +338,7 @@
 		US_DEBUGP("Transfer happy\n");
 		break;
 
-	case SCSI_DATA_WRITE:
+	case DMA_TO_DEVICE:
 		/* catch bogus "write 0 length" case */
 		if (!length)
 			break;
@@ -364,7 +368,7 @@
 		break;
 
 
-	case SCSI_DATA_NONE:
+	case DMA_NONE:
 		/* Easy, do nothing. */
 		break;
 
diff -Nru a/drivers/usb/storage/freecom.h b/drivers/usb/storage/freecom.h
--- a/drivers/usb/storage/freecom.h	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/freecom.h	2004-08-04 17:58:03 -07:00
@@ -29,7 +29,7 @@
 #ifndef _FREECOM_USB_H
 #define _FREECOM_USB_H
 
-extern int freecom_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int freecom_transport(struct scsi_cmnd *srb, struct us_data *us);
 extern int usb_stor_freecom_reset(struct us_data *us);
 extern int freecom_init (struct us_data *us);
 
diff -Nru a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
--- a/drivers/usb/storage/isd200.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/isd200.c	2004-08-04 17:58:03 -07:00
@@ -44,6 +44,16 @@
 
 /* Include files */
 
+#include <linux/jiffies.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
@@ -51,11 +61,6 @@
 #include "scsiglue.h"
 #include "isd200.h"
 
-#include <linux/jiffies.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/hdreg.h>
-#include <linux/ide.h>
 
 /* Timeout defines (in Seconds) */
 
@@ -349,7 +354,7 @@
  * RETURNS:
  *    void
  */
-static void isd200_build_sense(struct us_data *us, Scsi_Cmnd *srb)
+static void isd200_build_sense(struct us_data *us, struct scsi_cmnd *srb)
 {
 	struct isd200_info *info = (struct isd200_info *)us->extra;
 	struct sense_data *buf = (struct sense_data *) &srb->sense_buffer[0];
@@ -427,7 +432,7 @@
 		ata.generic.RegisterSelect =
 		  REG_CYLINDER_LOW | REG_CYLINDER_HIGH |
 		  REG_STATUS | REG_ERROR;
-		srb->sc_data_direction = SCSI_DATA_READ;
+		srb->sc_data_direction = DMA_FROM_DEVICE;
 		srb->request_buffer = pointer;
 		srb->request_bufflen = value;
 		break;
@@ -439,7 +444,7 @@
 					   ACTION_SELECT_5;
 		ata.generic.RegisterSelect = REG_DEVICE_HEAD;
 		ata.write.DeviceHeadByte = value;
-		srb->sc_data_direction = SCSI_DATA_NONE;
+		srb->sc_data_direction = DMA_NONE;
 		break;
 
 	case ACTION_RESET:
@@ -448,7 +453,7 @@
 					   ACTION_SELECT_3|ACTION_SELECT_4;
 		ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
 		ata.write.DeviceControlByte = ATA_DC_RESET_CONTROLLER;
-		srb->sc_data_direction = SCSI_DATA_NONE;
+		srb->sc_data_direction = DMA_NONE;
 		break;
 
 	case ACTION_REENABLE:
@@ -457,7 +462,7 @@
 					   ACTION_SELECT_3|ACTION_SELECT_4;
 		ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
 		ata.write.DeviceControlByte = ATA_DC_REENABLE_CONTROLLER;
-		srb->sc_data_direction = SCSI_DATA_NONE;
+		srb->sc_data_direction = DMA_NONE;
 		break;
 
 	case ACTION_SOFT_RESET:
@@ -466,14 +471,14 @@
 		ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND;
 		ata.write.DeviceHeadByte = info->DeviceHead;
 		ata.write.CommandByte = WIN_SRST;
-		srb->sc_data_direction = SCSI_DATA_NONE;
+		srb->sc_data_direction = DMA_NONE;
 		break;
 
 	case ACTION_IDENTIFY:
 		US_DEBUGP("   isd200_action(IDENTIFY)\n");
 		ata.generic.RegisterSelect = REG_COMMAND;
 		ata.write.CommandByte = WIN_IDENTIFY;
-		srb->sc_data_direction = SCSI_DATA_READ;
+		srb->sc_data_direction = DMA_FROM_DEVICE;
 		srb->request_buffer = (void *) info->id;
 		srb->request_bufflen = sizeof(struct hd_driveid);
 		break;
@@ -535,7 +540,7 @@
  * the device and receive the response.
  */
 static void isd200_invoke_transport( struct us_data *us, 
-			      Scsi_Cmnd *srb, 
+			      struct scsi_cmnd *srb, 
 			      union ata_cdb *ataCdb )
 {
 	int need_auto_sense = 0;
@@ -839,7 +844,7 @@
 	unsigned long endTime;
 	struct isd200_info *info = (struct isd200_info *)us->extra;
 	unsigned char *regs = info->RegsBuf;
-	int recheckAsMaster = FALSE;
+	int recheckAsMaster = 0;
 
 	if ( detect )
 		endTime = jiffies + ISD200_ENUM_DETECT_TIMEOUT * HZ;
@@ -847,7 +852,7 @@
 		endTime = jiffies + ISD200_ENUM_BSY_TIMEOUT * HZ;
 
 	/* loop until we detect !BSY or timeout */
-	while(TRUE) {
+	while(1) {
 #ifdef CONFIG_USB_STORAGE_DEBUG
 		char* mstr = master_slave == ATA_ADDRESS_DEVHEAD_STD ?
 			"Master" : "Slave";
@@ -899,9 +904,9 @@
 			   itself okay as a master also
 			*/
 			if ((master_slave & ATA_ADDRESS_DEVHEAD_SLAVE) &&
-			    (recheckAsMaster == FALSE)) {
+			    !recheckAsMaster) {
 				US_DEBUGP("   Identified ATAPI device as slave.  Rechecking again as master\n");
-				recheckAsMaster = TRUE;
+				recheckAsMaster = 1;
 				master_slave = ATA_ADDRESS_DEVHEAD_STD;
 			} else {
 				US_DEBUGP("   Identified ATAPI device\n");
@@ -948,15 +953,15 @@
 	if (retStatus == ISD200_GOOD) {
 		int isslave;
 		/* master or slave? */
-		retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, FALSE );
+		retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, 0);
 		if (retStatus == ISD200_GOOD)
-			retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_SLAVE, FALSE );
+			retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_SLAVE, 0);
 
 		if (retStatus == ISD200_GOOD) {
 			retStatus = isd200_srst(us);
 			if (retStatus == ISD200_GOOD)
 				/* ata or atapi? */
-				retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, TRUE );
+				retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, 1);
 		}
 
 		isslave = (info->DeviceHead & ATA_ADDRESS_DEVHEAD_SLAVE) ? 1 : 0;
@@ -1121,15 +1126,15 @@
  * Translate SCSI commands to ATA commands.
  *
  * RETURNS:
- *    TRUE if the command needs to be sent to the transport layer
- *    FALSE otherwise
+ *    1 if the command needs to be sent to the transport layer
+ *    0 otherwise
  */
-static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
+static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
 			      union ata_cdb * ataCdb)
 {
 	struct isd200_info *info = (struct isd200_info *)us->extra;
 	struct hd_driveid *id = info->id;
-	int sendToTransport = TRUE;
+	int sendToTransport = 1;
 	unsigned char sectnum, head;
 	unsigned short cylinder;
 	unsigned long lba;
@@ -1147,7 +1152,7 @@
 		usb_stor_set_xfer_buf((unsigned char *) &info->InquiryData,
 				sizeof(info->InquiryData), srb);
 		srb->result = SAM_STAT_GOOD;
-		sendToTransport = FALSE;
+		sendToTransport = 0;
 		break;
 
 	case MODE_SENSE:
@@ -1167,7 +1172,7 @@
 		} else {
 			US_DEBUGP("   Media Status not supported, just report okay\n");
 			srb->result = SAM_STAT_GOOD;
-			sendToTransport = FALSE;
+			sendToTransport = 0;
 		}
 		break;
 
@@ -1185,7 +1190,7 @@
 		} else {
 			US_DEBUGP("   Media Status not supported, just report okay\n");
 			srb->result = SAM_STAT_GOOD;
-			sendToTransport = FALSE;
+			sendToTransport = 0;
 		}
 		break;
 
@@ -1209,7 +1214,7 @@
 		usb_stor_set_xfer_buf((unsigned char *) &readCapacityData,
 				sizeof(readCapacityData), srb);
 		srb->result = SAM_STAT_GOOD;
-		sendToTransport = FALSE;
+		sendToTransport = 0;
 	}
 	break;
 
@@ -1293,7 +1298,7 @@
 		} else {
 			US_DEBUGP("   Not removeable media, just report okay\n");
 			srb->result = SAM_STAT_GOOD;
-			sendToTransport = FALSE;
+			sendToTransport = 0;
 		}
 		break;
 
@@ -1319,14 +1324,14 @@
 		} else {
 			US_DEBUGP("   Nothing to do, just report okay\n");
 			srb->result = SAM_STAT_GOOD;
-			sendToTransport = FALSE;
+			sendToTransport = 0;
 		}
 		break;
 
 	default:
 		US_DEBUGP("Unsupported SCSI command - 0x%X\n", srb->cmnd[0]);
 		srb->result = DID_ERROR << 16;
-		sendToTransport = FALSE;
+		sendToTransport = 0;
 		break;
 	}
 
@@ -1424,9 +1429,9 @@
  *
  */
 
-void isd200_ata_command(Scsi_Cmnd *srb, struct us_data *us)
+void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us)
 {
-	int sendToTransport = TRUE;
+	int sendToTransport = 1;
 	union ata_cdb ataCdb;
 
 	/* Make sure driver was initialized */
diff -Nru a/drivers/usb/storage/isd200.h b/drivers/usb/storage/isd200.h
--- a/drivers/usb/storage/isd200.h	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/isd200.h	2004-08-04 17:58:03 -07:00
@@ -25,7 +25,7 @@
 #ifndef _USB_ISD200_H
 #define _USB_ISD200_H
 
-extern void isd200_ata_command(Scsi_Cmnd *srb, struct us_data *us);
+extern void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us);
 extern int isd200_Initialization(struct us_data *us);
 
 #endif
diff -Nru a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
--- a/drivers/usb/storage/jumpshot.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/jumpshot.c	2004-08-04 17:58:03 -07:00
@@ -47,15 +47,19 @@
   * in that routine.
   */
 
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "jumpshot.h"
 
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
 
 static inline int jumpshot_bulk_read(struct us_data *us,
 				     unsigned char *data, 
@@ -319,7 +323,7 @@
 }
 
 static int jumpshot_handle_mode_sense(struct us_data *us,
-				      Scsi_Cmnd * srb, 
+				      struct scsi_cmnd * srb, 
 				      int sense_6)
 {
 	static unsigned char rw_err_page[12] = {
@@ -426,7 +430,7 @@
 
 // Transport for the Lexar 'Jumpshot'
 //
-int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us)
+int jumpshot_transport(struct scsi_cmnd * srb, struct us_data *us)
 {
 	struct jumpshot_info *info;
 	int rc;
@@ -551,12 +555,12 @@
 
 	if (srb->cmnd[0] == MODE_SENSE) {
 		US_DEBUGP("jumpshot_transport:  MODE_SENSE_6 detected\n");
-		return jumpshot_handle_mode_sense(us, srb, TRUE);
+		return jumpshot_handle_mode_sense(us, srb, 1);
 	}
 
 	if (srb->cmnd[0] == MODE_SENSE_10) {
 		US_DEBUGP("jumpshot_transport:  MODE_SENSE_10 detected\n");
-		return jumpshot_handle_mode_sense(us, srb, FALSE);
+		return jumpshot_handle_mode_sense(us, srb, 0);
 	}
 
 	if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
diff -Nru a/drivers/usb/storage/jumpshot.h b/drivers/usb/storage/jumpshot.h
--- a/drivers/usb/storage/jumpshot.h	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/jumpshot.h	2004-08-04 17:58:03 -07:00
@@ -24,7 +24,7 @@
 #ifndef _USB_JUMPSHOT_H
 #define _USB_JUMPSHOT_H
 
-extern int jumpshot_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 struct jumpshot_info {
    unsigned long   sectors;     // total sector count
diff -Nru a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
--- a/drivers/usb/storage/protocol.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/protocol.c	2004-08-04 17:58:03 -07:00
@@ -45,6 +45,8 @@
  */
 
 #include <linux/highmem.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
@@ -59,7 +61,7 @@
  * Fix-up the return data from an INQUIRY command to show 
  * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us
  */
-static void fix_inquiry_data(Scsi_Cmnd *srb)
+static void fix_inquiry_data(struct scsi_cmnd *srb)
 {
 	unsigned char databuf[3];
 	unsigned int index, offset;
@@ -91,7 +93,7 @@
  * Fix-up the return data from a READ CAPACITY command. My Feiya reader
  * returns a value that is 1 too large.
  */
-static void fix_read_capacity(Scsi_Cmnd *srb)
+static void fix_read_capacity(struct scsi_cmnd *srb)
 {
 	unsigned int index, offset;
 	u32 c;
@@ -120,11 +122,11 @@
  * Protocol routines
  ***********************************************************************/
 
-void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_qic157_command(struct scsi_cmnd *srb, struct us_data *us)
 {
 	/* Pad the ATAPI command with zeros 
 	 *
-	 * NOTE: This only works because a Scsi_Cmnd struct field contains
+	 * NOTE: This only works because a scsi_cmnd struct field contains
 	 * a unsigned char cmnd[16], so we know we have storage available
 	 */
 	for (; srb->cmd_len<12; srb->cmd_len++)
@@ -141,11 +143,11 @@
 	}
 }
 
-void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_ATAPI_command(struct scsi_cmnd *srb, struct us_data *us)
 {
 	/* Pad the ATAPI command with zeros 
 	 *
-	 * NOTE: This only works because a Scsi_Cmnd struct field contains
+	 * NOTE: This only works because a scsi_cmnd struct field contains
 	 * a unsigned char cmnd[16], so we know we have storage available
 	 */
 
@@ -166,12 +168,12 @@
 }
 
 
-void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_ufi_command(struct scsi_cmnd *srb, struct us_data *us)
 {
 	/* fix some commands -- this is a form of mode translation
 	 * UFI devices only accept 12 byte long commands 
 	 *
-	 * NOTE: This only works because a Scsi_Cmnd struct field contains
+	 * NOTE: This only works because a scsi_cmnd struct field contains
 	 * a unsigned char cmnd[16], so we know we have storage available
 	 */
 
@@ -213,7 +215,8 @@
 	}
 }
 
-void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb,
+				       struct us_data *us)
 {
 	/* send the command to the transport layer */
 	usb_stor_invoke_transport(srb, us);
@@ -241,7 +244,7 @@
  * pick up from where this one left off. */
 
 unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
-	unsigned int buflen, Scsi_Cmnd *srb, unsigned int *index,
+	unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
 	unsigned int *offset, enum xfer_buf_dir dir)
 {
 	unsigned int cnt;
@@ -327,7 +330,7 @@
 /* Store the contents of buffer into srb's transfer buffer and set the
  * SCSI residue. */
 void usb_stor_set_xfer_buf(unsigned char *buffer,
-	unsigned int buflen, Scsi_Cmnd *srb)
+	unsigned int buflen, struct scsi_cmnd *srb)
 {
 	unsigned int index = 0, offset = 0;
 
diff -Nru a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h
--- a/drivers/usb/storage/protocol.h	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/protocol.h	2004-08-04 17:58:03 -07:00
@@ -41,9 +41,8 @@
 #ifndef _PROTOCOL_H_
 #define _PROTOCOL_H_
 
-#include <linux/blkdev.h>
-#include "scsi.h"
-#include "usb.h"
+struct scsi_cmnd;
+struct us_data;
 
 /* Sub Classes */
 
@@ -60,18 +59,19 @@
 #define US_SC_DEVICE	0xff		/* Use device's value */
 
 /* Protocol handling routines */
-extern void usb_stor_ATAPI_command(Scsi_Cmnd*, struct us_data*);
-extern void usb_stor_qic157_command(Scsi_Cmnd*, struct us_data*);
-extern void usb_stor_ufi_command(Scsi_Cmnd*, struct us_data*);
-extern void usb_stor_transparent_scsi_command(Scsi_Cmnd*, struct us_data*);
+extern void usb_stor_ATAPI_command(struct scsi_cmnd*, struct us_data*);
+extern void usb_stor_qic157_command(struct scsi_cmnd*, struct us_data*);
+extern void usb_stor_ufi_command(struct scsi_cmnd*, struct us_data*);
+extern void usb_stor_transparent_scsi_command(struct scsi_cmnd*,
+		struct us_data*);
 
-/* Scsi_Cmnd transfer buffer access utilities */
+/* struct scsi_cmnd transfer buffer access utilities */
 enum xfer_buf_dir	{TO_XFER_BUF, FROM_XFER_BUF};
 
 extern unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
-	unsigned int buflen, Scsi_Cmnd *srb, unsigned int *index,
+	unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
 	unsigned int *offset, enum xfer_buf_dir dir);
 
 extern void usb_stor_set_xfer_buf(unsigned char *buffer,
-	unsigned int buflen, Scsi_Cmnd *srb);
+	unsigned int buflen, struct scsi_cmnd *srb);
 #endif
diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
--- a/drivers/usb/storage/scsiglue.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/scsiglue.c	2004-08-04 17:58:03 -07:00
@@ -44,17 +44,23 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-#include "scsiglue.h"
-#include "usb.h"
-#include "debug.h"
-#include "transport.h"
-#include "protocol.h"
 
 #include <linux/slab.h>
 #include <linux/module.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_devinfo.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
 #include <scsi/scsi_host.h>
 
+#include "scsiglue.h"
+#include "usb.h"
+#include "debug.h"
+#include "transport.h"
+#include "protocol.h"
+
 /***********************************************************************
  * Host functions 
  ***********************************************************************/
@@ -92,17 +98,15 @@
 	 * the end, scatter-gather buffers follow page boundaries. */
 	blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
 
-	/* Devices using Genesys Logic chips cause a lot of trouble for
-	 * high-speed transfers; they die unpredictably when given more
-	 * than 64 KB of data at a time.  If we detect such a device,
-	 * reduce the maximum transfer size to 64 KB = 128 sectors. */
-
-#define USB_VENDOR_ID_GENESYS	0x05e3		// Needs a standard location
-
+	/* According to the technical support people at Genesys Logic,
+	 * devices using their chips have problems transferring more than
+	 * 32 KB at a time.  In practice people have found that 64 KB
+	 * works okay and that's what Windows does.  But we'll be
+	 * conservative; people can always use the sysfs interface to
+	 * increase max_sectors. */
 	if (us->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS &&
-			us->pusb_dev->speed == USB_SPEED_HIGH &&
-			sdev->request_queue->max_sectors > 128)
-		blk_queue_max_sectors(sdev->request_queue, 128);
+			sdev->request_queue->max_sectors > 64)
+		blk_queue_max_sectors(sdev->request_queue, 64);
 
 	/* We can't put these settings in slave_alloc() because that gets
 	 * called before the device type is known.  Consequently these
@@ -146,7 +150,8 @@
 
 /* queue a command */
 /* This is always called with scsi_lock(srb->host) held */
-static int queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *))
+static int queuecommand(struct scsi_cmnd *srb,
+			void (*done)(struct scsi_cmnd *))
 {
 	struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
 
@@ -176,7 +181,7 @@
 
 /* Command abort */
 /* This is always called with scsi_lock(srb->host) held */
-static int command_abort( Scsi_Cmnd *srb )
+static int command_abort(struct scsi_cmnd *srb )
 {
 	struct Scsi_Host *host = srb->device->host;
 	struct us_data *us = (struct us_data *) host->hostdata[0];
@@ -223,7 +228,7 @@
 /* This invokes the transport reset mechanism to reset the state of the
  * device */
 /* This is always called with scsi_lock(srb->host) held */
-static int device_reset( Scsi_Cmnd *srb )
+static int device_reset(struct scsi_cmnd *srb)
 {
 	struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
 	int result;
@@ -258,7 +263,7 @@
 /* It refuses to work if there's more than one interface in
  * the device, so that other users are not affected. */
 /* This is always called with scsi_lock(srb->host) held */
-static int bus_reset( Scsi_Cmnd *srb )
+static int bus_reset(struct scsi_cmnd *srb)
 {
 	struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
 	int result;
@@ -444,10 +449,10 @@
 	 * periodically someone should test to see which setting is more
 	 * optimal.
 	 */
-	.use_clustering =		TRUE,
+	.use_clustering =		1,
 
 	/* emulated HBA */
-	.emulated =			TRUE,
+	.emulated =			1,
 
 	/* we do our own delay after a device or bus reset */
 	.skip_settle_delay =		1,
diff -Nru a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h
--- a/drivers/usb/storage/scsiglue.h	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/scsiglue.h	2004-08-04 17:58:03 -07:00
@@ -41,17 +41,15 @@
 #ifndef _SCSIGLUE_H_
 #define _SCSIGLUE_H_
 
-#include <linux/blkdev.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
-#include "usb.h"
+
+struct us_data;
+struct scsi_cmnd;
 
 extern void usb_stor_report_device_reset(struct us_data *us);
 
 extern unsigned char usb_stor_sense_notready[18];
 extern unsigned char usb_stor_sense_invalidCDB[18];
 extern struct scsi_host_template usb_stor_host_template;
-extern int usb_stor_scsiSense10to6(Scsi_Cmnd*);
-extern int usb_stor_scsiSense6to10(Scsi_Cmnd*);
 
 #endif
diff -Nru a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
--- a/drivers/usb/storage/sddr09.c	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/storage/sddr09.c	2004-08-04 17:58:04 -07:00
@@ -41,16 +41,19 @@
  * EF: compute checksum (?)
  */
 
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "sddr09.h"
 
-#include <linux/version.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
 
 #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
 #define LSB_of(s) ((s)&0xFF)
@@ -1401,7 +1404,7 @@
 /*
  * Transport for the Sandisk SDDR-09
  */
-int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
+int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	static unsigned char sensekey = 0, sensecode = 0;
 	static unsigned char havefakesense = 0;
@@ -1581,13 +1584,13 @@
 	if (srb->request_bufflen == 0)
 		return USB_STOR_TRANSPORT_GOOD;
 
-	if (srb->sc_data_direction == SCSI_DATA_WRITE ||
-	    srb->sc_data_direction == SCSI_DATA_READ) {
-		unsigned int pipe = (srb->sc_data_direction == SCSI_DATA_WRITE)
+	if (srb->sc_data_direction == DMA_TO_DEVICE ||
+	    srb->sc_data_direction == DMA_FROM_DEVICE) {
+		unsigned int pipe = (srb->sc_data_direction == DMA_TO_DEVICE)
 				? us->send_bulk_pipe : us->recv_bulk_pipe;
 
 		US_DEBUGP("SDDR09: %s %d bytes\n",
-			  (srb->sc_data_direction == SCSI_DATA_WRITE) ?
+			  (srb->sc_data_direction == DMA_TO_DEVICE) ?
 			  "sending" : "receiving",
 			  srb->request_bufflen);
 
diff -Nru a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h
--- a/drivers/usb/storage/sddr09.h	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/sddr09.h	2004-08-04 17:58:03 -07:00
@@ -29,7 +29,7 @@
 
 /* Sandisk SDDR-09 stuff */
 
-extern int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 struct sddr09_card_info {
 	unsigned long	capacity;	/* Size of card in bytes */
diff -Nru a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
--- a/drivers/usb/storage/sddr55.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/sddr55.c	2004-08-04 17:58:03 -07:00
@@ -24,15 +24,19 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/jiffies.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "sddr55.h"
 
-#include <linux/jiffies.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
 
 #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
 #define LSB_of(s) ((s)&0xFF)
@@ -74,7 +78,7 @@
 sddr55_bulk_transport(struct us_data *us, int direction,
 		      unsigned char *data, unsigned int len) {
 	struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
-	unsigned int pipe = (direction == SCSI_DATA_READ) ?
+	unsigned int pipe = (direction == DMA_FROM_DEVICE) ?
 			us->recv_bulk_pipe : us->send_bulk_pipe;
 
 	if (!len)
@@ -99,7 +103,7 @@
 	command[5] = 0xB0;
 	command[7] = 0x80;
 	result = sddr55_bulk_transport(us,
-		SCSI_DATA_WRITE, command, 8);
+		DMA_TO_DEVICE, command, 8);
 
 	US_DEBUGP("Result for send_command in status %d\n",
 		result);
@@ -110,7 +114,7 @@
 	}
 
 	result = sddr55_bulk_transport(us,
-		SCSI_DATA_READ, status,	4);
+		DMA_FROM_DEVICE, status,	4);
 
 	/* expect to get short transfer if no card fitted */
 	if (result == USB_STOR_XFER_SHORT || result == USB_STOR_XFER_STALLED) {
@@ -139,7 +143,7 @@
 
 	/* now read status */
 	result = sddr55_bulk_transport(us,
-		SCSI_DATA_READ, status,	2);
+		DMA_FROM_DEVICE, status,	2);
 
 	if (result != USB_STOR_XFER_GOOD) {
 		set_sense_info (4, 0, 0);	/* hardware error */
@@ -215,7 +219,7 @@
 
 			/* send command */
 			result = sddr55_bulk_transport(us,
-				SCSI_DATA_WRITE, command, 8);
+				DMA_TO_DEVICE, command, 8);
 
 			US_DEBUGP("Result for send_command in read_data %d\n",
 				result);
@@ -227,7 +231,7 @@
 
 			/* read data */
 			result = sddr55_bulk_transport(us,
-				SCSI_DATA_READ, buffer, len);
+				DMA_FROM_DEVICE, buffer, len);
 
 			if (result != USB_STOR_XFER_GOOD) {
 				result = USB_STOR_TRANSPORT_ERROR;
@@ -236,7 +240,7 @@
 
 			/* now read status */
 			result = sddr55_bulk_transport(us,
-				SCSI_DATA_READ, status, 2);
+				DMA_FROM_DEVICE, status, 2);
 
 			if (result != USB_STOR_XFER_GOOD) {
 				result = USB_STOR_TRANSPORT_ERROR;
@@ -390,7 +394,7 @@
 
 		/* send command */
 		result = sddr55_bulk_transport(us,
-			SCSI_DATA_WRITE, command, 8);
+			DMA_TO_DEVICE, command, 8);
 
 		if (result != USB_STOR_XFER_GOOD) {
 			US_DEBUGP("Result for send_command in write_data %d\n",
@@ -404,7 +408,7 @@
 
 		/* send the data */
 		result = sddr55_bulk_transport(us,
-			SCSI_DATA_WRITE, buffer, len);
+			DMA_TO_DEVICE, buffer, len);
 
 		if (result != USB_STOR_XFER_GOOD) {
 			US_DEBUGP("Result for send_data in write_data %d\n",
@@ -417,7 +421,7 @@
 		}
 
 		/* now read status */
-		result = sddr55_bulk_transport(us, SCSI_DATA_READ, status, 6);
+		result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, status, 6);
 
 		if (result != USB_STOR_XFER_GOOD) {
 			US_DEBUGP("Result for get_status in write_data %d\n",
@@ -483,7 +487,7 @@
 	memset(command, 0, 8);
 	command[5] = 0xB0;
 	command[7] = 0x84;
-	result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8);
+	result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8);
 
 	US_DEBUGP("Result of send_control for device ID is %d\n",
 		result);
@@ -492,7 +496,7 @@
 		return USB_STOR_TRANSPORT_ERROR;
 
 	result = sddr55_bulk_transport(us,
-		SCSI_DATA_READ, content, 4);
+		DMA_FROM_DEVICE, content, 4);
 
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
@@ -502,7 +506,7 @@
 
 	if (content[0] != 0xff)	{
     		result = sddr55_bulk_transport(us,
-			SCSI_DATA_READ, content, 2);
+			DMA_FROM_DEVICE, content, 2);
 	}
 
 	return USB_STOR_TRANSPORT_GOOD;
@@ -624,21 +628,21 @@
 	command[6] = numblocks * 2 / 256;
 	command[7] = 0x8A;
 
-	result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8);
+	result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8);
 
 	if ( result != USB_STOR_XFER_GOOD) {
 		kfree (buffer);
 		return -1;
 	}
 
-	result = sddr55_bulk_transport(us, SCSI_DATA_READ, buffer, numblocks * 2);
+	result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, buffer, numblocks * 2);
 
 	if ( result != USB_STOR_XFER_GOOD) {
 		kfree (buffer);
 		return -1;
 	}
 
-	result = sddr55_bulk_transport(us, SCSI_DATA_READ, command, 2);
+	result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, command, 2);
 
 	if ( result != USB_STOR_XFER_GOOD) {
 		kfree (buffer);
@@ -734,7 +738,7 @@
 /*
  * Transport for the Sandisk SDDR-55
  */
-int sddr55_transport(Scsi_Cmnd *srb, struct us_data *us)
+int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	int result;
 	static unsigned char inquiry_response[8] = {
diff -Nru a/drivers/usb/storage/sddr55.h b/drivers/usb/storage/sddr55.h
--- a/drivers/usb/storage/sddr55.h	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/storage/sddr55.h	2004-08-04 17:58:04 -07:00
@@ -28,7 +28,7 @@
 
 /* Sandisk SDDR-55 stuff */
 
-extern int sddr55_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us);
 extern int sddr55_reset(struct us_data *us);
 
 #endif
diff -Nru a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
--- a/drivers/usb/storage/shuttle_usbat.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/shuttle_usbat.c	2004-08-04 17:58:03 -07:00
@@ -39,16 +39,20 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/cdrom.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "shuttle_usbat.h"
 
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
 #define short_pack(LSB,MSB) ( ((u16)(LSB)) | ( ((u16)(MSB))<<8 ) )
 #define LSB_of(s) ((s)&0xFF)
 #define MSB_of(s) ((s)>>8)
@@ -275,7 +279,7 @@
 			       int minutes)
 {
 	int result;
-	unsigned int pipe = (direction == SCSI_DATA_READ) ?
+	unsigned int pipe = (direction == DMA_FROM_DEVICE) ?
 			us->recv_bulk_pipe : us->send_bulk_pipe;
 
 	// Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here,
@@ -315,9 +319,9 @@
 		} else
 			cmdlen = 8;
 
-		command[cmdlen-8] = (direction==SCSI_DATA_WRITE ? 0x40 : 0xC0);
+		command[cmdlen-8] = (direction==DMA_TO_DEVICE ? 0x40 : 0xC0);
 		command[cmdlen-7] = access |
-				(direction==SCSI_DATA_WRITE ? 0x05 : 0x04);
+				(direction==DMA_TO_DEVICE ? 0x05 : 0x04);
 		command[cmdlen-6] = data_reg;
 		command[cmdlen-5] = status_reg;
 		command[cmdlen-4] = timeout;
@@ -355,7 +359,7 @@
 
 
 		//US_DEBUGP("Transfer %s %d bytes, sg buffers %d\n",
-		//	direction == SCSI_DATA_WRITE ? "out" : "in",
+		//	direction == DMA_TO_DEVICE ? "out" : "in",
 		//	len, use_sg);
 
 		result = usb_stor_bulk_transfer_sg(us,
@@ -388,7 +392,7 @@
 			 * the bulk output pipe only the first time.
 			 */
 
-			if (direction==SCSI_DATA_READ && i==0) {
+			if (direction==DMA_FROM_DEVICE && i==0) {
 				if (usb_stor_clear_halt(us,
 						us->send_bulk_pipe) < 0)
 					return USB_STOR_TRANSPORT_ERROR;
@@ -399,7 +403,7 @@
 			 */
 
  			result = usbat_read(us, USBAT_ATA, 
-				direction==SCSI_DATA_WRITE ? 0x17 : 0x0E, 
+				direction==DMA_TO_DEVICE ? 0x17 : 0x0E, 
 				status);
 
 			if (result!=USB_STOR_XFER_GOOD)
@@ -410,7 +414,7 @@
 				return USB_STOR_TRANSPORT_FAILED;
 
 			US_DEBUGP("Redoing %s\n",
-			  direction==SCSI_DATA_WRITE ? "write" : "read");
+			  direction==DMA_TO_DEVICE ? "write" : "read");
 
 		} else if (result != USB_STOR_XFER_GOOD)
 			return USB_STOR_TRANSPORT_ERROR;
@@ -420,7 +424,7 @@
 	}
 
 	US_DEBUGP("Bummer! %s bulk data 20 times failed.\n",
-		direction==SCSI_DATA_WRITE ? "Writing" : "Reading");
+		direction==DMA_TO_DEVICE ? "Writing" : "Reading");
 
 	return USB_STOR_TRANSPORT_FAILED;
 }
@@ -520,7 +524,7 @@
 static int usbat_handle_read10(struct us_data *us,
 			       unsigned char *registers,
 			       unsigned char *data,
-			       Scsi_Cmnd *srb)
+			       struct scsi_cmnd *srb)
 {
 	int result = USB_STOR_TRANSPORT_GOOD;
 	unsigned char *buffer;
@@ -537,7 +541,7 @@
 		result = usbat_rw_block_test(us, USBAT_ATA, 
 			registers, data, 19,
 			0x10, 0x17, 0xFD, 0x30,
-			SCSI_DATA_READ,
+			DMA_FROM_DEVICE,
 			srb->request_buffer, 
 			srb->request_bufflen, srb->use_sg, 1);
 
@@ -606,7 +610,7 @@
 		result = usbat_rw_block_test(us, USBAT_ATA, 
 			registers, data, 19,
 			0x10, 0x17, 0xFD, 0x30,
-			SCSI_DATA_READ,
+			DMA_FROM_DEVICE,
 			buffer,
 			len, 0, 1);
 
@@ -803,7 +807,7 @@
 /*
  * Transport for the HP 8200e
  */
-int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us)
+int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	int result;
 	unsigned char *status = us->iobuf;
@@ -847,12 +851,12 @@
 	if (srb->cmnd[0] == TEST_UNIT_READY)
 		transferred = 0;
 
-	if (srb->sc_data_direction == SCSI_DATA_WRITE) {
+	if (srb->sc_data_direction == DMA_TO_DEVICE) {
 
 		result = usbat_rw_block_test(us, USBAT_ATA, 
 			registers, data, 19,
 			0x10, 0x17, 0xFD, 0x30,
-			SCSI_DATA_WRITE,
+			DMA_TO_DEVICE,
 			srb->request_buffer, 
 			len, srb->use_sg, 10);
 
@@ -900,7 +904,7 @@
 	// If there is response data to be read in 
 	// then do it here.
 
-	if (len != 0 && (srb->sc_data_direction == SCSI_DATA_READ)) {
+	if (len != 0 && (srb->sc_data_direction == DMA_FROM_DEVICE)) {
 
 		// How many bytes to read in? Check cylL register
 
diff -Nru a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h
--- a/drivers/usb/storage/shuttle_usbat.h	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/shuttle_usbat.h	2004-08-04 17:58:03 -07:00
@@ -53,7 +53,7 @@
 #define USBAT_UIO_ADPRST	0x01 // Reset SCM chip
 
 /* HP 8200e stuff */
-extern int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us);
 extern int init_8200e(struct us_data *us);
 
 #endif
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/transport.c	2004-08-04 17:58:03 -07:00
@@ -46,15 +46,20 @@
  */
 
 #include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "scsiglue.h"
 #include "usb.h"
 #include "debug.h"
 
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
 
 /***********************************************************************
  * Data transfer routines
@@ -522,7 +527,7 @@
  * This is used by the protocol layers to actually send the message to
  * the device and receive the response.
  */
-void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	int need_auto_sense;
 	int result;
@@ -569,7 +574,7 @@
 	 * can signal most data-in errors by stalling the bulk-in pipe.
 	 */
 	if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) &&
-			srb->sc_data_direction != SCSI_DATA_READ) {
+			srb->sc_data_direction != DMA_FROM_DEVICE) {
 		US_DEBUGP("-- CB transport device requiring auto-sense\n");
 		need_auto_sense = 1;
 	}
@@ -629,7 +634,7 @@
 
 		/* set the transfer direction */
 		old_sc_data_direction = srb->sc_data_direction;
-		srb->sc_data_direction = SCSI_DATA_READ;
+		srb->sc_data_direction = DMA_FROM_DEVICE;
 
 		/* use the new buffer we have */
 		old_request_buffer = srb->request_buffer;
@@ -749,7 +754,7 @@
  * Control/Bulk/Interrupt transport
  */
 
-int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
+int usb_stor_CBI_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	unsigned int transfer_length = srb->request_bufflen;
 	unsigned int pipe = 0;
@@ -778,7 +783,7 @@
 	/* DATA STAGE */
 	/* transfer the data payload for this command, if one exists*/
 	if (transfer_length) {
-		pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
+		pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
 				us->recv_bulk_pipe : us->send_bulk_pipe;
 		result = usb_stor_bulk_transfer_sg(us, pipe,
 					srb->request_buffer, transfer_length,
@@ -849,7 +854,7 @@
 /*
  * Control/Bulk transport
  */
-int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
+int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	unsigned int transfer_length = srb->request_bufflen;
 	int result;
@@ -877,7 +882,7 @@
 	/* DATA STAGE */
 	/* transfer the data payload for this command, if one exists*/
 	if (transfer_length) {
-		unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
+		unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
 				us->recv_bulk_pipe : us->send_bulk_pipe;
 		result = usb_stor_bulk_transfer_sg(us, pipe,
 					srb->request_buffer, transfer_length,
@@ -939,7 +944,7 @@
 	return -1;
 }
 
-int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
+int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
 	struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
@@ -952,7 +957,7 @@
 	/* set up the command wrapper */
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 	bcb->DataTransferLength = cpu_to_le32(transfer_length);
-	bcb->Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
+	bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0;
 	bcb->Tag = srb->serial_number;
 	bcb->Lun = srb->device->lun;
 	if (us->flags & US_FL_SCM_MULT_TARG)
@@ -977,8 +982,14 @@
 
 	/* DATA STAGE */
 	/* send/receive data payload, if there is any */
+
+	/* Genesys Logic interface chips need a 100us delay between the
+	 * command phase and the data phase */
+	if (us->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS)
+		udelay(100);
+
 	if (transfer_length) {
-		unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
+		unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
 				us->recv_bulk_pipe : us->send_bulk_pipe;
 		result = usb_stor_bulk_transfer_sg(us, pipe,
 					srb->request_buffer, transfer_length,
diff -Nru a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
--- a/drivers/usb/storage/transport.h	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/transport.h	2004-08-04 17:58:03 -07:00
@@ -44,7 +44,8 @@
 #include <linux/config.h>
 #include <linux/blkdev.h>
 #include "usb.h"
-#include "scsi.h"
+
+struct scsi_cmnd;
 
 /* Protocols */
 
@@ -150,16 +151,16 @@
 
 #define US_CBI_ADSC		0
 
-extern int usb_stor_CBI_transport(Scsi_Cmnd*, struct us_data*);
+extern int usb_stor_CBI_transport(struct scsi_cmnd *, struct us_data*);
 
-extern int usb_stor_CB_transport(Scsi_Cmnd*, struct us_data*);
+extern int usb_stor_CB_transport(struct scsi_cmnd *, struct us_data*);
 extern int usb_stor_CB_reset(struct us_data*);
 
-extern int usb_stor_Bulk_transport(Scsi_Cmnd*, struct us_data*);
+extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data*);
 extern int usb_stor_Bulk_max_lun(struct us_data*);
 extern int usb_stor_Bulk_reset(struct us_data*);
 
-extern void usb_stor_invoke_transport(Scsi_Cmnd*, struct us_data*);
+extern void usb_stor_invoke_transport(struct scsi_cmnd *, struct us_data*);
 extern void usb_stor_stop_transport(struct us_data*);
 
 extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
--- a/drivers/usb/storage/unusual_devs.h	2004-08-04 17:58:04 -07:00
+++ b/drivers/usb/storage/unusual_devs.h	2004-08-04 17:58:04 -07:00
@@ -45,11 +45,6 @@
  *
  */
 
-UNUSUAL_DEV(  0x03ee, 0x0000, 0x0000, 0x0245, 
-		"Mitsumi",
-		"CD-R/RW Drive",
-		US_SC_8020, US_PR_CBI, NULL, 0), 
-
 UNUSUAL_DEV(  0x03ee, 0x6901, 0x0000, 0x0100,
 		"Mitsumi",
 		"USB FDD",
@@ -373,6 +368,15 @@
 		US_SC_DEVICE,  US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN),
 
+/* Reported by Johann Cardon <johann.cardon@free.fr>
+ * This entry is needed only because the device reports
+ * bInterfaceClass = 0xff (vendor-specific)
+ */
+UNUSUAL_DEV(  0x057b, 0x0022, 0x0000, 0x9999, 
+		"Y-E Data",
+		"Silicon Media R/W",
+		US_SC_DEVICE, US_PR_DEVICE, NULL, 0),
+
 /* Fabrizio Fellini <fello@libero.it> */
 UNUSUAL_DEV(  0x0595, 0x4343, 0x0000, 0x2210,
 		"Fujifilm",
@@ -384,11 +388,15 @@
 		"USB Hard Disk",
 		US_SC_RBC, US_PR_CB, NULL, 0 ), 
 
-/* Submitted by Jol Bourquard <numlock@freesurf.ch> */
+/* Submitted by Joel Bourquard <numlock@freesurf.ch>
+ * Some versions of this device need the SubClass and Protocol overrides
+ * while others don't.
+ */
 UNUSUAL_DEV(  0x05ab, 0x0060, 0x1104, 0x1110,
 		"In-System",
 		"PyroGate External CD-ROM Enclosure (FCD-523)",
-		US_SC_SCSI, US_PR_BULK, NULL, 0 ),
+		US_SC_SCSI, US_PR_BULK, NULL,
+		US_FL_NEED_OVERRIDE ),
 
 #ifdef CONFIG_USB_STORAGE_ISD200
 UNUSUAL_DEV(  0x05ab, 0x0031, 0x0100, 0x0110,
@@ -685,7 +693,7 @@
 		"Trumpion",
 		"t33520 USB Flash Card Controller",
 		US_SC_DEVICE, US_PR_BULK, NULL,
-		US_FL_MODE_XLATE),
+		US_FL_NEED_OVERRIDE | US_FL_MODE_XLATE),
 
 /* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */
 UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999,
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/usb.c	2004-08-04 17:58:03 -07:00
@@ -50,6 +50,11 @@
 #include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
 #include "usb.h"
 #include "scsiglue.h"
 #include "transport.h"
@@ -322,7 +327,7 @@
 		/* reject the command if the direction indicator 
 		 * is UNKNOWN
 		 */
-		if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) {
+		if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL) {
 			US_DEBUGP("UNKNOWN data direction\n");
 			us->srb->result = DID_ERROR << 16;
 		}
@@ -423,6 +428,13 @@
 	us->pusb_dev = interface_to_usbdev(intf);
 	us->pusb_intf = intf;
 	us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+	US_DEBUGP("Vendor: 0x%04x, Product: 0x%04x, Revision: 0x%04x\n",
+			us->pusb_dev->descriptor.idVendor,
+			us->pusb_dev->descriptor.idProduct,
+			us->pusb_dev->descriptor.bcdDevice);
+	US_DEBUGP("Interface Subclass: 0x%02x, Protocol: 0x%02x\n",
+			intf->cur_altsetting->desc.bInterfaceSubClass,
+			intf->cur_altsetting->desc.bInterfaceProtocol);
 
 	/* Store our private data in the interface */
 	usb_set_intfdata(intf, us);
@@ -453,11 +465,6 @@
 	struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index];
 	struct usb_device_id *id = &storage_usb_ids[id_index];
 
-	if (unusual_dev->vendorName)
-		US_DEBUGP("Vendor: %s\n", unusual_dev->vendorName);
-	if (unusual_dev->productName)
-		US_DEBUGP("Product: %s\n", unusual_dev->productName);
-
 	/* Store the entries */
 	us->unusual_dev = unusual_dev;
 	us->subclass = (unusual_dev->useProtocol == US_SC_DEVICE) ?
@@ -528,6 +535,8 @@
 	}
 	if (strlen(us->serial) == 0)
 		strcpy(us->serial, "None");
+
+	US_DEBUGP("Vendor: %s,  Product: %s\n", us->vendor, us->product);
 }
 
 /* Get the transport settings */
@@ -715,8 +724,6 @@
 			ep_int = ep;
 		}
 	}
-	US_DEBUGP("Endpoints: In: 0x%p Out: 0x%p Int: 0x%p (Period %d)\n",
-		  ep_in, ep_out, ep_int, ep_int ? ep_int->bInterval : 0);
 
 	if (!ep_in || !ep_out || (us->protocol == US_PR_CBI && !ep_int)) {
 		US_DEBUGP("Endpoint sanity check failed! Rejecting dev.\n");
@@ -880,9 +887,6 @@
 	int result;
 
 	US_DEBUGP("USB Mass Storage device detected\n");
-	US_DEBUGP("altsetting is %d, id_index is %d\n",
-			intf->cur_altsetting->desc.bAlternateSetting,
-			id_index);
 
 	/* Allocate the us_data structure and initialize the mutexes */
 	us = (struct us_data *) kmalloc(sizeof(*us), GFP_KERNEL);
diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
--- a/drivers/usb/storage/usb.h	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/storage/usb.h	2004-08-04 17:58:03 -07:00
@@ -48,10 +48,9 @@
 #include <linux/blkdev.h>
 #include <linux/smp_lock.h>
 #include <linux/completion.h>
-#include "scsi.h"
-#include <scsi/scsi_host.h>
 
 struct us_data;
+struct scsi_cmnd;
 
 /*
  * Unusual device list definitions 
@@ -102,9 +101,9 @@
 
 #define US_IOBUF_SIZE		64	/* Size of the DMA-mapped I/O buffer */
 
-typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*);
+typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*);
 typedef int (*trans_reset)(struct us_data*);
-typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*);
+typedef void (*proto_cmnd)(struct scsi_cmnd*, struct us_data*);
 typedef void (*extra_data_destructor)(void *);	 /* extra data destructor   */
 
 /* we allocate one of these for every device that we remember */
@@ -144,7 +143,7 @@
 
 	/* SCSI interfaces */
 	struct Scsi_Host	*host;		 /* our dummy host data */
-	Scsi_Cmnd		*srb;		 /* current srb		*/
+	struct scsi_cmnd	*srb;		 /* current srb		*/
 
 	/* thread information */
 	int			pid;		 /* control thread	 */
@@ -179,5 +178,9 @@
  * single queue element srb for write access */
 #define scsi_unlock(host)	spin_unlock_irq(host->host_lock)
 #define scsi_lock(host)		spin_lock_irq(host->host_lock)
+
+
+/* Vendor ID list for devices that require special handling */
+#define USB_VENDOR_ID_GENESYS		0x05e3	/* Genesys Logic */
 
 #endif
diff -Nru a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
--- a/drivers/usb/usb-skeleton.c	2004-08-04 17:58:03 -07:00
+++ b/drivers/usb/usb-skeleton.c	2004-08-04 17:58:03 -07:00
@@ -1,42 +1,15 @@
 /*
- * USB Skeleton driver - 1.1
+ * USB Skeleton driver - 2.0
  *
- * Copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001-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 the Free Software Foundation, version 2.
  *
- *
- * This driver is to be used as a skeleton driver to be able to create a
- * USB driver quickly.  The design of it is based on the usb-serial and
- * dc2xx drivers.
- *
- * Thanks to Oliver Neukum, David Brownell, and Alan Stern for their help
- * in debugging this driver.
- *
- *
- * History:
- *
- * 2003-05-06 - 1.1 - changes due to usb core changes with usb_register_dev()
- * 2003-02-25 - 1.0 - fix races involving urb->status, unlink_urb(), and
- *			disconnect.  Fix transfer amount in read().  Use
- *			macros instead of magic numbers in probe().  Change
- *			size variables to size_t.  Show how to eliminate
- *			DMA bounce buffer.
- * 2002_12_12 - 0.9 - compile fixes and got rid of fixed minor array.
- * 2002_09_26 - 0.8 - changes due to USB core conversion to struct device
- *			driver.
- * 2002_02_12 - 0.7 - zero out dev in probe function for devices that do
- *			not have both a bulk in and bulk out endpoint.
- *			Thanks to Holger Waechtler for the fix.
- * 2001_11_05 - 0.6 - fix minor locking problem in skel_disconnect.
- *			Thanks to Pete Zaitcev for the fix.
- * 2001_09_04 - 0.5 - fix devfs bug in skel_disconnect. Thanks to wim delvaux
- * 2001_08_21 - 0.4 - more small bug fixes.
- * 2001_05_29 - 0.3 - more bug fixes based on review from linux-usb-devel
- * 2001_05_24 - 0.2 - bug fixes based on review from linux-usb-devel people
- * 2001_05_01 - 0.1 - first version
+ * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c 
+ * but has been rewritten to be easy to read and use, as no locks are now
+ * needed anymore.
  *
  */
 
@@ -46,31 +19,10 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
-#include <linux/completion.h>
+#include <linux/kref.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
 
-#ifdef CONFIG_USB_DEBUG
-	static int debug = 1;
-#else
-	static int debug;
-#endif
-
-/* Use our own dbg macro */
-#undef dbg
-#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0)
-
-
-/* Version Information */
-#define DRIVER_VERSION "v1.0"
-#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com"
-#define DRIVER_DESC "USB Skeleton Driver"
-
-/* Module parameters */
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
 
 /* Define these values to match your devices */
 #define USB_SKEL_VENDOR_ID	0xfff0
@@ -79,11 +31,8 @@
 /* table of devices that work with this driver */
 static struct usb_device_id skel_table [] = {
 	{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
-	/* "Gadget Zero" firmware runs under Linux */
-	{ USB_DEVICE(0x0525, 0xa4a0) },
 	{ }					/* Terminating entry */
 };
-
 MODULE_DEVICE_TABLE (usb, skel_table);
 
 
@@ -92,413 +41,195 @@
 
 /* Structure to hold all of our device specific stuff */
 struct usb_skel {
-	struct usb_device *	udev;			/* save off the usb device pointer */
+	struct usb_device *	udev;			/* the usb device for this device */
 	struct usb_interface *	interface;		/* the interface for this device */
-	unsigned char		minor;			/* the starting minor number for this device */
-	unsigned char		num_ports;		/* the number of ports this device has */
-	char			num_interrupt_in;	/* number of interrupt in endpoints we have */
-	char			num_bulk_in;		/* number of bulk in endpoints we have */
-	char			num_bulk_out;		/* number of bulk out endpoints we have */
-
 	unsigned char *		bulk_in_buffer;		/* the buffer to receive data */
 	size_t			bulk_in_size;		/* the size of the receive buffer */
 	__u8			bulk_in_endpointAddr;	/* the address of the bulk in endpoint */
-
-	unsigned char *		bulk_out_buffer;	/* the buffer to send data */
-	size_t			bulk_out_size;		/* the size of the send buffer */
-	struct urb *		write_urb;		/* the urb used to send data */
 	__u8			bulk_out_endpointAddr;	/* the address of the bulk out endpoint */
-	atomic_t		write_busy;		/* true iff write urb is busy */
-	struct completion	write_finished;		/* wait for the write to finish */
-
-	int			open;			/* if the port is open or not */
-	int			present;		/* if the device is not disconnected */
-	struct semaphore	sem;			/* locks this structure */
+	struct kref		kref;
 };
+#define to_skel_dev(d) container_of(d, struct usb_skel, kref)
 
+static struct usb_driver skel_driver;
 
-/* prevent races between open() and disconnect() */
-static DECLARE_MUTEX (disconnect_sem);
-
-/* local function prototypes */
-static ssize_t skel_read	(struct file *file, char *buffer, size_t count, loff_t *ppos);
-static ssize_t skel_write	(struct file *file, const char *buffer, size_t count, loff_t *ppos);
-static int skel_ioctl		(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
-static int skel_open		(struct inode *inode, struct file *file);
-static int skel_release		(struct inode *inode, struct file *file);
-
-static int skel_probe		(struct usb_interface *interface, const struct usb_device_id *id);
-static void skel_disconnect	(struct usb_interface *interface);
-
-static void skel_write_bulk_callback	(struct urb *urb, struct pt_regs *regs);
-
-/*
- * File operations needed when we register this driver.
- * This assumes that this driver NEEDS file operations,
- * of course, which means that the driver is expected
- * to have a node in the /dev directory. If the USB
- * device were for a network interface then the driver
- * would use "struct net_driver" instead, and a serial
- * device would use "struct tty_driver".
- */
-static struct file_operations skel_fops = {
-	/*
-	 * The owner field is part of the module-locking
-	 * mechanism. The idea is that the kernel knows
-	 * which module to increment the use-counter of
-	 * BEFORE it calls the device's open() function.
-	 * This also means that the kernel can decrement
-	 * the use-counter again before calling release()
-	 * or should the open() function fail.
-	 */
-	.owner =	THIS_MODULE,
-
-	.read =		skel_read,
-	.write =	skel_write,
-	.ioctl =	skel_ioctl,
-	.open =		skel_open,
-	.release =	skel_release,
-};
-
-/* 
- * usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with devfs and the driver core
- */
-static struct usb_class_driver skel_class = {
-	.name =		"usb/skel%d",
-	.fops =		&skel_fops,
-	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
-	.minor_base =	USB_SKEL_MINOR_BASE,
-};
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver skel_driver = {
-	.owner =	THIS_MODULE,
-	.name =		"skeleton",
-	.probe =	skel_probe,
-	.disconnect =	skel_disconnect,
-	.id_table =	skel_table,
-};
-
-
-/**
- *	usb_skel_debug_data
- */
-static inline void usb_skel_debug_data (const char *function, int size, const unsigned char *data)
-{
-	int i;
-
-	if (!debug)
-		return;
-
-	printk (KERN_DEBUG __FILE__": %s - length = %d, data = ",
-		function, size);
-	for (i = 0; i < size; ++i) {
-		printk ("%.2x ", data[i]);
-	}
-	printk ("\n");
-}
-
+static void skel_delete(struct kref *kref)
+{	
+	struct usb_skel *dev = to_skel_dev(kref);
 
-/**
- *	skel_delete
- */
-static inline void skel_delete (struct usb_skel *dev)
-{
+	usb_put_dev(dev->udev);
 	kfree (dev->bulk_in_buffer);
-	usb_buffer_free (dev->udev, dev->bulk_out_size,
-				dev->bulk_out_buffer,
-				dev->write_urb->transfer_dma);
-	usb_free_urb (dev->write_urb);
 	kfree (dev);
 }
 
-
-/**
- *	skel_open
- */
-static int skel_open (struct inode *inode, struct file *file)
+static int skel_open(struct inode *inode, struct file *file)
 {
-	struct usb_skel *dev = NULL;
+	struct usb_skel *dev;
 	struct usb_interface *interface;
 	int subminor;
 	int retval = 0;
 
-	dbg("%s", __FUNCTION__);
-
 	subminor = iminor(inode);
 
-	/* prevent disconnects */
-	down (&disconnect_sem);
-
-	interface = usb_find_interface (&skel_driver, subminor);
+	interface = usb_find_interface(&skel_driver, subminor);
 	if (!interface) {
 		err ("%s - error, can't find device for minor %d",
 		     __FUNCTION__, subminor);
 		retval = -ENODEV;
-		goto exit_no_device;
+		goto exit;
 	}
 
 	dev = usb_get_intfdata(interface);
 	if (!dev) {
 		retval = -ENODEV;
-		goto exit_no_device;
+		goto exit;
 	}
 
-	/* lock this device */
-	down (&dev->sem);
-
-	/* increment our usage count for the driver */
-	++dev->open;
+	/* increment our usage count for the device */
+	kref_get(&dev->kref);
 
 	/* save our object in the file's private structure */
 	file->private_data = dev;
 
-	/* unlock this device */
-	up (&dev->sem);
-
-exit_no_device:
-	up (&disconnect_sem);
+exit:
 	return retval;
 }
 
-
-/**
- *	skel_release
- */
-static int skel_release (struct inode *inode, struct file *file)
+static int skel_release(struct inode *inode, struct file *file)
 {
 	struct usb_skel *dev;
-	int retval = 0;
 
 	dev = (struct usb_skel *)file->private_data;
-	if (dev == NULL) {
-		dbg ("%s - object is NULL", __FUNCTION__);
+	if (dev == NULL)
 		return -ENODEV;
-	}
-
-	dbg("%s - minor %d", __FUNCTION__, dev->minor);
-
-	/* lock our device */
-	down (&dev->sem);
-
-	if (dev->open <= 0) {
-		dbg ("%s - device not opened", __FUNCTION__);
-		retval = -ENODEV;
-		goto exit_not_opened;
-	}
-
-	/* wait for any bulk writes that might be going on to finish up */
-	if (atomic_read (&dev->write_busy))
-		wait_for_completion (&dev->write_finished);
-
-	--dev->open;
 
-	if (!dev->present && !dev->open) {
-		/* the device was unplugged before the file was released */
-		up (&dev->sem);
-		skel_delete (dev);
-		return 0;
-	}
-
-exit_not_opened:
-	up (&dev->sem);
-
-	return retval;
+	/* decrement the count on our device */
+	kref_put(&dev->kref, skel_delete);
+	return 0;
 }
 
-
-/**
- *	skel_read
- */
-static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t *ppos)
+static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct usb_skel *dev;
 	int retval = 0;
 
 	dev = (struct usb_skel *)file->private_data;
-
-	dbg("%s - minor %d, count = %d", __FUNCTION__, dev->minor, count);
-
-	/* lock this object */
-	down (&dev->sem);
-
-	/* verify that the device wasn't unplugged */
-	if (!dev->present) {
-		up (&dev->sem);
-		return -ENODEV;
-	}
-
+	
 	/* do a blocking bulk read to get data from the device */
-	retval = usb_bulk_msg (dev->udev,
-			       usb_rcvbulkpipe (dev->udev,
-						dev->bulk_in_endpointAddr),
-			       dev->bulk_in_buffer,
-			       min (dev->bulk_in_size, count),
-			       &count, HZ*10);
+	retval = usb_bulk_msg(dev->udev,
+			      usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
+			      dev->bulk_in_buffer,
+			      min(dev->bulk_in_size, count),
+			      &count, HZ*10);
 
 	/* if the read was successful, copy the data to userspace */
 	if (!retval) {
-		if (copy_to_user (buffer, dev->bulk_in_buffer, count))
+		if (copy_to_user(buffer, dev->bulk_in_buffer, count))
 			retval = -EFAULT;
 		else
 			retval = count;
 	}
 
-	/* unlock the device */
-	up (&dev->sem);
 	return retval;
 }
 
+static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+	struct usb_skel *dev;
 
-/**
- *	skel_write
- *
- *	A device driver has to decide how to report I/O errors back to the
- *	user.  The safest course is to wait for the transfer to finish before
- *	returning so that any errors will be reported reliably.  skel_read()
- *	works like this.  But waiting for I/O is slow, so many drivers only
- *	check for errors during I/O initiation and do not report problems
- *	that occur during the actual transfer.  That's what we will do here.
- *
- *	A driver concerned with maximum I/O throughput would use double-
- *	buffering:  Two urbs would be devoted to write transfers, so that
- *	one urb could always be active while the other was waiting for the
- *	user to send more data.
- */
-static ssize_t skel_write (struct file *file, const char *buffer, size_t count, loff_t *ppos)
+	dev = (struct usb_skel *)urb->context;
+
+	/* sync/async unlink faults aren't errors */
+	if (urb->status && 
+	    !(urb->status == -ENOENT || 
+	      urb->status == -ECONNRESET ||
+	      urb->status == -ESHUTDOWN)) {
+		dbg("%s - nonzero write bulk status received: %d",
+		    __FUNCTION__, urb->status);
+	}
+
+	/* free up our allocated buffer */
+	usb_buffer_free(urb->dev, urb->transfer_buffer_length, 
+			urb->transfer_buffer, urb->transfer_dma);
+}
+
+static ssize_t skel_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos)
 {
 	struct usb_skel *dev;
-	ssize_t bytes_written = 0;
 	int retval = 0;
+	struct urb *urb = NULL;
+	char *buf = NULL;
 
 	dev = (struct usb_skel *)file->private_data;
 
-	dbg("%s - minor %d, count = %d", __FUNCTION__, dev->minor, count);
-
-	/* lock this object */
-	down (&dev->sem);
-
-	/* verify that the device wasn't unplugged */
-	if (!dev->present) {
-		retval = -ENODEV;
+	/* verify that we actually have some data to write */
+	if (count == 0)
 		goto exit;
+
+	/* create a urb, and a buffer for it, and copy the data to the urb */
+	urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!urb) {
+		retval = -ENOMEM;
+		goto error;
 	}
 
-	/* verify that we actually have some data to write */
-	if (count == 0) {
-		dbg("%s - write request of 0 bytes", __FUNCTION__);
-		goto exit;
+	buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
+	if (!buf) {
+		retval = -ENOMEM;
+		goto error;
 	}
 
-	/* wait for a previous write to finish up; we don't use a timeout
-	 * and so a nonresponsive device can delay us indefinitely.
-	 */
-	if (atomic_read (&dev->write_busy))
-		wait_for_completion (&dev->write_finished);
-
-	/* we can only write as much as our buffer will hold */
-	bytes_written = min (dev->bulk_out_size, count);
-
-	/* copy the data from userspace into our transfer buffer;
-	 * this is the only copy required.
-	 */
-	if (copy_from_user(dev->write_urb->transfer_buffer, buffer,
-			   bytes_written)) {
+	if (copy_from_user(buf, user_buffer, count)) {
 		retval = -EFAULT;
-		goto exit;
+		goto error;
 	}
 
-	usb_skel_debug_data (__FUNCTION__, bytes_written,
-			     dev->write_urb->transfer_buffer);
-
-	/* this urb was already set up, except for this write size */
-	dev->write_urb->transfer_buffer_length = bytes_written;
+	/* initialize the urb properly */
+	usb_fill_bulk_urb(urb, dev->udev,
+			  usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
+			  buf, count, skel_write_bulk_callback, dev);
+	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
 	/* send the data out the bulk port */
-	/* a character device write uses GFP_KERNEL,
-	 unless a spinlock is held */
-	init_completion (&dev->write_finished);
-	atomic_set (&dev->write_busy, 1);
-	retval = usb_submit_urb(dev->write_urb, GFP_KERNEL);
+	retval = usb_submit_urb(urb, GFP_KERNEL);
 	if (retval) {
-		atomic_set (&dev->write_busy, 0);
-		err("%s - failed submitting write urb, error %d",
-		    __FUNCTION__, retval);
-	} else {
-		retval = bytes_written;
+		err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);
+		goto error;
 	}
 
+	/* release our reference to this urb, the USB core will eventually free it entirely */
+	usb_free_urb(urb);
+
 exit:
-	/* unlock the device */
-	up (&dev->sem);
+	return count;
 
+error:
+	usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
+	usb_free_urb(urb);
 	return retval;
 }
 
+static struct file_operations skel_fops = {
+	.owner =	THIS_MODULE,
+	.read =		skel_read,
+	.write =	skel_write,
+	.open =		skel_open,
+	.release =	skel_release,
+};
 
-/**
- *	skel_ioctl
- */
-static int skel_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct usb_skel *dev;
-
-	dev = (struct usb_skel *)file->private_data;
-
-	/* lock this object */
-	down (&dev->sem);
-
-	/* verify that the device wasn't unplugged */
-	if (!dev->present) {
-		up (&dev->sem);
-		return -ENODEV;
-	}
-
-	dbg("%s - minor %d, cmd 0x%.4x, arg %ld", __FUNCTION__,
-	    dev->minor, cmd, arg);
-
-	/* fill in your device specific stuff here */
-
-	/* unlock the device */
-	up (&dev->sem);
-
-	/* return that we did not understand this ioctl call */
-	return -ENOTTY;
-}
-
-
-/**
- *	skel_write_bulk_callback
+/* 
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with devfs and the driver core
  */
-static void skel_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
-{
-	struct usb_skel *dev = (struct usb_skel *)urb->context;
-
-	dbg("%s - minor %d", __FUNCTION__, dev->minor);
-
-	/* sync/async unlink faults aren't errors */
-	if (urb->status && !(urb->status == -ENOENT ||
-				urb->status == -ECONNRESET)) {
-		dbg("%s - nonzero write bulk status received: %d",
-		    __FUNCTION__, urb->status);
-	}
-
-	/* notify anyone waiting that the write has finished */
-	atomic_set (&dev->write_busy, 0);
-	complete (&dev->write_finished);
-}
-
+static struct usb_class_driver skel_class = {
+	.name =		"usb/skel%d",
+	.fops =		&skel_fops,
+	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
+	.minor_base =	USB_SKEL_MINOR_BASE,
+};
 
-/**
- *	skel_probe
- *
- *	Called by the usb core when a new device is connected that it thinks
- *	this driver might be interested in.
- */
 static int skel_probe(struct usb_interface *interface, const struct usb_device_id *id)
 {
-	struct usb_device *udev = interface_to_usbdev(interface);
 	struct usb_skel *dev = NULL;
 	struct usb_host_interface *iface_desc;
 	struct usb_endpoint_descriptor *endpoint;
@@ -506,28 +237,21 @@
 	int i;
 	int retval = -ENOMEM;
 
-	/* See if the device offered us matches what we can accept */
-	if ((udev->descriptor.idVendor != USB_SKEL_VENDOR_ID) ||
-	    (udev->descriptor.idProduct != USB_SKEL_PRODUCT_ID)) {
-		return -ENODEV;
-	}
-
 	/* allocate memory for our device state and initialize it */
-	dev = kmalloc (sizeof(struct usb_skel), GFP_KERNEL);
+	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL) {
-		err ("Out of memory");
-		return -ENOMEM;
+		err("Out of memory");
+		goto error;
 	}
-	memset (dev, 0x00, sizeof (*dev));
+	memset(dev, 0x00, sizeof(*dev));
+	kref_init(&dev->kref);
 
-	init_MUTEX (&dev->sem);
-	dev->udev = udev;
+	dev->udev = usb_get_dev(interface_to_usbdev(interface));
 	dev->interface = interface;
 
 	/* set up the endpoint information */
-	/* check out the endpoints */
 	/* use only the first bulk-in and bulk-out endpoints */
-	iface_desc = &interface->altsetting[0];
+	iface_desc = interface->cur_altsetting;
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
 		endpoint = &iface_desc->endpoint[i].desc;
 
@@ -539,9 +263,9 @@
 			buffer_size = endpoint->wMaxPacketSize;
 			dev->bulk_in_size = buffer_size;
 			dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
-			dev->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
+			dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
 			if (!dev->bulk_in_buffer) {
-				err("Couldn't allocate bulk_in_buffer");
+				err("Could not allocate bulk_in_buffer");
 				goto error;
 			}
 		}
@@ -551,153 +275,85 @@
 		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
 					== USB_ENDPOINT_XFER_BULK)) {
 			/* we found a bulk out endpoint */
-			/* a probe() may sleep and has no restrictions on memory allocations */
-			dev->write_urb = usb_alloc_urb(0, GFP_KERNEL);
-			if (!dev->write_urb) {
-				err("No free urbs available");
-				goto error;
-			}
 			dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
-
-			/* on some platforms using this kind of buffer alloc
-			 * call eliminates a dma "bounce buffer".
-			 *
-			 * NOTE: you'd normally want i/o buffers that hold
-			 * more than one packet, so that i/o delays between
-			 * packets don't hurt throughput.
-			 */
-			buffer_size = endpoint->wMaxPacketSize;
-			dev->bulk_out_size = buffer_size;
-			dev->write_urb->transfer_flags = (URB_NO_TRANSFER_DMA_MAP |
-					URB_ASYNC_UNLINK);
-			dev->bulk_out_buffer = usb_buffer_alloc (udev,
-					buffer_size, GFP_KERNEL,
-					&dev->write_urb->transfer_dma);
-			if (!dev->bulk_out_buffer) {
-				err("Couldn't allocate bulk_out_buffer");
-				goto error;
-			}
-			usb_fill_bulk_urb(dev->write_urb, udev,
-				      usb_sndbulkpipe(udev,
-						      endpoint->bEndpointAddress),
-				      dev->bulk_out_buffer, buffer_size,
-				      skel_write_bulk_callback, dev);
 		}
 	}
 	if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
-		err("Couldn't find both bulk-in and bulk-out endpoints");
+		err("Could not find both bulk-in and bulk-out endpoints");
 		goto error;
 	}
 
-	/* allow device read, write and ioctl */
-	dev->present = 1;
+	/* save our data pointer in this interface device */
+	usb_set_intfdata(interface, dev);
 
 	/* we can register the device now, as it is ready */
-	usb_set_intfdata (interface, dev);
-	retval = usb_register_dev (interface, &skel_class);
+	retval = usb_register_dev(interface, &skel_class);
 	if (retval) {
 		/* something prevented us from registering this driver */
-		err ("Not able to get a minor for this device.");
-		usb_set_intfdata (interface, NULL);
+		err("Not able to get a minor for this device.");
+		usb_set_intfdata(interface, NULL);
 		goto error;
 	}
 
-	dev->minor = interface->minor;
-
 	/* let the user know what node this device is now attached to */
-	info ("USB Skeleton device now attached to USBSkel-%d", dev->minor);
+	info("USB Skeleton device now attached to USBSkel-%d", interface->minor);
 	return 0;
 
 error:
-	skel_delete (dev);
+	if (dev)
+		kref_put(&dev->kref, skel_delete);
 	return retval;
 }
 
-
-/**
- *	skel_disconnect
- *
- *	Called by the usb core when the device is removed from the system.
- *
- *	This routine guarantees that the driver will not submit any more urbs
- *	by clearing dev->udev.  It is also supposed to terminate any currently
- *	active urbs.  Unfortunately, usb_bulk_msg(), used in skel_read(), does
- *	not provide any way to do this.  But at least we can cancel an active
- *	write.
- */
 static void skel_disconnect(struct usb_interface *interface)
 {
 	struct usb_skel *dev;
-	int minor;
+	int minor = interface->minor;
 
-	/* prevent races with open() */
-	down (&disconnect_sem);
+	/* prevent skel_open() from racing skel_disconnect() */
+	lock_kernel();
 
-	dev = usb_get_intfdata (interface);
-	usb_set_intfdata (interface, NULL);
-
-	down (&dev->sem);
-
-	minor = dev->minor;
+	dev = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
 
 	/* give back our minor */
-	usb_deregister_dev (interface, &skel_class);
+	usb_deregister_dev(interface, &skel_class);
 
-	/* terminate an ongoing write */
-	if (atomic_read (&dev->write_busy)) {
-		usb_unlink_urb (dev->write_urb);
-		wait_for_completion (&dev->write_finished);
-	}
-
-	/* prevent device read, write and ioctl */
-	dev->present = 0;
-
-	up (&dev->sem);
+	unlock_kernel();
 
-	/* if the device is opened, skel_release will clean this up */
-	if (!dev->open)
-		skel_delete (dev);
-
-	up (&disconnect_sem);
+	/* decrement our usage count */
+	kref_put(&dev->kref, skel_delete);
 
 	info("USB Skeleton #%d now disconnected", minor);
 }
 
+static struct usb_driver skel_driver = {
+	.owner =	THIS_MODULE,
+	.name =		"skeleton",
+	.probe =	skel_probe,
+	.disconnect =	skel_disconnect,
+	.id_table =	skel_table,
+};
 
-
-/**
- *	usb_skel_init
- */
 static int __init usb_skel_init(void)
 {
 	int result;
 
 	/* register this driver with the USB subsystem */
 	result = usb_register(&skel_driver);
-	if (result) {
-		err("usb_register failed. Error number %d",
-		    result);
-		return result;
-	}
+	if (result)
+		err("usb_register failed. Error number %d", result);
 
-	info(DRIVER_DESC " " DRIVER_VERSION);
-	return 0;
+	return result;
 }
 
-
-/**
- *	usb_skel_exit
- */
 static void __exit usb_skel_exit(void)
 {
 	/* deregister this driver with the USB subsystem */
 	usb_deregister(&skel_driver);
 }
 
-
 module_init (usb_skel_init);
 module_exit (usb_skel_exit);
 
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
diff -Nru a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c	2004-08-04 17:58:03 -07:00
+++ b/fs/namei.c	2004-08-04 17:58:03 -07:00
@@ -1659,7 +1659,7 @@
  * if it cannot handle the case of removing a directory
  * that is still in use by something else..
  */
-static void d_unhash(struct dentry *dentry)
+void dentry_unhash(struct dentry *dentry)
 {
 	dget(dentry);
 	spin_lock(&dcache_lock);
@@ -1689,7 +1689,7 @@
 	DQUOT_INIT(dir);
 
 	down(&dentry->d_inode->i_sem);
-	d_unhash(dentry);
+	dentry_unhash(dentry);
 	if (d_mountpoint(dentry))
 		error = -EBUSY;
 	else {
@@ -2032,7 +2032,7 @@
 	target = new_dentry->d_inode;
 	if (target) {
 		down(&target->i_sem);
-		d_unhash(new_dentry);
+		dentry_unhash(new_dentry);
 	}
 	if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
 		error = -EBUSY;
@@ -2410,4 +2410,5 @@
 EXPORT_SYMBOL(vfs_rmdir);
 EXPORT_SYMBOL(vfs_symlink);
 EXPORT_SYMBOL(vfs_unlink);
+EXPORT_SYMBOL(dentry_unhash);
 EXPORT_SYMBOL(generic_readlink);
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	2004-08-04 17:58:03 -07:00
+++ b/include/linux/fs.h	2004-08-04 17:58:03 -07:00
@@ -809,6 +809,11 @@
 extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
 
 /*
+ * VFS dentry helper functions.
+ */
+extern void dentry_unhash(struct dentry *dentry);
+
+/*
  * File types
  *
  * NOTE! These match bits 12..15 of stat.st_mode