bk://linux-scsi.bkbits.net/scsi-misc-2.6
matthew@wil.cx[jejb]|ChangeSet|20050307075602|53127 matthew

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2005/03/07 15:17:31-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-scsi
# 
# drivers/scsi/Kconfig
#   2005/03/07 15:17:26-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/07 14:23:37-08:00 akpm@bix.(none) 
#   Merge bk://linux-scsi.bkbits.net/scsi-misc-2.6
#   into bix.(none):/usr/src/bk-scsi
# 
# drivers/scsi/scsi_transport_spi.c
#   2005/03/07 14:23:30-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/scsi_devinfo.c
#   2005/03/07 14:23:30-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/07 09:56:02+02:00 matthew@wil.cx 
#   [PATCH] Use spi_display_xfer_agreement() in 53c700
#   
#   Convert 53c700 to use spi_display_xfer_agreement()
#   
#   Signed-off-by: Matthew Wilcox <matthew@wil.cx>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/53c700.c
#   2005/02/24 16:48:28+02:00 matthew@wil.cx +5 -11
#   Use spi_display_xfer_agreement() in 53c700
# 
# ChangeSet
#   2005/03/07 09:51:22+02:00 matthew@wil.cx 
#   [PATCH] Display SPI transfer agreement in common code
#   
#   [ This is an updated version of
#     http://marc.theaimsgroup.com/?l=linux-scsi&m=110918302718178&w=2
#     Relative to that patch, it prints the period in a nicer way; exactly
#     the same way as the strings in the original version of this file. ]
#   
#   Introduce a generic SPI function to print the negotiated transfer
#   agreement.  It's based on the implementation in sym53c8xx_2/sym_misc.c.
#   I have changes in my tree to make 53c700, ncr53c8xx and sym2 use it.
#   Other drivers need to be converted to use the SPI transport layer first.
#   
#   In order to calculate the speed I needed to be able to convert from
#   period factor to period in picoseconds.  That required changing
#   (show|store)_spi_transport_period to work in picoseconds rather than
#   a string.
#   
#   Signed-off-by: Matthew Wilcox <matthew@wil.cx>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# include/scsi/scsi_transport_spi.h
#   2005/02/23 20:31:37+02:00 matthew@wil.cx +1 -0
#   Display SPI transfer agreement in common code
# 
# drivers/scsi/scsi_transport_spi.c
#   2005/03/06 19:11:18+02:00 matthew@wil.cx +124 -59
#   Display SPI transfer agreement in common code
# 
# ChangeSet
#   2005/03/07 09:46:29+02:00 bunk@stusta.de 
#   [PATCH] SCSI NCR_D700.c: make some code static
#   
#   This patch makes some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/NCR_D700.c
#   2005/02/27 02:04:25+02:00 bunk@stusta.de +2 -2
#   SCSI NCR_D700.c: make some code static
# 
# ChangeSet
#   2005/03/07 09:41:11+02:00 kenn@linux.ie 
#   [PATCH] NCR5380 delayed work fix and locking fix
#   
#   Changes to the NCR5380 driver between 2.6.9 and 2.6.10 replaced the
#   driver's home-grown delayed work implementation with a call to
#   schedule_delayed_work().  However, the delay argument was not passed
#   correctly, so the work was usually scheduled for _way_ too far in
#   the future.  This patch fixes this.
#   
#   NCR5380_print_status() is called from NCR5380_abort() and from
#   NCR5380_bus_reset().  In at least the abort() case, the host lock
#   has already been acquired by scsi_error.c:scsi_try_to_abort_command().
#   NCR5380_print_status() calls NCR5380_proc_info() which also acquires
#   and releases the host lock.  This patch removes the call to
#   NCR5380_proc_info() from NCR5380_print_status.
#   
#   Cosmetic: Remove duplicated lines of code from NCR5380_abort().
#   
#   Signed-off-by: Kenn Humborg <kenn@linux.ie>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/NCR5380.c
#   2005/02/25 01:17:28+02:00 kenn@linux.ie +1 -14
#   NCR5380 delayed work fix and locking fix
# 
# ChangeSet
#   2005/03/07 09:32:15+02:00 davej@redhat.com 
#   [PATCH] blacklist microtek scanmaker III
#   
#   To try and escape the madness of adding a zillion USB card readers
#   to the SCSI whitelist, I flipped the scan all lun's by default switch
#   in the fedora kernel recently to see just what breaks, in the hope
#   of moving from a whitelist solution to a blacklist.
#   
#   Here's the first (hopefully of not too many) devices that broke.
#   (See https://bugzilla.redhat.com/beta/show_bug.cgi?id=149402 for more info)
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/scsi_devinfo.c
#   2005/02/23 21:29:06+02:00 davej@redhat.com +1 -0
#   blacklist microtek scanmaker III
# 
# ChangeSet
#   2005/03/06 19:49:47-08:00 akpm@bix.(none) 
#   Merge bk://linux-scsi.bkbits.net/scsi-misc-2.6
#   into bix.(none):/usr/src/bk-scsi
# 
# drivers/scsi/dc395x.c
#   2005/03/06 19:49:42-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/03 10:41:40+02:00 lenehan@twibble.org 
#   [PATCH] dc395x: Fix support for highmem
#   
#   From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
#   
#   Removes the page_to_virt and maps sg lists dynamically.
#   This makes the driver work with highmem pages.
#   
#   Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
#   Signed-off-by: Jamie Lenehan <lenehan@twibble.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/dc395x.c
#   2005/01/23 00:55:45+02:00 lenehan@twibble.org +35 -13
#   dc395x: Fix support for highmem
# 
# ChangeSet
#   2005/03/03 10:34:52+02:00 Kai.Makisara@kolumbus.fi 
#   [PATCH] SCSI tape: write filemark before rewind etc. when writing
#   
#   The patch at the end of this message modifies the st write semantics in
#   the following way: write a filemark before rewind, offline, or seek if the
#   previous operation was write.
#   
#   This semantics is specified on the man pages of some Unices and some
#   software (e.g., cpio) seems to assume this. The change makes sure that the
#   last file on the tape is properly terminated with a filemark and reading the
#   file does not fail at the end.
#   
#   Signed-off-by: Kai Makisara <kai.makisara@kolumbus.fi>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/st.c
#   2005/02/20 22:22:51+02:00 Kai.Makisara@kolumbus.fi +13 -0
#   SCSI tape: write filemark before rewind etc. when writing
# 
# Documentation/scsi/st.txt
#   2005/02/20 22:28:27+02:00 Kai.Makisara@kolumbus.fi +4 -1
#   SCSI tape: write filemark before rewind etc. when writing
# 
# ChangeSet
#   2005/03/03 10:22:41+02:00 jejb@mulgrave.(none) 
#   SCSI: revamp target scanning routines
#   
#   The basic change is to allow target scans to be done
#   by generic device (which need only have a scsi host
#   as a parent).  Also changes most target functions to
#   take a struct scsi_target instead of the H/C/T numbers.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# include/scsi/scsi_host.h
#   2005/03/03 10:22:17+02:00 jejb@mulgrave.(none) +13 -4
#   SCSI: revamp target scanning routines
# 
# include/scsi/scsi_device.h
#   2005/03/03 10:22:17+02:00 jejb@mulgrave.(none) +11 -0
#   SCSI: revamp target scanning routines
# 
# drivers/scsi/scsi_sysfs.c
#   2005/03/03 10:22:17+02:00 jejb@mulgrave.(none) +39 -104
#   SCSI: revamp target scanning routines
# 
# drivers/scsi/scsi_scan.c
#   2005/03/03 10:22:17+02:00 jejb@mulgrave.(none) +205 -61
#   SCSI: revamp target scanning routines
# 
# drivers/scsi/scsi_lib.c
#   2005/03/03 10:22:17+02:00 jejb@mulgrave.(none) +6 -3
#   SCSI: revamp target scanning routines
# 
# drivers/scsi/scsi.c
#   2005/03/03 10:22:17+02:00 jejb@mulgrave.(none) +54 -0
#   SCSI: revamp target scanning routines
# 
# drivers/scsi/hosts.c
#   2005/03/03 10:22:17+02:00 jejb@mulgrave.(none) +1 -0
#   SCSI: revamp target scanning routines
# 
# ChangeSet
#   2005/03/01 18:42:59-08:00 akpm@bix.(none) 
#   Merge bk://linux-scsi.bkbits.net/scsi-misc-2.6
#   into bix.(none):/usr/src/bk-scsi
# 
# drivers/scsi/scsi_transport_fc.c
#   2005/03/01 18:42:55-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/scsi_devinfo.c
#   2005/03/01 18:42:55-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/megaraid/megaraid_mm.c
#   2005/03/01 18:42:55-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/Kconfig
#   2005/03/01 18:42:55-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/02/22 10:21:31+01:00 stern@rowland.harvard.edu 
#   [PATCH] Add a NOREPORTLUN blacklist flag
#   
#   This patch adds a NOREPORTLUN blacklist flag for a disk made by "WDC"
#   (Winchester?).  The drive's firmware crashes when it receives REPORT_LUNS,
#   even though it claims to be SCSI rev 04.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/scsi_devinfo.c
#   2005/02/16 17:30:56+01:00 stern@rowland.harvard.edu +1 -0
#   Add a NOREPORTLUN blacklist flag
# 
# ChangeSet
#   2005/02/22 10:18:48+01:00 stern@rowland.harvard.edu 
#   [PATCH] Retry supposedly "unrecoverable" hardware errors
#   
#   This is an updated and unmangled version of the patch sent in by Martin
#   Peschke.  Apparently some drives report Hardware Error sense for
#   problems which do improve after retrying, so the patch retries these
#   supposedly "unrecoverable" errors for such devices.
#   
#   In addition to the IBM ESS drive it adds a blacklist entry for the drive
#   inside the MPIO HS200 Gigabox.
#   
#   Signed-off-by: Martin Peschke <mpeschke@de.ibm.com>
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# include/scsi/scsi_devinfo.h
#   2005/02/11 19:21:51+01:00 stern@rowland.harvard.edu +1 -0
#   Retry supposedly "unrecoverable" hardware errors
# 
# drivers/scsi/scsi_error.c
#   2005/02/11 19:23:45+01:00 stern@rowland.harvard.edu +10 -1
#   Retry supposedly "unrecoverable" hardware errors
# 
# drivers/scsi/scsi_devinfo.c
#   2005/02/11 19:25:41+01:00 stern@rowland.harvard.edu +2 -0
#   Retry supposedly "unrecoverable" hardware errors
# 
# ChangeSet
#   2005/02/22 10:13:21+01:00 Kai.Makisara@kolumbus.fi 
#   [PATCH] SCSI tape descriptor based sense data support
#   
#   The patch at the end of this message converts the SCSI tape driver to support
#   also descriptor based sense data. Test for deferred sense data have been added
#   in a couple of places and the EOM tests have been unified. Some tests have been
#   simplified but the patch is not meant to change the current behavior. The
#   patch is against 2.6.11-rc4 and has been tested to some extent.
#   
#   The patch also includes the msleep_interruptible change from from kernel
#   janitors.
#   
#   Thanks to Doug Gilbert for doing a first version of this sense data
#   conversion.
#   
#   Signed-off-by: Kai Makisara <kai.makisara@kolumbus.fi>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/st.h
#   2005/02/13 09:40:21+01:00 Kai.Makisara@kolumbus.fi +18 -1
#   SCSI tape descriptor based sense data support
# 
# drivers/scsi/st.c
#   2005/02/13 21:42:48+01:00 Kai.Makisara@kolumbus.fi +178 -141
#   SCSI tape descriptor based sense data support
# 
# ChangeSet
#   2005/02/22 10:06:06+01:00 hch@lst.de 
#   [PATCH] mark qlogicisp broken
#   
#   It's lacking EH support and the hardware is supported by the qla1280
#   driver now.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/Kconfig
#   2005/02/10 14:59:56+01:00 hch@lst.de +1 -1
#   mark qlogicisp broken
# 
# ChangeSet
#   2005/02/22 10:03:39+01:00 hch@lst.de 
#   [PATCH] mark eata_pio broken
#   
#   it oopses when trying to use it with my SmartRaid IV card, it's a mess
#   and the only hardware supported by it but not the eata driver are two
#   10-year old ISA boards.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/Kconfig
#   2005/02/10 14:59:56+01:00 hch@lst.de +1 -1
#   mark eata_pio broken
# 
# ChangeSet
#   2005/02/22 10:01:04+01:00 hch@lst.de 
#   [PATCH] qla1280: update changelog
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/qla1280.c
#   2005/02/10 13:42:44+01:00 hch@lst.de +3 -0
#   qla1280: update changelog
# 
# ChangeSet
#   2005/02/22 09:57:38+01:00 hch@lst.de 
#   [PATCH] qla1280: use pci_map_single
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/qla1280.c
#   2005/02/10 13:42:44+01:00 hch@lst.de +12 -20
#   qla1280: use pci_map_single
# 
# ChangeSet
#   2005/02/22 09:54:33+01:00 hch@lst.de 
#   [PATCH] qla1280: remove qla1280_proc_info
#   
#   reading the /proc/scsi/qla1280/* files can easily corrupt kernel memory.
#   
#   As the feature is deprecated, and the qla1280 implementation doesn't
#   return very usefull implementation but is so buggy that any serious
#   user would have noticed we just remove it.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/qla1280.c
#   2005/02/10 13:42:44+01:00 hch@lst.de +0 -111
#   qla1280: remove qla1280_proc_info
# 
# ChangeSet
#   2005/02/22 09:51:11+01:00 matthew@wil.cx 
#   scsi: remove device_request_lock
#   
#   The static device_request_lock doesn't protect anything; remove it.
#   
#   Signed-off-by: Matthew Wilcox <matthew@wil.cx>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/scsi.c
#   2005/02/06 20:57:07+01:00 matthew@wil.cx +2 -7
#   scsi: remove device_request_lock
# 
# ChangeSet
#   2005/02/22 09:47:49+01:00 ak@suse.de 
#   [PATCH] Fix selection of command serial numbers and pids
#   
#   This patch fixes one of Christroph's fixme comments in the SCSI midlayer.
#   
#   The selection of the serial number and pid for commands was done
#   by a global variable and not SMP safe. The race was not very
#   serious because it was only used for error handling, but it's
#   still better to fix it.
#   
#   I audited all the drivers and none seemed to use them
#   for anything interesting, so I just made it a per host counter
#   protected by host lock.
#   
#   (in fact they could be probably removed because they only see
#   to be used as a flag in exception handling and for debugging.
#   The patch would be unfortunately quite big because a lot
#   of driver printks use them)
#   
#   This should be slight faster on SMP too because the cache line of
#   the counter won't bounce around the machine.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# include/scsi/scsi_host.h
#   2005/02/05 12:02:17+01:00 ak@suse.de +6 -1
#   Fix selection of command serial numbers and pids
# 
# include/scsi/scsi_cmnd.h
#   2005/02/05 09:28:31+01:00 ak@suse.de +2 -1
#   Fix selection of command serial numbers and pids
# 
# drivers/scsi/scsi.c
#   2005/02/05 12:02:50+01:00 ak@suse.de +21 -13
#   Fix selection of command serial numbers and pids
# 
# ChangeSet
#   2005/02/04 09:12:34-06:00 bunk@stusta.de 
#   [PATCH] SCSI sim710.c: make some code static
#   
#   This patch makes some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/sim710.c
#   2004/11/13 18:28:48-06:00 bunk@stusta.de +3 -3
#   SCSI sim710.c: make some code static
# 
# ChangeSet
#   2005/02/03 22:08:04-06:00 jejb@mulgrave.(none) 
#   SCSI: fix io statistics compile warnings
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/scsi_sysfs.c
#   2005/02/03 22:05:26-06:00 jejb@mulgrave.(none) +2 -2
#   SCSI: fix io statistics compile warnings
# 
# ChangeSet
#   2005/02/03 21:37:56-06:00 jejb@mulgrave.(none) 
#   SCSI: Add device io statistics
#   
#   From: 	James.Smart@Emulex.Com
#   
#   Adds io statistics (requests, completions, error count) as generic
#   attributes for scsi devices.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# include/scsi/scsi_device.h
#   2005/02/03 21:35:03-06:00 jejb@mulgrave.(none) +4 -0
#   SCSI: Add device io statistics
# 
# drivers/scsi/scsi_sysfs.c
#   2005/02/03 21:35:03-06:00 jejb@mulgrave.(none) +26 -0
#   SCSI: Add device io statistics
# 
# drivers/scsi/scsi.c
#   2005/02/03 21:35:03-06:00 jejb@mulgrave.(none) +8 -0
#   SCSI: Add device io statistics
# 
# ChangeSet
#   2005/02/03 21:29:59-06:00 hch@lst.de 
#   [PATCH] drop some attibutes from the FC transport class
#   
#   I think the hardware_version, firmware_version, rom_version and
#   driver_version don't belong to the FC transport class, there's
#   nothing specific to FC or even SCSI specific in them.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# include/scsi/scsi_transport_fc.h
#   2005/01/19 11:17:24-06:00 hch@lst.de +0 -4
#   drop some attibutes from the FC transport class
# 
# drivers/scsi/scsi_transport_fc.c
#   2005/01/19 11:17:03-06:00 hch@lst.de +0 -16
#   drop some attibutes from the FC transport class
# 
# ChangeSet
#   2005/02/03 20:51:38-06:00 jejb@mulgrave.(none) 
#   SCSI: fix compat_ioctl compile warnings
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/st.c
#   2005/02/03 20:48:50-06:00 jejb@mulgrave.(none) +2 -2
#   SCSI: fix compat_ioctl compile warnings
# 
# drivers/scsi/osst.c
#   2005/02/03 20:48:50-06:00 jejb@mulgrave.(none) +1 -1
#   SCSI: fix compat_ioctl compile warnings
# 
# drivers/scsi/aacraid/linit.c
#   2005/02/03 20:48:49-06:00 jejb@mulgrave.(none) +2 -2
#   SCSI: fix compat_ioctl compile warnings
# 
# ChangeSet
#   2005/02/03 20:01:17-06:00 jejb@mulgrave.(none) 
#   mptfusion: delete watchdogs timers from mptctl and mptscsih
#   
#   From: 	Moore, Eric Dean <Eric.Moore@lsil.com>
#   
#   1) mptscsih.c: I have changed task management 
#   requests so they complete in same thread before returning
#   to os.  I removed the TMtimer code.  
#    
#   (2) mptctl.c: I have deleted both TMtimer and timer code. Replaced
#   with wait_event_interruptible_timeout.  So commands are now
#   completed in same thread.  
#    
#   (3) mptctl_do_fw_download - nasty polling of global parameters
#   that are set in contents of interrupt handler(mptctl_reply), now using
#   wait_event_interruptible_timeout. 
#    
#   (4) I have cleaned up mptctl_reply.
#   
#   Signed-off-by: Eric Moore <Eric.Moore@lsil.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/message/fusion/mptscsih.c
#   2005/02/03 19:58:54-06:00 jejb@mulgrave.(none) +62 -123
#   mptfusion: delete watchdogs timers from mptctl and mptscsih
# 
# drivers/message/fusion/mptctl.c
#   2005/02/03 19:58:54-06:00 jejb@mulgrave.(none) +199 -300
#   mptfusion: delete watchdogs timers from mptctl and mptscsih
# 
# drivers/message/fusion/mptbase.h
#   2005/02/03 19:58:54-06:00 jejb@mulgrave.(none) +2 -8
#   mptfusion: delete watchdogs timers from mptctl and mptscsih
# 
# ChangeSet
#   2005/02/03 19:49:11-06:00 ak@muc.de 
#   [PATCH] Add compat_ioctl to mptctl
#   
#   Convert mptctl to compat_ioctl. I also changed it to unlocked_ioctl
#   while I was on it.
#   
#   Signed-off-by: Andi Kleen <ak@muc.de>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/message/fusion/mptctl.c
#   2005/01/18 05:11:30-06:00 ak@muc.de +56 -81
#   Add compat_ioctl to mptctl
# 
# ChangeSet
#   2005/02/03 19:38:47-06:00 ak@muc.de 
#   [PATCH] Convert megaraid2 to compat_ioctl
#   
#   Convert megaraid2 driver to new compat_ioctl entry points.
#   
#   Signed-off-by: Andi Kleen <ak@muc.de>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/megaraid/megaraid_mm.c
#   2005/01/17 23:28:34-06:00 ak@muc.de +14 -12
#   Convert megaraid2 to compat_ioctl
# 
# ChangeSet
#   2005/02/03 19:27:13-06:00 ak@muc.de 
#   [PATCH] Add compat_ioctl to SG
#   
#   Add compat_ioctl to SG driver
#   
#   Signed-off-by: Andi Kleen <ak@muc.de>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/sg.c
#   2005/01/17 22:24:28-06:00 ak@muc.de +26 -0
#   Add compat_ioctl to SG
# 
# ChangeSet
#   2005/02/03 19:17:33-06:00 ak@muc.de 
#   [PATCH] Convert aacraid to compat_ioctl
#   
#   Convert aacraid driver to the compat_ioctl entry points.
#   
#   I don't have hardware, so this is only compile tested, but I just
#   did some transformations on the existing code.
#   
#   Signed-off-by: Andi Kleen <ak@muc.de>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/aacraid/linit.c
#   2005/01/18 00:58:31-06:00 ak@muc.de +60 -50
#   Convert aacraid to compat_ioctl
# 
# ChangeSet
#   2005/02/03 18:56:42-06:00 ak@muc.de 
#   [PATCH] Add compat_ioctl to osst
#   
#   Add compat_ioctl to osst
#   
#   Signed-off-by: Andi Kleen <ak@muc.de>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/osst.c
#   2005/01/17 22:14:59-06:00 ak@muc.de +19 -0
#   Add compat_ioctl to osst
# 
# ChangeSet
#   2005/02/03 18:52:01-06:00 ak@muc.de 
#   [PATCH] Add comment for compat_ioctl to SR
#   
#   Add comment that SR doesn't support compat_ioctl (because it doesn't
#   pass down any driver ioctls right now)
#   
#   Signed-off-by: Andi Kleen <ak@muc.de>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/sr.c
#   2005/01/17 21:54:59-06:00 ak@muc.de +4 -0
#   Add comment for compat_ioctl to SR
# 
# ChangeSet
#   2005/02/03 18:47:23-06:00 ak@muc.de 
#   [PATCH] Add compat_ioctl to st
#   
#   Call new compat_ioctl host vector from tape driver
#   
#   Signed-off-by: Andi Kleen <ak@muc.de>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/st.c
#   2005/01/17 21:50:09-06:00 ak@muc.de +19 -0
#   Add compat_ioctl to st
# 
# ChangeSet
#   2005/02/03 18:33:31-06:00 ak@muc.de 
#   [PATCH] Add compat_ioctl to SD
#   
#   Add compat_ioctl entry point to SD
#   
#   Signed-off-by: Andi Kleen <ak@muc.de>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/sd.c
#   2005/01/17 21:55:17-06:00 ak@muc.de +39 -0
#   Add compat_ioctl to SD
# 
diff -Nru a/Documentation/scsi/st.txt b/Documentation/scsi/st.txt
--- a/Documentation/scsi/st.txt	2005-03-07 15:19:08 -08:00
+++ b/Documentation/scsi/st.txt	2005-03-07 15:19:08 -08:00
@@ -2,7 +2,7 @@
 The driver is currently maintained by Kai Mäkisara (email
 Kai.Makisara@kolumbus.fi)
 
-Last modified: Wed Feb 25 14:09:08 2004 by makisara
+Last modified: Sun Feb 20 22:28:27 2005 by kai.makisara
 
 
 BASICS
@@ -84,6 +84,9 @@
 writing and the last operation has been a write. Two filemarks can be
 optionally written. In both cases end of data is signified by
 returning zero bytes for two consecutive reads.
+
+If the rewind, offline, or seek is done and previous tape operation was write,
+a filemark is written before moving tape.
 
 The compile options are defined in the file linux/drivers/scsi/st_options.h.
 
diff -Nru a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
--- a/drivers/message/fusion/mptbase.h	2005-03-07 15:19:08 -08:00
+++ b/drivers/message/fusion/mptbase.h	2005-03-07 15:19:08 -08:00
@@ -83,8 +83,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2004 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.01.18"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.01.18"
+#define MPT_LINUX_VERSION_COMMON	"3.01.19"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.01.19"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -420,7 +420,6 @@
 
 typedef struct _MPT_IOCTL {
 	struct _MPT_ADAPTER	*ioc;
-	struct timer_list	 timer;		/* timer function for this adapter */
 	u8			 ReplyFrame[MPT_DEFAULT_FRAME_SIZE];	/* reply frame data */
 	u8			 sense[MPT_SENSE_BUFFER_ALLOC];
 	int			 wait_done;	/* wake-up value for this ioc */
@@ -428,8 +427,6 @@
 	u8			 status;	/* current command status */
 	u8			 reset;		/* 1 if bus reset allowed */
 	u8			 target;	/* target for reset */
-	void 			*tmPtr;
-	struct timer_list	 TMtimer;	/* timer function for this adapter */
 	struct semaphore	 sem_ioc;
 } MPT_IOCTL;
 
@@ -882,11 +879,9 @@
 	int			  port;
 	u32			  pad0;
 	struct scsi_cmnd	**ScsiLookup;
-	u32			  qtag_tick;
 	VirtDevice		**Targets;
 	MPT_LOCAL_REPLY		 *pLocal;		/* used for internal commands */
 	struct timer_list	  timer;
-	struct timer_list	  TMtimer;		/* Timer for TM commands ONLY */
 		/* Pool of memory for holding SCpnts before doing
 		 * OS callbacks. freeQ is the free pool.
 		 */
@@ -896,7 +891,6 @@
 	u8			  pad1;
 	u8                        tmState;
 	u8			  rsvd[2];
-	MPT_FRAME_HDR		 *tmPtr;		/* Ptr to TM request*/
 	MPT_FRAME_HDR		 *cmdPtr;		/* Ptr to nonOS request */
 	struct scsi_cmnd	 *abortSCpnt;
 	MPT_LOCAL_REPLY		  localReply;		/* internal cmd reply struct */
diff -Nru a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
--- a/drivers/message/fusion/mptctl.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/message/fusion/mptctl.c	2005-03-07 15:19:08 -08:00
@@ -81,6 +81,7 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/pci.h>
+#include <linux/delay.h>	/* for mdelay */
 #include <linux/miscdevice.h>
 #include <linux/smp_lock.h>
 #include <linux/compat.h>
@@ -142,6 +143,9 @@
 static int  mptctl_probe(struct pci_dev *, const struct pci_device_id *);
 static void mptctl_remove(struct pci_dev *);
 
+#ifdef CONFIG_COMPAT
+static long compat_mpctl_ioctl(struct file *f, unsigned cmd, unsigned long arg);
+#endif
 /*
  * Private function calls.
  */
@@ -151,7 +155,7 @@
 		struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
 static void kfree_sgl( MptSge_t *sgl, dma_addr_t sgl_dma,
 		struct buflist *buflist, MPT_ADAPTER *ioc);
-static void mptctl_timer_expired (unsigned long data);
+static void mptctl_timeout_expired (MPT_IOCTL *ioctl);
 static int  mptctl_bus_reset(MPT_IOCTL *ioctl);
 static int mptctl_set_tm_flags(MPT_SCSI_HOST *hd);
 static void mptctl_free_tm_flags(MPT_ADAPTER *ioc);
@@ -184,9 +188,6 @@
 
 #define MPT_IOCTL_DEFAULT_TIMEOUT 10	/* Default timeout value (seconds) */
 
-static u32 fwReplyBuffer[16];
-static pMPIDefaultReply_t ReplyMsg = NULL;
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *	mptctl_syscall_down - Down the MPT adapter syscall semaphore.
@@ -204,11 +205,6 @@
 	int rc = 0;
 	dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock));
 
-	if (ioc->ioctl->tmPtr != NULL) {
-		dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down BUSY\n"));
-		return -EBUSY;
-	}
-
 	if (nonblock) {
 		if (down_trylock(&ioc->ioctl->sem_ioc))
 			rc = -EAGAIN;
@@ -235,131 +231,101 @@
 	u16 iocStatus;
 	u8 cmd;
 
-	dctlprintk((MYIOC_s_INFO_FMT ": mptctl_reply()!\n", ioc->name));
+	dctlprintk(("mptctl_reply()!\n"));
 	if (req)
 		 cmd = req->u.hdr.Function;
 	else
 		return 1;
 
 	if (ioc->ioctl) {
-		/* If timer is not running, then an error occurred.
-		 * A timeout will call the reset routine to reload the messaging
-		 * queues.
-		 * Main callback will free message and reply frames.
-		 */
-		if (reply && (cmd == MPI_FUNCTION_SCSI_TASK_MGMT) &&
-		    (ioc->ioctl->status & MPT_IOCTL_STATUS_TMTIMER_ACTIVE)) {
-			/* This is internally generated TM
-			 */
-			del_timer (&ioc->ioctl->TMtimer);
-			ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TMTIMER_ACTIVE;
 
-			mptctl_free_tm_flags(ioc);
+		if (reply==NULL) {
 
-			/* If TM failed, reset the timer on the existing command,
-			 * will trigger an adapter reset.
-			 */
-			iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK;
-			if (iocStatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED) {
-				if (ioc->ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE) {
-					ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
-					del_timer (&ioc->ioctl->timer);
-					ioc->ioctl->timer.expires = jiffies + HZ;
-					add_timer(&ioc->ioctl->timer);
-				}
-			}
-			ioc->ioctl->tmPtr = NULL;
+			dctlprintk(("mptctl_reply() NULL Reply "
+				"Function=%x!\n", cmd));
 
-		} else if (ioc->ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE) {
-			/* Delete this timer
-			 */
-			del_timer (&ioc->ioctl->timer);
-			ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TIMER_ACTIVE;
+			ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
+			ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
 
-			/* Set the overall status byte.  Good if:
-			 * IOC status is good OR if no reply and a SCSI IO request
-			 */
-			if (reply) {
-				/* Copy the reply frame (which much exist
-				 * for non-SCSI I/O) to the IOC structure.
-				 */
-				dctlprintk((MYIOC_s_INFO_FMT ": Copying Reply Frame @%p to IOC!\n",
-						ioc->name, reply));
-				memcpy(ioc->ioctl->ReplyFrame, reply,
-					min(ioc->reply_sz, 4*reply->u.reply.MsgLength));
-				ioc->ioctl->status |= MPT_IOCTL_STATUS_RF_VALID;
+			/* We are done, issue wake up
+	 		*/
+			ioc->ioctl->wait_done = 1;
+			wake_up (&mptctl_wait);
+			return 1;
 
-				/* Set the command status to GOOD if IOC Status is GOOD
-				 * OR if SCSI I/O cmd and data underrun or recovered error.
-				 */
-				iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK;
-				if (iocStatus  == MPI_IOCSTATUS_SUCCESS)
-					ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
-
-				if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
-					(cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
-					ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
-
-					if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) ||
-						(iocStatus == MPI_IOCSTATUS_SCSI_RECOVERED_ERROR)) {
-						ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
-					}
-				}
+		}
 
-				/* Copy the sense data - if present
-				 */
-				if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) &&
-					(reply->u.sreply.SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)){
+		dctlprintk(("mptctl_reply() with req=%p "
+			"reply=%p Function=%x!\n", req, reply, cmd));
 
-					sz = req->u.scsireq.SenseBufferLength;
-					req_index = le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
-					sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
-					memcpy(ioc->ioctl->sense, sense_data, sz);
-					ioc->ioctl->status |= MPT_IOCTL_STATUS_SENSE_VALID;
-				}
+		/* Copy the reply frame (which much exist
+		 * for non-SCSI I/O) to the IOC structure.
+		 */
+		dctlprintk(("Copying Reply Frame @%p to ioc%d!\n",
+			reply, ioc->id));
+		memcpy(ioc->ioctl->ReplyFrame, reply,
+			min(ioc->reply_sz, 4*reply->u.reply.MsgLength));
+		ioc->ioctl->status |= MPT_IOCTL_STATUS_RF_VALID;
 
-				if (cmd == MPI_FUNCTION_SCSI_TASK_MGMT)
-					mptctl_free_tm_flags(ioc);
+		/* Set the command status to GOOD if IOC Status is GOOD
+		 * OR if SCSI I/O cmd and data underrun or recovered error.
+		 */
+		iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK;
+		if (iocStatus  == MPI_IOCSTATUS_SUCCESS)
+			ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
 
+		if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
+			(cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
+			ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
 
-			} else if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
-					(cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
-				ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
-				ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
+			if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) ||
+			(iocStatus == MPI_IOCSTATUS_SCSI_RECOVERED_ERROR)) {
+			ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
 			}
+		}
 
-			/* We are done, issue wake up
-			 */
-			ioc->ioctl->wait_done = 1;
-			wake_up (&mptctl_wait);
-		} else if (reply && cmd == MPI_FUNCTION_FW_DOWNLOAD) {
-			/* Two paths to FW DOWNLOAD! */
-			// NOTE: Expects/requires non-Turbo reply!
-			dctlprintk((MYIOC_s_INFO_FMT ":Caching MPI_FUNCTION_FW_DOWNLOAD reply!\n",
-				ioc->name));
-			memcpy(fwReplyBuffer, reply, min_t(int, sizeof(fwReplyBuffer), 4*reply->u.reply.MsgLength));
-			ReplyMsg = (pMPIDefaultReply_t) fwReplyBuffer;
+		/* Copy the sense data - if present
+		 */
+		if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) &&
+			(reply->u.sreply.SCSIState &
+			 MPI_SCSI_STATE_AUTOSENSE_VALID)){
+			sz = req->u.scsireq.SenseBufferLength;
+			req_index =
+			    le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
+			sense_data =
+			    ((u8 *)ioc->sense_buf_pool +
+			     (req_index * MPT_SENSE_BUFFER_ALLOC));
+			memcpy(ioc->ioctl->sense, sense_data, sz);
+			ioc->ioctl->status |= MPT_IOCTL_STATUS_SENSE_VALID;
 		}
+
+		if (cmd == MPI_FUNCTION_SCSI_TASK_MGMT)
+			mptctl_free_tm_flags(ioc);
+
+		/* We are done, issue wake up
+		 */
+		ioc->ioctl->wait_done = 1;
+		wake_up (&mptctl_wait);
 	}
 	return 1;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* mptctl_timer_expired
+/* mptctl_timeout_expired
  *
- * Call back for timer process. Used only for ioctl functionality.
+ * Expecting an interrupt, however timed out.
  *
  */
-static void mptctl_timer_expired (unsigned long data)
+static void mptctl_timeout_expired (MPT_IOCTL *ioctl)
 {
-	MPT_IOCTL *ioctl = (MPT_IOCTL *) data;
 	int rc = 1;
 
-	dctlprintk((KERN_NOTICE MYNAM ": Timer Expired! Host %d\n",
+	dctlprintk((KERN_NOTICE MYNAM ": Timeout Expired! Host %d\n",
 				ioctl->ioc->id));
 	if (ioctl == NULL)
 		return;
 
+	ioctl->wait_done = 0;
 	if (ioctl->reset & MPTCTL_RESET_OK)
 		rc = mptctl_bus_reset(ioctl);
 
@@ -367,6 +333,8 @@
 		/* Issue a reset for this device.
 		 * The IOC is not responding.
 		 */
+		dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
+			 ioctl->ioc->name));
 		mpt_HardResetHandler(ioctl->ioc, NO_SLEEP);
 	}
 	return;
@@ -391,7 +359,7 @@
 
 	if (ioctl->ioc->sh == NULL)
 		return -EPERM;
-	
+
 	hd = (MPT_SCSI_HOST *) ioctl->ioc->sh->hostdata;
 	if (hd == NULL)
 		return -EPERM;
@@ -431,26 +399,34 @@
 		pScsiTm->Reserved2[ii] = 0;
 
 	pScsiTm->TaskMsgContext = 0;
-	dtmprintk((MYIOC_s_INFO_FMT "mptctl_bus_reset: issued.\n", ioctl->ioc->name));
+	dtmprintk((MYIOC_s_INFO_FMT
+		"mptctl_bus_reset: issued.\n", ioctl->ioc->name));
 
-	ioctl->tmPtr = mf;
-	ioctl->TMtimer.expires = jiffies + HZ * 20;	/* 20 seconds */
-	ioctl->status |= MPT_IOCTL_STATUS_TMTIMER_ACTIVE;
-	add_timer(&ioctl->TMtimer);
-
-	retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc,
-			sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, NO_SLEEP);
-
-	if (retval != 0) {
-		dtmprintk((MYIOC_s_WARN_FMT "_send_handshake FAILED!"
-			" (hd %p, ioc %p, mf %p) \n", ioctl->ioc->name, hd, hd->ioc, mf));
+	DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);
 
-		mptctl_free_tm_flags(ioctl->ioc);
-		del_timer(&ioctl->TMtimer);
-		mpt_free_msg_frame(ioctl->ioc, mf);
-		ioctl->tmPtr = NULL;
+	ioctl->wait_done=0;
+	if ((retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc,
+	     sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) {
+		dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
+			" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
+			hd->ioc, mf));
+		goto mptctl_bus_reset_done;
 	}
 
+	/* Now wait for the command to complete */
+	ii = wait_event_interruptible_timeout(mptctl_wait,
+	     ioctl->wait_done == 1,
+	     HZ*5 /* 5 second timeout */);
+
+	if(ii <=0 && (ioctl->wait_done != 1 ))  {
+		ioctl->wait_done = 0;
+		retval = -1; /* return failure */
+	}
+
+mptctl_bus_reset_done:
+
+	mpt_free_msg_frame(hd->ioc, mf);
+	mptctl_free_tm_flags(ioctl->ioc);
 	return retval;
 }
 
@@ -491,7 +467,6 @@
 	return;
 }
 
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /* mptctl_ioc_reset
  *
@@ -504,43 +479,22 @@
 {
 	MPT_IOCTL *ioctl = ioc->ioctl;
 	dctlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to IOCTL driver!\n",
-			reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
-			reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
-
-	if (reset_phase == MPT_IOC_SETUP_RESET){
-		;
-	} else if (reset_phase == MPT_IOC_PRE_RESET){
-
-		/* Someone has called the reset handler to
-		 * do a hard reset. No more replies from the FW.
-		 * Delete the timer. TM flags cleaned up by SCSI driver.
-		 * Do not need to free msg frame, as re-initialized
-		 */
-		if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE)){
-			del_timer(&ioctl->timer);
-		}
-		if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TMTIMER_ACTIVE)){
-			ioctl->status &= ~MPT_IOCTL_STATUS_TMTIMER_ACTIVE;
-			del_timer(&ioctl->TMtimer);
-			mpt_free_msg_frame(ioc, ioctl->tmPtr);
-		}
-
-	} else {
-		ioctl->tmPtr = NULL;
+		reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
+		reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
 
-		/* Set the status and continue IOCTL
-		 * processing. All memory will be free'd
-		 * by originating thread after wake_up is
-		 * called.
-		 */
-		if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE)){
-			ioctl->status |= MPT_IOCTL_STATUS_DID_IOCRESET;
+	if(ioctl == NULL)
+		return 1;
 
-			/* Wake up the calling process
-			 */
-			ioctl->wait_done = 1;
-			wake_up(&mptctl_wait);
-		}
+	switch(reset_phase) {
+	case MPT_IOC_SETUP_RESET:
+		ioctl->status |= MPT_IOCTL_STATUS_DID_IOCRESET;
+		break;
+	case MPT_IOC_POST_RESET:
+		ioctl->status &= ~MPT_IOCTL_STATUS_DID_IOCRESET;
+		break;
+	case MPT_IOC_PRE_RESET:
+	default:
+		break;
 	}
 
 	return 1;
@@ -552,8 +506,8 @@
  *  cmd - specify the particular IOCTL command to be issued
  *  arg - data specific to the command. Must not be null.
  */
-static int
-mptctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long
+__mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	mpt_ioctl_header __user *uhdr = (void __user *) arg;
 	mpt_ioctl_header	 khdr;
@@ -637,6 +591,16 @@
 	return ret;
 }
 
+static long
+mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	long ret;
+	lock_kernel();
+	ret = __mptctl_ioctl(file, cmd, arg);
+	unlock_kernel();
+	return ret;
+}
+
 static int mptctl_do_reset(unsigned long arg)
 {
 	struct mpt_ioctl_diag_reset __user *urinfo = (void __user *) arg;
@@ -735,9 +699,9 @@
 	u32			 nib;
 	int			 fw_bytes_copied = 0;
 	int			 i;
-	int			 cntdn;
 	int			 sge_offset = 0;
 	u16			 iocstat;
+	pFWDownloadReply_t	 ReplyMsg = NULL;
 
 	dctlprintk((KERN_INFO "mptctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id));
 
@@ -868,31 +832,25 @@
 	/*
 	 * Finally, perform firmware download.
 	 */
-	ReplyMsg = NULL;
+	iocp->ioctl->wait_done = 0;
 	mpt_put_msg_frame(mptctl_id, iocp, mf);
 
-	/*
-	 *  Wait until the reply has been received
-	 */
-	for (cntdn=HZ*60, i=1; ReplyMsg == NULL; cntdn--, i++) {
-		if (!cntdn) {
-			ret = -ETIME;
-			goto fwdl_out;
-		}
-
-		if (!(i%HZ)) {
-			dctlprintk((KERN_INFO "DbG::_do_fwdl: "
-				   "In ReplyMsg loop - iteration %d\n",
-				   i));
-		}
-
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(1);
+	/* Now wait for the command to complete */
+	ret = wait_event_interruptible_timeout(mptctl_wait,
+	     iocp->ioctl->wait_done == 1,
+	     HZ*60);
+
+	if(ret <=0 && (iocp->ioctl->wait_done != 1 )) {
+	/* Now we need to reset the board */
+		mptctl_timeout_expired(iocp->ioctl);
+		ret = -ENODATA;
+		goto fwdl_out;
 	}
 
 	if (sgl)
 		kfree_sgl(sgl, sgl_dma, buflist, iocp);
 
+	ReplyMsg = (pFWDownloadReply_t)iocp->ioctl->ReplyFrame;
 	iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK;
 	if (iocstat == MPI_IOCSTATUS_SUCCESS) {
 		printk(KERN_INFO MYNAM ": F/W update successfully sent to %s!\n", iocp->name);
@@ -1180,14 +1138,14 @@
 		cim_rev = 0;	/* obsolete */
 	else
 		return -EFAULT;
-	
+
 	karg = kmalloc(data_size, GFP_KERNEL);
 	if (karg == NULL) {
 		printk(KERN_ERR "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n",
 				__FILE__, __LINE__);
 		return -ENOMEM;
 	}
-		
+
 	if (copy_from_user(karg, uarg, data_size)) {
 		printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
 			"Unable to read in mpt_ioctl_iocinfo struct @ %p\n",
@@ -1812,8 +1770,8 @@
 	int		iocnum, flagsLength;
 	int		sz, rc = 0;
 	int		msgContext;
-	int		tm_flags_set = 0;
 	u16		req_idx;
+	ulong 		timeout;
 
 	dctlprintk(("mptctl_do_mpt_command called.\n"));
 	bufIn.kptr = bufOut.kptr = NULL;
@@ -2029,7 +1987,6 @@
 				rc = -EPERM;
 				goto done_free_mem;
 			}
-			tm_flags_set = 1;
 		}
 		break;
 
@@ -2181,136 +2138,108 @@
 		mpt_add_sge(psge, flagsLength, (dma_addr_t) -1);
 	}
 
-	/* The request is complete. Set the timer parameters
-	 * and issue the request.
-	 */
-	if (karg.timeout > 0) {
-		ioc->ioctl->timer.expires = jiffies + HZ*karg.timeout;
-	} else {
-		ioc->ioctl->timer.expires = jiffies + HZ*MPT_IOCTL_DEFAULT_TIMEOUT;
-	}
-
 	ioc->ioctl->wait_done = 0;
-	ioc->ioctl->status |= MPT_IOCTL_STATUS_TIMER_ACTIVE;
-	add_timer(&ioc->ioctl->timer);
-
 	if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
+
 		DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);
-		rc = mpt_send_handshake_request(mptctl_id, ioc,
-				sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP);
-		if (rc == 0) {
-			wait_event(mptctl_wait, ioc->ioctl->wait_done);
-		} else {
+
+		if (mpt_send_handshake_request(mptctl_id, ioc,
+			sizeof(SCSITaskMgmt_t), (u32*)mf,
+			CAN_SLEEP) != 0) {
+			dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
+				" (ioc %p, mf %p) \n", ioc->name,
+				ioc, mf));
 			mptctl_free_tm_flags(ioc);
-			tm_flags_set= 0;
-			del_timer(&ioc->ioctl->timer);
-			ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TIMER_ACTIVE;
-			ioc->ioctl->status |= MPT_IOCTL_STATUS_TM_FAILED;
-			mpt_free_msg_frame(ioc, mf);
+			rc = -ENODATA;
+			goto done_free_mem;
 		}
-	} else {
+
+	} else
 		mpt_put_msg_frame(mptctl_id, ioc, mf);
-		wait_event(mptctl_wait, ioc->ioctl->wait_done);
+
+	/* Now wait for the command to complete */
+	timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
+	timeout = wait_event_interruptible_timeout(mptctl_wait,
+	     ioc->ioctl->wait_done == 1,
+	     HZ*timeout);
+
+	if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) {
+	/* Now we need to reset the board */
+
+		if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT)
+			mptctl_free_tm_flags(ioc);
+
+		mptctl_timeout_expired(ioc->ioctl);
+		rc = -ENODATA;
+		goto done_free_mem;
 	}
 
 	mf = NULL;
 
-	/* MF Cleanup:
-	 * If command failed and failure triggered a diagnostic reset
-	 * OR a diagnostic reset happens during command processing,
-	 * no data, messaging queues are reset (mf cannot be accessed),
-	 * and status is DID_IOCRESET
-	 *
-	 * If a user-requested bus reset fails to be handshaked, then
-	 * mf is returned to free queue and status is TM_FAILED.
-	 *
-	 * Otherise, the command completed and the mf was freed
-	 # by ISR (mf cannot be touched).
+	/* If a valid reply frame, copy to the user.
+	 * Offset 2: reply length in U32's
 	 */
-	if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) {
-		/* The timer callback deleted the
-		 * timer and reset the adapter queues.
-		 */
-		printk(KERN_WARNING "%s@%d::mptctl_do_mpt_command - "
-			"Timeout Occurred on IOCTL! Reset IOC.\n", __FILE__, __LINE__);
-		tm_flags_set= 0;
-		rc = -ETIME;
-	} else if (ioc->ioctl->status & MPT_IOCTL_STATUS_TM_FAILED) {
-		/* User TM request failed! mf has not been freed.
-		 */
-		rc = -ENODATA;
-	} else {
-		/* If a valid reply frame, copy to the user.
-		 * Offset 2: reply length in U32's
-		 */
-		if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
-			if (karg.maxReplyBytes < ioc->reply_sz) {
-				 sz = min(karg.maxReplyBytes, 4*ioc->ioctl->ReplyFrame[2]);
-			} else {
-				 sz = min(ioc->reply_sz, 4*ioc->ioctl->ReplyFrame[2]);
-			}
-
-			if (sz > 0) {
-				if (copy_to_user(karg.replyFrameBufPtr,
-					 &ioc->ioctl->ReplyFrame, sz)){
-
-					 printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
-					 "Unable to write out reply frame %p\n",
-					 __FILE__, __LINE__, karg.replyFrameBufPtr);
-					 rc =  -ENODATA;
-					 goto done_free_mem;
-				}
-			}
+	if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
+		if (karg.maxReplyBytes < ioc->reply_sz) {
+			 sz = min(karg.maxReplyBytes, 4*ioc->ioctl->ReplyFrame[2]);
+		} else {
+			 sz = min(ioc->reply_sz, 4*ioc->ioctl->ReplyFrame[2]);
 		}
 
-		/* If valid sense data, copy to user.
-		 */
-		if (ioc->ioctl->status & MPT_IOCTL_STATUS_SENSE_VALID) {
-			sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE);
-			if (sz > 0) {
-				if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) {
-					printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
-					"Unable to write sense data to user %p\n",
-					__FILE__, __LINE__,
-					karg.senseDataPtr);
-					rc =  -ENODATA;
-					goto done_free_mem;
-				}
+		if (sz > 0) {
+			if (copy_to_user(karg.replyFrameBufPtr,
+				 &ioc->ioctl->ReplyFrame, sz)){
+				 printk(KERN_ERR
+				     "%s@%d::mptctl_do_mpt_command - "
+				 "Unable to write out reply frame %p\n",
+				 __FILE__, __LINE__, karg.replyFrameBufPtr);
+				 rc =  -ENODATA;
+				 goto done_free_mem;
 			}
 		}
+	}
 
-		/* If the overall status is _GOOD and data in, copy data
-		 * to user.
-		 */
-		if ((ioc->ioctl->status & MPT_IOCTL_STATUS_COMMAND_GOOD) &&
-					(karg.dataInSize > 0) && (bufIn.kptr)) {
-
-			if (copy_to_user(karg.dataInBufPtr,
-					 bufIn.kptr, karg.dataInSize)) {
+	/* If valid sense data, copy to user.
+	 */
+	if (ioc->ioctl->status & MPT_IOCTL_STATUS_SENSE_VALID) {
+		sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE);
+		if (sz > 0) {
+			if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) {
 				printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
-					"Unable to write data to user %p\n",
-					__FILE__, __LINE__,
-					karg.dataInBufPtr);
+				"Unable to write sense data to user %p\n",
+				__FILE__, __LINE__,
+				karg.senseDataPtr);
 				rc =  -ENODATA;
+				goto done_free_mem;
 			}
 		}
 	}
 
+	/* If the overall status is _GOOD and data in, copy data
+	 * to user.
+	 */
+	if ((ioc->ioctl->status & MPT_IOCTL_STATUS_COMMAND_GOOD) &&
+				(karg.dataInSize > 0) && (bufIn.kptr)) {
+
+		if (copy_to_user(karg.dataInBufPtr,
+				 bufIn.kptr, karg.dataInSize)) {
+			printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+				"Unable to write data to user %p\n",
+				__FILE__, __LINE__,
+				karg.dataInBufPtr);
+			rc =  -ENODATA;
+		}
+	}
+
 done_free_mem:
-	/* Clear all status bits except TMTIMER_ACTIVE, this bit is cleared
-	 * upon completion of the TM command.
-	 * ioc->ioctl->status = 0;
-	 */
-	ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_TIMER_ACTIVE | MPT_IOCTL_STATUS_TM_FAILED |
-			MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID |
-			MPT_IOCTL_STATUS_RF_VALID | MPT_IOCTL_STATUS_DID_IOCRESET);
 
-	if (tm_flags_set)
-		mptctl_free_tm_flags(ioc);
+	ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_COMMAND_GOOD |
+		MPT_IOCTL_STATUS_SENSE_VALID |
+		MPT_IOCTL_STATUS_RF_VALID );
 
 	/* Free the allocated memory.
 	 */
-	 if (bufOut.kptr != NULL) {
+	if (bufOut.kptr != NULL) {
 		pci_free_consistent(ioc->pcidev,
 			bufOut.len, (void *) bufOut.kptr, dma_addr_out);
 	}
@@ -2549,7 +2478,7 @@
 				__FILE__, __LINE__, uarg);
 		return -EFAULT;
 	}
-	
+
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 		(ioc == NULL)) {
 		dctlprintk((KERN_ERR "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n",
@@ -2567,7 +2496,7 @@
 
 	if (ioc->sh->host_no != karg.hdr.host)
 		return -ENODEV;
-		
+
        /* Get the data transfer speeds
         */
 	data_sz = ioc->spi_data.sdp0length * 4;
@@ -2669,7 +2598,10 @@
 static struct file_operations mptctl_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
-	.ioctl =	mptctl_ioctl,
+	.unlocked_ioctl = mptctl_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = compat_mpctl_ioctl,
+#endif
 };
 
 static struct miscdevice mptctl_miscdev = {
@@ -2684,29 +2616,9 @@
 
 #include <linux/ioctl32.h>
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* compat_XXX functions are used to provide a conversion between
- * pointers and u32's. If the arg does not contain any pointers, then
- * a specialized function (compat_XXX) is not needed. If the arg
- * does contain pointer(s), then the specialized function is used
- * to ensure the structure contents is properly processed by mptctl.
- */
 static int
-compat_mptctl_ioctl(unsigned int fd, unsigned int cmd,
-			unsigned long arg, struct file *filp)
-{
-	int ret;
-
-	lock_kernel();
-	dctlprintk((KERN_INFO MYNAM "::compat_mptctl_ioctl() called\n"));
-	ret = mptctl_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
-	unlock_kernel();
-	return ret;
-}
- 
-static int
-compat_mptfwxfer_ioctl(unsigned int fd, unsigned int cmd,
-			unsigned long arg, struct file *filp)
+compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
+			unsigned long arg)
 {
 	struct mpt_fw_xfer32 kfw32;
 	struct mpt_fw_xfer kfw;
@@ -2744,8 +2656,8 @@
 }
 
 static int
-compat_mpt_command(unsigned int fd, unsigned int cmd,
-			unsigned long arg, struct file *filp)
+compat_mpt_command(struct file *filp, unsigned int cmd,
+			unsigned long arg)
 {
 	struct mpt_ioctl_command32 karg32;
 	struct mpt_ioctl_command32 __user *uarg = (struct mpt_ioctl_command32 __user *) arg;
@@ -2797,6 +2709,38 @@
 	return ret;
 }
 
+static long compat_mpctl_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	long ret;
+	lock_kernel();
+	switch (cmd) {
+	case MPTIOCINFO:
+	case MPTIOCINFO1:
+	case MPTIOCINFO2:
+	case MPTTARGETINFO:
+	case MPTEVENTQUERY:
+	case MPTEVENTENABLE:
+	case MPTEVENTREPORT:
+	case MPTHARDRESET:
+	case HP_GETHOSTINFO:
+	case HP_GETTARGETINFO:
+	case MPTTEST:
+		ret = __mptctl_ioctl(f, cmd, arg);
+		break;
+	case MPTCOMMAND32:
+		ret = compat_mpt_command(f, cmd, arg);
+		break;
+	case MPTFWDOWNLOAD32:
+		ret = compat_mptfwxfer_ioctl(f, cmd, arg);
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+		break;
+	}
+	unlock_kernel();
+	return ret;
+}
+
 #endif
 
 
@@ -2830,12 +2774,6 @@
 	memset(mem, 0, sz);
 	ioc->ioctl = (MPT_IOCTL *) mem;
 	ioc->ioctl->ioc = ioc;
-	init_timer (&ioc->ioctl->timer);
-	ioc->ioctl->timer.data = (unsigned long) ioc->ioctl;
-	ioc->ioctl->timer.function = mptctl_timer_expired;
-	init_timer (&ioc->ioctl->TMtimer);
-	ioc->ioctl->TMtimer.data = (unsigned long) ioc->ioctl;
-	ioc->ioctl->TMtimer.function = mptctl_timer_expired;
 	sema_init(&ioc->ioctl->sem_ioc, 1);
 	return 0;
 
@@ -2879,36 +2817,6 @@
 		": failed to register dd callbacks\n"));
 	}
 
-#ifdef CONFIG_COMPAT
-	err = register_ioctl32_conversion(MPTIOCINFO, compat_mptctl_ioctl);
-	if (++where && err) goto out_fail;
-	err = register_ioctl32_conversion(MPTIOCINFO1, compat_mptctl_ioctl);
-	if (++where && err) goto out_fail;
-	err = register_ioctl32_conversion(MPTIOCINFO2, compat_mptctl_ioctl);
-	if (++where && err) goto out_fail;
-	err = register_ioctl32_conversion(MPTTARGETINFO, compat_mptctl_ioctl);
-	if (++where && err) goto out_fail;
-	err = register_ioctl32_conversion(MPTTEST, compat_mptctl_ioctl);
-	if (++where && err) goto out_fail;
-	err = register_ioctl32_conversion(MPTEVENTQUERY, compat_mptctl_ioctl);
-	if (++where && err) goto out_fail;
-	err = register_ioctl32_conversion(MPTEVENTENABLE, compat_mptctl_ioctl);
-	if (++where && err) goto out_fail;
-	err = register_ioctl32_conversion(MPTEVENTREPORT, compat_mptctl_ioctl);
-	if (++where && err) goto out_fail;
-	err = register_ioctl32_conversion(MPTHARDRESET, compat_mptctl_ioctl);
-	if (++where && err) goto out_fail;
-	err = register_ioctl32_conversion(MPTCOMMAND32, compat_mpt_command);
-	if (++where && err) goto out_fail;
-	err = register_ioctl32_conversion(MPTFWDOWNLOAD32,
-					  compat_mptfwxfer_ioctl);
-	if (++where && err) goto out_fail;
-	err = register_ioctl32_conversion(HP_GETHOSTINFO, compat_mptctl_ioctl);
-	if (++where && err) goto out_fail;
-	err = register_ioctl32_conversion(HP_GETTARGETINFO, compat_mptctl_ioctl);
-	if (++where && err) goto out_fail;
-#endif
-
 	/* Register this device */
 	err = misc_register(&mptctl_miscdev);
 	if (err < 0) {
@@ -2940,24 +2848,6 @@
 
 out_fail:
 
-#ifdef CONFIG_COMPAT
-	printk(KERN_ERR MYNAM ": ERROR: Failed to register ioctl32_conversion!"
-			" (%d:err=%d)\n", where, err);
-	unregister_ioctl32_conversion(MPTIOCINFO);
-	unregister_ioctl32_conversion(MPTIOCINFO1);
-	unregister_ioctl32_conversion(MPTIOCINFO2);
-	unregister_ioctl32_conversion(MPTTARGETINFO);
-	unregister_ioctl32_conversion(MPTTEST);
-	unregister_ioctl32_conversion(MPTEVENTQUERY);
-	unregister_ioctl32_conversion(MPTEVENTENABLE);
-	unregister_ioctl32_conversion(MPTEVENTREPORT);
-	unregister_ioctl32_conversion(MPTHARDRESET);
-	unregister_ioctl32_conversion(MPTCOMMAND32);
-	unregister_ioctl32_conversion(MPTFWDOWNLOAD32);
-	unregister_ioctl32_conversion(HP_GETHOSTINFO);
-	unregister_ioctl32_conversion(HP_GETTARGETINFO);
-#endif
-
 	mpt_device_driver_deregister(MPTCTL_DRIVER);
 
 	return err;
@@ -2979,22 +2869,6 @@
 	printk(KERN_INFO MYNAM ": Deregistered from Fusion MPT base driver\n");
 
         mpt_device_driver_deregister(MPTCTL_DRIVER);
-
-#ifdef CONFIG_COMPAT
-	unregister_ioctl32_conversion(MPTIOCINFO);
-	unregister_ioctl32_conversion(MPTIOCINFO1);
-	unregister_ioctl32_conversion(MPTIOCINFO2);
-	unregister_ioctl32_conversion(MPTTARGETINFO);
-	unregister_ioctl32_conversion(MPTTEST);
-	unregister_ioctl32_conversion(MPTEVENTQUERY);
-	unregister_ioctl32_conversion(MPTEVENTENABLE);
-	unregister_ioctl32_conversion(MPTEVENTREPORT);
-	unregister_ioctl32_conversion(MPTHARDRESET);
-	unregister_ioctl32_conversion(MPTCOMMAND32);
-	unregister_ioctl32_conversion(MPTFWDOWNLOAD32);
-	unregister_ioctl32_conversion(HP_GETHOSTINFO);
-	unregister_ioctl32_conversion(HP_GETTARGETINFO);
-#endif
 
 }
 
diff -Nru a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
--- a/drivers/message/fusion/mptscsih.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/message/fusion/mptscsih.c	2005-03-07 15:19:08 -08:00
@@ -179,10 +179,11 @@
 static void	mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
 static void	copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
 static int	mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
+static int	mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
 static u32	SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
 
-static int	mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
-static int	mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
+static int	mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
+static int	mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
 
 static int	mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
 static int	mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
@@ -196,13 +197,9 @@
 static int	mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
 static int	mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 static void	mptscsih_timer_expired(unsigned long data);
-static void	mptscsih_taskmgmt_timeout(unsigned long data);
-static void	mptscsih_schedule_reset(void *hd);
 static int	mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
 static int	mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
 
-static struct work_struct   mptscsih_rstTask;
-
 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
 static int	mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
 static void	mptscsih_domainValidation(void *hd);
@@ -1207,7 +1204,6 @@
 	hd->tmState = TM_STATE_NONE;
 	hd->resetPending = 0;
 	hd->abortSCpnt = NULL;
-	hd->tmPtr = NULL;
 
 	/* Clear the pointer used to store
 	 * single-threaded commands, i.e., those
@@ -1224,14 +1220,6 @@
 	hd->timer.data = (unsigned long) hd;
 	hd->timer.function = mptscsih_timer_expired;
 
-	init_timer(&hd->TMtimer);
-	hd->TMtimer.data = (unsigned long) hd;
-	hd->TMtimer.function = mptscsih_taskmgmt_timeout;
-	hd->qtag_tick = jiffies;
-
-	/* Moved Earlier Pam D */
-	/* ioc->sh = sh;	*/
-
 	if (ioc->bus_type == SCSI) {
 		/* Update with the driver setup
 		 * values.
@@ -1925,7 +1913,6 @@
  *	@target: Logical Target ID for reset (if appropriate)
  *	@lun: Logical Unit for reset (if appropriate)
  *	@ctx2abort: Context for the task to be aborted (if appropriate)
- *	@sleepFlag: If set, use udelay instead of schedule in handshake code.
  *
  *	Remark: Currently invoked from a non-interrupt thread (_bh).
  *
@@ -1935,7 +1922,7 @@
  *	Returns 0 for SUCCESS or -1 if FAILED.
  */
 static int
-mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag)
+mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
 {
 	MPT_ADAPTER	*ioc;
 	int		 rc = -1;
@@ -2015,7 +2002,7 @@
 		 */
 		if (hd->hard_resets < -1)
 			hd->hard_resets++;
-		rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout, sleepFlag);
+		rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout);
 		if (rc) {
 			printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
 		} else {
@@ -2029,7 +2016,7 @@
 		ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
 		dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
 			 hd->ioc->name));
-		rc = mpt_HardResetHandler(hd->ioc, sleepFlag);
+		rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
 	}
 
 	dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
@@ -2046,7 +2033,6 @@
  *	@target: Logical Target ID for reset (if appropriate)
  *	@lun: Logical Unit for reset (if appropriate)
  *	@ctx2abort: Context for the task to be aborted (if appropriate)
- *	@sleepFlag: If set, use udelay instead of schedule in handshake code.
  *
  *	Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
  *	or a non-interrupt thread.  In the former, must not call schedule().
@@ -2057,7 +2043,7 @@
  *	else other non-zero value returned.
  */
 static int
-mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag)
+mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
 {
 	MPT_FRAME_HDR	*mf;
 	SCSITaskMgmt_t	*pScsiTm;
@@ -2087,7 +2073,7 @@
 	pScsiTm->TaskType = type;
 	pScsiTm->Reserved1 = 0;
 	pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
-	                    ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
+                    ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
 
 	for (ii= 0; ii < 8; ii++) {
 		pScsiTm->LUN[ii] = 0;
@@ -2099,29 +2085,32 @@
 
 	pScsiTm->TaskMsgContext = ctx2abort;
 
-	/* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
-		mpt_put_msg_frame(hd->ioc->id, mf);
-	* Save the MF pointer in case the request times out.
-	*/
-	hd->tmPtr = mf;
-	hd->TMtimer.expires = jiffies + timeout;
-	add_timer(&hd->TMtimer);
-
-	dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
-			hd->ioc->name, ctx2abort, type));
+	dtmprintk((MYIOC_s_INFO_FMT
+		"IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
+		hd->ioc->name, ctx2abort, type));
 
 	DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
 
 	if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc,
-				sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, sleepFlag))
-	!= 0) {
+		sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
+		CAN_SLEEP)) != 0) {
 		dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
-			" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf));
-		hd->tmPtr = NULL;
-		del_timer(&hd->TMtimer);
+			" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
+			hd->ioc, mf));
 		mpt_free_msg_frame(hd->ioc, mf);
+		return retval;
 	}
-	
+
+	if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
+		dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
+			" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
+			hd->ioc, mf));
+		mpt_free_msg_frame(hd->ioc, mf);
+		dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
+			 hd->ioc->name));
+		retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
+	}
+
 	return retval;
 }
 
@@ -2187,13 +2176,13 @@
 	 */
 	mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
 	ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
-	
+
 	hd->abortSCpnt = SCpnt;
 
 	spin_unlock_irq(host_lock);
 	if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
 		SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
-		ctx2abort, (HZ*2) /* 2 second timeout */,CAN_SLEEP)
+		ctx2abort, 2 /* 2 second timeout */)
 		< 0) {
 
 		/* The TM request failed and the subsequent FW-reload failed!
@@ -2206,7 +2195,7 @@
 		 */
 		hd->tmPending = 0;
 		hd->tmState = TM_STATE_NONE;
-		
+
 		spin_lock_irq(host_lock);
 
 		/* Unmap the DMA buffers, if any. */
@@ -2226,7 +2215,6 @@
 	}
 	spin_lock_irq(host_lock);
 	return SUCCESS;
-
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2259,15 +2247,10 @@
 	printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
 	       hd->ioc->name, SCpnt);
 
-	/* Supported for FC only.
-	 */
-	if (hd->ioc->bus_type == SCSI) 
-		return FAILED;
-
 	spin_unlock_irq(host_lock);
 	if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
 		SCpnt->device->channel, SCpnt->device->id,
-		0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
+		0, 0, 5 /* 5 second timeout */)
 		< 0){
 		/* The TM request failed and the subsequent FW-reload failed!
 		 * Fatal error case.
@@ -2317,7 +2300,7 @@
 	/* We are now ready to execute the task management request. */
 	spin_unlock_irq(host_lock);
 	if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
-		SCpnt->device->channel, 0, 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
+		SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */)
 	    < 0){
 
 		/* The TM request failed and the subsequent FW-reload failed!
@@ -2398,7 +2381,7 @@
 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
 {
 	unsigned long  flags;
-	int            loop_count = 10 * 4;  /* Wait 10 seconds */
+	int            loop_count = 4 * 10;  /* Wait 10 seconds */
 	int            status = FAILED;
 
 	do {
@@ -2406,8 +2389,8 @@
 		if (hd->tmState == TM_STATE_NONE) {
 			hd->tmState = TM_STATE_IN_PROGRESS;
 			hd->tmPending = 1;
-			spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
 			status = SUCCESS;
+			spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
 			break;
 		}
 		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
@@ -2419,6 +2402,34 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
+ *	mptscsih_tm_wait_for_completion - wait for completion of TM task
+ *	@hd: Pointer to MPT host structure.
+ *
+ *	Returns {SUCCESS,FAILED}.
+ */
+static int
+mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
+{
+	unsigned long  flags;
+	int            loop_count = 4 * timeout;
+	int            status = FAILED;
+
+	do {
+		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+		if(hd->tmPending == 0) {
+			status = SUCCESS;
+			spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+			break;
+		}
+		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+		msleep_interruptible(250);
+	} while (--loop_count);
+
+	return status;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
  *	mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@mf: Pointer to SCSI task mgmt request frame
@@ -2449,9 +2460,6 @@
 		 * Decrement count of outstanding TM requests.
 		 */
 		hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
-		if (hd->tmPtr) {
-			del_timer(&hd->TMtimer);
-		}
 	} else {
 		dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
 			ioc->name));
@@ -2505,7 +2513,6 @@
 		}
 	}
 
-	hd->tmPtr = NULL;
 	spin_lock_irqsave(&ioc->FreeQlock, flags);
 	hd->tmPending = 0;
 	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
@@ -2913,14 +2920,6 @@
 			mpt_free_msg_frame(ioc, hd->cmdPtr);
 		}
 
-		/* 2d. If a task management has not completed,
-		 * free resources associated with this request.
-		 */
-		if (hd->tmPtr) {
-			del_timer(&hd->TMtimer);
-			mpt_free_msg_frame(ioc, hd->tmPtr);
-		}
-
 		dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
 
 	} else {
@@ -2942,12 +2941,6 @@
 		/* 2. Chain Buffer initialization
 		 */
 
-		/* 3. tmPtr clear
-		 */
-		if (hd->tmPtr) {
-			hd->tmPtr = NULL;
-		}
-
 		/* 4. Renegotiate to all devices, if SCSI
 		 */
 		if (ioc->bus_type == SCSI) {
@@ -3808,60 +3801,6 @@
 	mpt_put_msg_frame(ScsiDoneCtx, ioc, mf);
 
 	return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*	mptscsih_taskmgmt_timeout - Call back for timeout on a
- *	task management request.
- *	@data: Pointer to MPT_SCSI_HOST recast as an unsigned long
- *
- */
-static void mptscsih_taskmgmt_timeout(unsigned long data)
-{
-	MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
-
-	dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_taskmgmt_timeout: "
-		   "TM request timed out!\n", hd->ioc->name));
-
-	/* Delete the timer that triggered this callback.
-	 * Remark: del_timer checks to make sure timer is active
-	 * before deleting.
-	 */
-	del_timer(&hd->TMtimer);
-
-	/* Call the reset handler. Already had a TM request
-	 * timeout - so issue a diagnostic reset
-	 */
-	INIT_WORK(&mptscsih_rstTask, mptscsih_schedule_reset, (void *)hd);
-	schedule_work(&mptscsih_rstTask);
-	return;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*	mptscsih_schedule_reset - Call back for timeout on a
- *	task management request.
- *	@data: Pointer to MPT_SCSI_HOST recast as an unsigned long
- *
- */
-static void
-mptscsih_schedule_reset(void *arg)
-{
-        MPT_SCSI_HOST           *hd;
-        hd = (MPT_SCSI_HOST *) arg;
-
-	if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) {
-		printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
-	} else {
-		/* Because we have reset the IOC, no TM requests can be
-		 * pending.  So let's make sure the tmPending flag is reset.
-		 */
-		dtmprintk((KERN_WARNING MYNAM
-			   ": %s: mptscsih_taskmgmt_timeout\n",
-			   hd->ioc->name));
-		hd->tmPending = 0;
-	}
-
-	return;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff -Nru a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
--- a/drivers/scsi/53c700.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/53c700.c	2005-03-07 15:19:08 -08:00
@@ -824,6 +824,7 @@
 	switch(hostdata->msgin[2]) {
 	case A_SDTR_MSG:
 		if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION)) {
+			struct scsi_target *starget = SCp->device->sdev_target;
 			__u8 period = hostdata->msgin[3];
 			__u8 offset = hostdata->msgin[4];
 
@@ -831,22 +832,15 @@
 				offset = 0;
 				period = 0;
 			}
+
+			spi_offset(starget) = offset;
+			spi_period(starget) = period;
 			
 			if(NCR_700_is_flag_set(SCp->device, NCR_700_DEV_PRINT_SYNC_NEGOTIATION)) {
-				if(spi_offset(SCp->device->sdev_target) != 0)
-					printk(KERN_INFO "scsi%d: (%d:%d) Synchronous at offset %d, period %dns\n",
-					       host->host_no, pun, lun,
-					       offset, period*4);
-				else
-					printk(KERN_INFO "scsi%d: (%d:%d) Asynchronous\n",
-					       host->host_no, pun, lun);
+				spi_display_xfer_agreement(starget);
 				NCR_700_clear_flag(SCp->device, NCR_700_DEV_PRINT_SYNC_NEGOTIATION);
 			}
-				
-			spi_offset(SCp->device->sdev_target) = offset;
-			spi_period(SCp->device->sdev_target) = period;
 			
-
 			NCR_700_set_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC);
 			NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION);
 			
diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
--- a/drivers/scsi/Kconfig	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/Kconfig	2005-03-07 15:19:08 -08:00
@@ -619,7 +619,7 @@
 
 config SCSI_EATA_PIO
 	tristate "EATA-PIO (old DPT PM2001, PM2012A) support"
-	depends on (ISA || EISA || PCI) && SCSI
+	depends on (ISA || EISA || PCI) && SCSI && BROKEN
 	---help---
 	  This driver supports all EATA-PIO protocol compliant SCSI Host
 	  Adapters like the DPT PM2001 and the PM2012A.  EATA-DMA compliant
@@ -1257,7 +1257,7 @@
 
 config SCSI_QLOGIC_ISP
 	tristate "Qlogic ISP SCSI support (old driver)"
-	depends on PCI && SCSI
+	depends on PCI && SCSI && BROKEN
 	---help---
 	  This driver works for all QLogic PCI SCSI host adapters (IQ-PCI,
 	  IQ-PCI-10, IQ_PCI-D) except for the PCI-basic card.  (This latter
diff -Nru a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
--- a/drivers/scsi/NCR5380.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/NCR5380.c	2005-03-07 15:19:08 -08:00
@@ -533,7 +533,7 @@
 static void NCR5380_set_timer(struct NCR5380_hostdata *hostdata, unsigned long timeout)
 {
 	hostdata->time_expires = jiffies + timeout;
-	schedule_delayed_work(&hostdata->coroutine, hostdata->time_expires);
+	schedule_delayed_work(&hostdata->coroutine, timeout);
 }
 
 
@@ -671,16 +671,8 @@
 
 static void NCR5380_print_status(struct Scsi_Host *instance)
 {
-	static char pr_bfr[512];
-	char *start;
-	int len;
-
 	NCR5380_dprint(NDEBUG_ANY, instance);
 	NCR5380_dprint_phase(NDEBUG_ANY, instance);
-
-	len = NCR5380_proc_info(instance, pr_bfr, &start, 0, sizeof(pr_bfr), 0);
-	pr_bfr[len] = 0;
-	printk("\n%s\n", pr_bfr);
 }
 
 /******************************************/
@@ -2684,11 +2676,6 @@
 	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 	Scsi_Cmnd *tmp, **prev;
 	
-	printk(KERN_WARNING "scsi%d : aborting command\n", instance->host_no);
-	print_Scsi_Cmnd(cmd);
-
-	NCR5380_print_status(instance);
-
 	printk(KERN_WARNING "scsi%d : aborting command\n", instance->host_no);
 	print_Scsi_Cmnd(cmd);
 
diff -Nru a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c
--- a/drivers/scsi/NCR_D700.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/NCR_D700.c	2005-03-07 15:19:08 -08:00
@@ -106,7 +106,7 @@
 #include "53c700.h"
 #include "NCR_D700.h"
 
-char *NCR_D700;			/* command line from insmod */
+static char *NCR_D700;		/* command line from insmod */
 
 MODULE_AUTHOR("James Bottomley");
 MODULE_DESCRIPTION("NCR Dual700 SCSI Driver");
@@ -352,7 +352,7 @@
 
 static short NCR_D700_id_table[] = { NCR_D700_MCA_ID, 0 };
 
-struct mca_driver NCR_D700_driver = {
+static struct mca_driver NCR_D700_driver = {
 	.id_table = NCR_D700_id_table,
 	.driver = {
 		.name		= "NCR_D700",
diff -Nru a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
--- a/drivers/scsi/aacraid/linit.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/aacraid/linit.c	2005-03-07 15:19:08 -08:00
@@ -45,6 +45,7 @@
 #include <linux/syscalls.h>
 #include <linux/ioctl32.h>
 #include <linux/delay.h>
+#include <linux/smp_lock.h>
 #include <asm/semaphore.h>
 
 #include <scsi/scsi.h>
@@ -191,28 +192,6 @@
 	{ aac_rkt_init, "aacraid", "ADAPTEC ", "RAID            ", 2 } /* Adaptec Rocket Catch All */
 };
 
-#ifdef CONFIG_COMPAT
-/* 
- * Promote 32 bit apps that call get_next_adapter_fib_ioctl to 64 bit version 
- */
-static int aac_get_next_adapter_fib_ioctl(unsigned int fd, unsigned int cmd, 
-		unsigned long arg, struct file *file)
-{
-	struct fib_ioctl __user *f;
-
-	f = compat_alloc_user_space(sizeof(*f));
-	if (!access_ok(VERIFY_WRITE, f, sizeof(*f)))
-		return -EFAULT;
-
-	clear_user(f, sizeof(*f));
-	if (copy_in_user(f, (void __user *)arg, sizeof(struct fib_ioctl) - sizeof(u32)))
-		return -EFAULT;
-
-	return sys_ioctl(fd, cmd, (unsigned long)f);
-}
-#endif
-
-
 /**
  *	aac_queuecommand	-	queue a SCSI command
  *	@cmd:		SCSI command to queue
@@ -494,9 +473,65 @@
 	return aac_do_ioctl(file->private_data, cmd, (void __user *)arg);
 }
 
+#ifdef CONFIG_COMPAT
+static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long arg)
+{
+	long ret;
+	lock_kernel();
+	switch (cmd) { 
+	case FSACTL_MINIPORT_REV_CHECK:
+	case FSACTL_SENDFIB:
+	case FSACTL_OPEN_GET_ADAPTER_FIB:
+	case FSACTL_CLOSE_GET_ADAPTER_FIB:
+	case FSACTL_SEND_RAW_SRB:
+	case FSACTL_GET_PCI_INFO:
+	case FSACTL_QUERY_DISK:
+	case FSACTL_DELETE_DISK:
+	case FSACTL_FORCE_DELETE_DISK:
+	case FSACTL_GET_CONTAINERS: 
+		ret = aac_do_ioctl(dev, cmd, (void __user *)arg);
+		break;
+
+	case FSACTL_GET_NEXT_ADAPTER_FIB: {
+		struct fib_ioctl __user *f;
+		
+		f = compat_alloc_user_space(sizeof(*f));
+		ret = 0;
+		if (clear_user(f, sizeof(*f) != sizeof(*f)))
+			ret = -EFAULT;
+		if (copy_in_user(f, (void __user *)arg, sizeof(struct fib_ioctl) - sizeof(u32)))
+			ret = -EFAULT;
+		if (!ret)
+			ret = aac_do_ioctl(dev, cmd, (void __user *)arg);
+		break;
+	}
+
+	default:
+		ret = -ENOIOCTLCMD; 
+		break;
+	} 
+	unlock_kernel();
+	return ret;
+}
+
+static int aac_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
+{
+	struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
+	return aac_compat_do_ioctl(dev, cmd, (unsigned long)arg);
+}
+
+static long aac_compat_cfg_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+{
+	return aac_compat_do_ioctl((struct aac_dev *)file->private_data, cmd, arg);
+}
+#endif
+
 static struct file_operations aac_cfg_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= aac_cfg_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl   = aac_compat_cfg_ioctl,
+#endif
 	.open		= aac_cfg_open,
 };
 
@@ -506,6 +541,9 @@
 	.proc_name			= "aacraid",
 	.info           		= aac_info,
 	.ioctl          		= aac_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl			= aac_compat_ioctl,
+#endif
 	.queuecommand   		= aac_queuecommand,
 	.bios_param     		= aac_biosparm,	
 	.slave_configure		= aac_slave_configure,
@@ -699,39 +737,11 @@
 		printk(KERN_WARNING
 		       "aacraid: unable to register \"aac\" device.\n");
 	}
-#ifdef CONFIG_COMPAT
-	register_ioctl32_conversion(FSACTL_MINIPORT_REV_CHECK, NULL);
-	register_ioctl32_conversion(FSACTL_SENDFIB, NULL);
-	register_ioctl32_conversion(FSACTL_OPEN_GET_ADAPTER_FIB, NULL);
-	register_ioctl32_conversion(FSACTL_GET_NEXT_ADAPTER_FIB, 
-		aac_get_next_adapter_fib_ioctl);
-	register_ioctl32_conversion(FSACTL_CLOSE_GET_ADAPTER_FIB, NULL);
-	register_ioctl32_conversion(FSACTL_SEND_RAW_SRB, NULL);
-	register_ioctl32_conversion(FSACTL_GET_PCI_INFO, NULL);
-	register_ioctl32_conversion(FSACTL_QUERY_DISK, NULL);
-	register_ioctl32_conversion(FSACTL_DELETE_DISK, NULL);
-	register_ioctl32_conversion(FSACTL_FORCE_DELETE_DISK, NULL);
-	register_ioctl32_conversion(FSACTL_GET_CONTAINERS, NULL);
-#endif
-
 	return 0;
 }
 
 static void __exit aac_exit(void)
 {
-#ifdef CONFIG_COMPAT
-	unregister_ioctl32_conversion(FSACTL_MINIPORT_REV_CHECK);
-	unregister_ioctl32_conversion(FSACTL_SENDFIB);
-	unregister_ioctl32_conversion(FSACTL_OPEN_GET_ADAPTER_FIB);
-	unregister_ioctl32_conversion(FSACTL_GET_NEXT_ADAPTER_FIB);
-	unregister_ioctl32_conversion(FSACTL_CLOSE_GET_ADAPTER_FIB);
-	unregister_ioctl32_conversion(FSACTL_SEND_RAW_SRB);
-	unregister_ioctl32_conversion(FSACTL_GET_PCI_INFO);
-	unregister_ioctl32_conversion(FSACTL_QUERY_DISK);
-	unregister_ioctl32_conversion(FSACTL_DELETE_DISK);
-	unregister_ioctl32_conversion(FSACTL_FORCE_DELETE_DISK);
-	unregister_ioctl32_conversion(FSACTL_GET_CONTAINERS);
-#endif
 	unregister_chrdev(aac_cfg_major, "aac");
 	pci_unregister_driver(&aac_pci_driver);
 }
diff -Nru a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
--- a/drivers/scsi/dc395x.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/dc395x.c	2005-03-07 15:19:08 -08:00
@@ -182,7 +182,7 @@
  * cross a page boundy.
  */
 #define SEGMENTX_LEN	(sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY)
-
+#define VIRTX_LEN	(sizeof(void *) * DC395x_MAX_SG_LISTENTRY)
 
 struct SGentry {
 	u32 address;		/* bus! address */
@@ -234,6 +234,7 @@
 	u8 sg_count;			/* No of HW sg entries for this request */
 	u8 sg_index;			/* Index of HW sg entry for this request */
 	u32 total_xfer_length;		/* Total number of bytes remaining to be transfered */
+	void **virt_map;
 	unsigned char *virt_addr;	/* Virtual address of current transfer position */
 
 	/*
@@ -1020,14 +1021,14 @@
 			reqlen, cmd->request_buffer, cmd->use_sg,
 			srb->sg_count);
 
-		srb->virt_addr = page_address(sl->page);
 		for (i = 0; i < srb->sg_count; i++) {
-			u32 busaddr = (u32)sg_dma_address(&sl[i]);
-			u32 seglen = (u32)sl[i].length;
-			sgp[i].address = busaddr;
+			u32 seglen = (u32)sg_dma_len(sl + i);
+			sgp[i].address = (u32)sg_dma_address(sl + i);
 			sgp[i].length = seglen;
 			srb->total_xfer_length += seglen;
+			srb->virt_map[i] = kmap(sl[i].page);
 		}
+		srb->virt_addr = srb->virt_map[0];
 		sgp += srb->sg_count - 1;
 
 		/*
@@ -1964,6 +1965,7 @@
 	int segment = cmd->use_sg;
 	u32 xferred = srb->total_xfer_length - left; /* bytes transfered */
 	struct SGentry *psge = srb->segment_x + srb->sg_index;
+	void **virt = srb->virt_map;
 
 	dprintkdbg(DBG_0,
 		"sg_update_list: Transfered %i of %i bytes, %i remain\n",
@@ -2003,16 +2005,16 @@
 
 	/* We have to walk the scatterlist to find it */
 	sg = (struct scatterlist *)cmd->request_buffer;
+	idx = 0;
 	while (segment--) {
 		unsigned long mask =
 		    ~((unsigned long)sg->length - 1) & PAGE_MASK;
 		if ((sg_dma_address(sg) & mask) == (psge->address & mask)) {
-			srb->virt_addr = (page_address(sg->page)
-					   + psge->address -
-					   (psge->address & PAGE_MASK));
+			srb->virt_addr = virt[idx] + (psge->address & ~PAGE_MASK);
 			return;
 		}
 		++sg;
+		++idx;
 	}
 
 	dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n");
@@ -2138,7 +2140,7 @@
 				DC395x_read32(acb, TRM_S1040_DMA_CXCNT));
 		}
 		/*
-		 * calculate all the residue data that not yet tranfered
+		 * calculate all the residue data that not yet transfered
 		 * SCSI transfer counter + left in SCSI FIFO data
 		 *
 		 * .....TRM_S1040_SCSI_COUNTER (24bits)
@@ -3256,6 +3258,7 @@
 	struct scsi_cmnd *cmd = srb->cmd;
 	enum dma_data_direction dir = cmd->sc_data_direction;
 	if (cmd->use_sg && dir != PCI_DMA_NONE) {
+		int i;
 		/* unmap DC395x SG list */
 		dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n",
 			srb->sg_bus_addr, SEGMENTX_LEN);
@@ -3265,6 +3268,8 @@
 		dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n",
 			cmd->use_sg, cmd->request_buffer);
 		/* unmap the sg segments */
+		for (i = 0; i < srb->sg_count; i++)
+			kunmap(virt_to_page(srb->virt_map[i]));
 		pci_unmap_sg(acb->dev,
 			     (struct scatterlist *)cmd->request_buffer,
 			     cmd->use_sg, dir);
@@ -3311,7 +3316,7 @@
 
 	if (cmd->use_sg) {
 		struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer;
-		ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset);
+		ptr = (struct ScsiInqData *)(srb->virt_map[0] + sg->offset);
 	} else {
 		ptr = (struct ScsiInqData *)(cmd->request_buffer);
 	}
@@ -4246,8 +4251,9 @@
 	const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN;
 
 	for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page)
-		if (acb->srb_array[i].segment_x)
-			kfree(acb->srb_array[i].segment_x);
+		kfree(acb->srb_array[i].segment_x);
+
+	vfree(acb->srb_array[0].virt_map);
 }
 
 
@@ -4263,9 +4269,12 @@
 	int srb_idx = 0;
 	unsigned i = 0;
 	struct SGentry *ptr;
+	void **virt_array;
 
-	for (i = 0; i < DC395x_MAX_SRB_CNT; i++)
+	for (i = 0; i < DC395x_MAX_SRB_CNT; i++) {
 		acb->srb_array[i].segment_x = NULL;
+		acb->srb_array[i].virt_map = NULL;
+	}
 
 	dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages);
 	while (pages--) {
@@ -4286,6 +4295,19 @@
 		    ptr + (i * DC395x_MAX_SG_LISTENTRY);
 	else
 		dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n");
+
+	virt_array = vmalloc((DC395x_MAX_SRB_CNT + 1) * DC395x_MAX_SG_LISTENTRY * sizeof(void*));
+
+	if (!virt_array) {
+		adapter_sg_tables_free(acb);
+		return 1;
+	}
+
+	for (i = 0; i < DC395x_MAX_SRB_CNT + 1; i++) {
+		acb->srb_array[i].virt_map = virt_array;
+		virt_array += DC395x_MAX_SG_LISTENTRY;
+	}
+
 	return 0;
 }
 
diff -Nru a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
--- a/drivers/scsi/hosts.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/hosts.c	2005-03-07 15:19:08 -08:00
@@ -216,6 +216,7 @@
 	spin_lock_init(&shost->default_lock);
 	scsi_assign_lock(shost, &shost->default_lock);
 	INIT_LIST_HEAD(&shost->__devices);
+	INIT_LIST_HEAD(&shost->__targets);
 	INIT_LIST_HEAD(&shost->eh_cmd_q);
 	INIT_LIST_HEAD(&shost->starved_list);
 	init_waitqueue_head(&shost->host_wait);
diff -Nru a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
--- a/drivers/scsi/megaraid/megaraid_mm.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/megaraid/megaraid_mm.c	2005-03-07 15:19:08 -08:00
@@ -16,6 +16,7 @@
  */
 
 #include "megaraid_mm.h"
+#include <linux/smp_lock.h>
 
 
 // Entry points for char node driver
@@ -43,8 +44,7 @@
 static void mraid_mm_teardown_dma_pools(mraid_mmadp_t *);
 
 #ifdef CONFIG_COMPAT
-static int mraid_mm_compat_ioctl(unsigned int, unsigned int, unsigned long,
-		struct file *);
+static long mraid_mm_compat_ioctl(struct file *, unsigned int, unsigned long);
 #endif
 
 MODULE_AUTHOR("LSI Logic Corporation");
@@ -71,6 +71,9 @@
 static struct file_operations lsi_fops = {
 	.open	= mraid_mm_open,
 	.ioctl	= mraid_mm_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = mraid_mm_compat_ioctl,
+#endif
 	.owner	= THIS_MODULE,
 };
 
@@ -1215,8 +1218,6 @@
 
 	INIT_LIST_HEAD(&adapters_list_g);
 
-	register_ioctl32_conversion(MEGAIOCCMD, mraid_mm_compat_ioctl);
-
 	return 0;
 }
 
@@ -1225,13 +1226,15 @@
  * mraid_mm_compat_ioctl	: 32bit to 64bit ioctl conversion routine
  */
 #ifdef CONFIG_COMPAT
-static int
-mraid_mm_compat_ioctl(unsigned int fd, unsigned int cmd,
-			unsigned long arg, struct file *filep)
-{
-	struct inode *inode = filep->f_dentry->d_inode;
-
-	return mraid_mm_ioctl(inode, filep, cmd, arg);
+static long
+mraid_mm_compat_ioctl(struct file *filep, unsigned int cmd,
+		      unsigned long arg)
+{
+	int err;
+	lock_kernel();
+	err = mraid_mm_ioctl(NULL, filep, cmd, arg);
+	unlock_kernel();
+	return err;
 }
 #endif
 
@@ -1244,7 +1247,6 @@
 	con_log(CL_DLEVEL1 , ("exiting common mod\n"));
 
 	unregister_chrdev(majorno, "megadev");
-	unregister_ioctl32_conversion(MEGAIOCCMD);
 }
 
 module_init(mraid_mm_init);
diff -Nru a/drivers/scsi/osst.c b/drivers/scsi/osst.c
--- a/drivers/scsi/osst.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/osst.c	2005-03-07 15:19:08 -08:00
@@ -5121,6 +5121,22 @@
 	return retval;
 }
 
+#ifdef CONFIG_COMPAT
+static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned long arg)
+{
+	struct osst_tape *STp = file->private_data;
+	struct scsi_device *sdev = STp->device;
+	int ret = -ENOIOCTLCMD;
+	if (sdev->host->hostt->compat_ioctl) {
+
+		ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
+
+	}
+	return ret;
+}
+#endif
+
+
 
 /* Memory handling routines */
 
@@ -5456,6 +5472,9 @@
 	.read =         osst_read,
 	.write =        osst_write,
 	.ioctl =        osst_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = osst_compat_ioctl,
+#endif
 	.open =         os_scsi_tape_open,
 	.flush =        os_scsi_tape_flush,
 	.release =      os_scsi_tape_close,
diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
--- a/drivers/scsi/qla1280.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/qla1280.c	2005-03-07 15:19:08 -08:00
@@ -20,6 +20,9 @@
 #define QLA1280_VERSION      "3.25"
 /*****************************************************************************
     Revision History:
+    Rev  3.25.1, February 10, 2005 Christoph Hellwig
+	- use pci_map_single to map non-S/G requests
+	- remove qla1280_proc_info
     Rev  3.25, September 28, 2004, Christoph Hellwig
 	- add support for ISP1020/1040
 	- don't include "scsi.h" anymore for 2.6.x
@@ -670,8 +673,6 @@
 };
 
 static int qla1280_verbose = 1;
-static int qla1280_buffer_size;
-static char *qla1280_buffer;
 
 #if DEBUG_QLA1280
 static int ql_debug_level = 1;
@@ -694,97 +695,6 @@
 #define LEAVE_INTR(x)		dprintk(4, "qla1280 : Leaving %s()\n", x);
 
 
-/*************************************************************************
- * qla1280_proc_info
- *
- * Description:
- *   Return information to handle /proc support for the driver.
- *
- * buffer - ptrs to a page buffer
- *
- * Returns:
- *************************************************************************/
-#define	PROC_BUF	&qla1280_buffer[len]
-
-static int qla1280_proc_info(struct Scsi_Host *host, char *buffer,
-			     char **start, off_t offset, int length, int inout)
-{
-	struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata;
-	struct qla_boards *bdp = &ql1280_board_tbl[ha->devnum];
-	int size = 0;
-	int len = 0;
-
-	if (inout)
-		return -ENOSYS;
-
-	/*
-	 * if our old buffer is the right size use it otherwise
-	 * allocate a new one.
-	 */
-	if (qla1280_buffer_size != PAGE_SIZE) {
-		/* deallocate this buffer and get a new one */
-		if (qla1280_buffer != NULL) {
-			free_page((unsigned long)qla1280_buffer);
-			qla1280_buffer_size = 0;
-		}
-		qla1280_buffer = (char *)get_zeroed_page(GFP_KERNEL);
-	}
-	if (qla1280_buffer == NULL) {
-		size = sprintf(buffer, "qla1280 - kmalloc error at line %d\n",
-			       __LINE__);
-		return size;
-	}
-	/* save the size of our buffer */
-	qla1280_buffer_size = PAGE_SIZE;
-
-	/* 3.20 clear the buffer we use for proc display */
-	memset(qla1280_buffer, 0, PAGE_SIZE);
-
-	/* start building the print buffer */
-	size = sprintf(PROC_BUF,
-		       "QLogic PCI to SCSI Adapter for ISP 1280/12160:\n"
-		       "        Firmware version: %2d.%02d.%02d, Driver version %s\n",
-		       bdp->fwver[0], bdp->fwver[1], bdp->fwver[2],
-		       QLA1280_VERSION);
-
-	len += size;
-
-	size = sprintf(PROC_BUF, "SCSI Host Adapter Information: %s\n",
-		       bdp->name);
-	len += size;
-	size = sprintf(PROC_BUF, "Request Queue count= 0x%x, Response "
-		       "Queue count= 0x%x\n",
-		       REQUEST_ENTRY_CNT, RESPONSE_ENTRY_CNT);
-	len += size;
-	size = sprintf(PROC_BUF, "Number of pending commands = 0x%lx\n",
-		       ha->actthreads);
-	len += size;
-	size = sprintf(PROC_BUF, "Number of free request entries = %d\n",
-		       ha->req_q_cnt);
-	len += size;
-	size = sprintf(PROC_BUF, "\n");	/* 1       */
-	len += size;
-
-	if (len >= qla1280_buffer_size) {
-		printk(KERN_WARNING
-		       "qla1280: Overflow buffer in qla1280_proc.c\n");
-	}
-
-	if (offset > len - 1) {
-		free_page((unsigned long) qla1280_buffer);
-		qla1280_buffer = NULL;
-		qla1280_buffer_size = length = 0;
-		*start = NULL;
-	} else {
-		*start = &qla1280_buffer[offset];	/* Start of wanted data */
-		if (len - offset < length) {
-			length = len - offset;
-		}
-	}
-	return length;
-}
-
-
 static int qla1280_read_nvram(struct scsi_qla_host *ha)
 {
 	uint16_t *wptr;
@@ -1334,22 +1244,6 @@
 {
 	return qla1280_biosparam(disk->device, NULL, disk->capacity, geom);
 }
-
-static int
-qla1280_proc_info_old(char *buffer, char **start, off_t offset, int length,
-		      int hostno, int inout)
-{
-	struct Scsi_Host *host;
-
-	for (host = scsi_hostlist; host; host = host->next) {
-		if (host->host_no == hostno) {
-			return qla1280_proc_info(host, buffer, start,
-						 offset, length, inout);
-		}
-	}
-
-	return -ESRCH;
-}
 #endif
 
 /**************************************************************************
@@ -1571,16 +1465,12 @@
 
 		/* Release memory used for this I/O */
 		if (cmd->use_sg) {
-			dprintk(3, "S/G unmap_sg cmd=%p\n", cmd);
-
 			pci_unmap_sg(ha->pdev, cmd->request_buffer,
-				     cmd->use_sg, cmd->sc_data_direction);
+					cmd->use_sg, cmd->sc_data_direction);
 		} else if (cmd->request_bufflen) {
-			/*dprintk(1, "No S/G unmap_single cmd=%x saved_dma_handle=%lx\n",
-			  cmd, sp->saved_dma_handle); */
-
-			pci_unmap_page(ha->pdev, sp->saved_dma_handle,
-				       cmd->request_bufflen, cmd->sc_data_direction);
+			pci_unmap_single(ha->pdev, sp->saved_dma_handle,
+					cmd->request_bufflen,
+					cmd->sc_data_direction);
 		}
 
 		/* Call the mid-level driver interrupt handler */
@@ -3354,14 +3244,11 @@
 						    REQUEST_ENTRY_SIZE);
 			}
 		} else {	/* No scatter gather data transfer */
-			struct page *page = virt_to_page(cmd->request_buffer);
-			unsigned long off = (unsigned long)cmd->request_buffer & ~PAGE_MASK;
-
-			dma_handle = pci_map_page(ha->pdev, page, off,
-						  cmd->request_bufflen,
-						  cmd->sc_data_direction);
+			dma_handle = pci_map_single(ha->pdev,
+					cmd->request_buffer,
+					cmd->request_bufflen,
+					cmd->sc_data_direction);
 
-			/* save dma_handle for pci_unmap_page */
 			sp->saved_dma_handle = dma_handle;
 #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
 			if (ha->flags.use_pci_vchannel)
@@ -3636,11 +3523,10 @@
 						    REQUEST_ENTRY_SIZE);
 			}
 		} else {	/* No S/G data transfer */
-			struct page *page = virt_to_page(cmd->request_buffer);
-			unsigned long off = (unsigned long)cmd->request_buffer & ~PAGE_MASK;
-			dma_handle = pci_map_page(ha->pdev, page, off,
-						  cmd->request_bufflen,
-						  cmd->sc_data_direction);
+			dma_handle = pci_map_single(ha->pdev,
+					cmd->request_buffer,
+					cmd->request_bufflen,
+					cmd->sc_data_direction);
 			sp->saved_dma_handle = dma_handle;
 
 			*dword_ptr++ = cpu_to_le32(pci_dma_lo32(dma_handle));
@@ -4668,7 +4554,6 @@
 	.eh_bus_reset_handler	= qla1280_eh_bus_reset,
 	.eh_host_reset_handler	= qla1280_eh_adapter_reset,
 	.bios_param		= qla1280_biosparam,
-	.proc_info		= qla1280_proc_info,
 	.can_queue		= 0xfffff,
 	.this_id		= -1,
 	.sg_tablesize		= SG_ALL,
@@ -4688,7 +4573,6 @@
 	.eh_bus_reset_handler	= qla1280_eh_bus_reset,
 	.eh_host_reset_handler	= qla1280_eh_adapter_reset,
 	.bios_param		= qla1280_biosparam_old,
-	.proc_info		= qla1280_proc_info_old,
 	.can_queue		= 0xfffff,
 	.this_id		= -1,
 	.sg_tablesize		= SG_ALL,
diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
--- a/drivers/scsi/scsi.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/scsi.c	2005-03-07 15:19:08 -08:00
@@ -88,12 +88,6 @@
 				COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len)
 
 /*
- * Data declarations.
- */
-unsigned long scsi_pid;
-static unsigned long serial_number;
-
-/*
  * Note - the initial logging level can be set here to log events at boot time.
  * After the system is up, you may enable logging via the /proc interface.
  */
@@ -510,6 +504,21 @@
 }
 #endif
 
+/* 
+ * Assign a serial number and pid to the request for error recovery
+ * and debugging purposes.  Protected by the Host_Lock of host.
+ */
+static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd)
+{
+	cmd->serial_number = host->cmd_serial_number++;
+	if (cmd->serial_number == 0) 
+		cmd->serial_number = host->cmd_serial_number++;
+	
+	cmd->pid = host->cmd_pid++;
+	if (cmd->pid == 0)
+		cmd->pid = host->cmd_pid++;
+}
+
 /*
  * Function:    scsi_dispatch_command
  *
@@ -532,6 +541,7 @@
 		 * returns an immediate error upwards, and signals
 		 * that the device is no longer present */
 		cmd->result = DID_NO_CONNECT << 16;
+		atomic_inc(&cmd->device->iorequest_cnt);
 		scsi_done(cmd);
 		/* return 0 (because the command has been processed) */
 		goto out;
@@ -556,13 +566,6 @@
 		goto out;
 	}
 
-	/* Assign a unique nonzero serial_number. */
-	/* XXX(hch): this is racy */
-	if (++serial_number == 0)
-		serial_number = 1;
-	cmd->serial_number = serial_number;
-	cmd->pid = scsi_pid++;
-
 	/* 
 	 * If SCSI-2 or lower, store the LUN value in cmnd.
 	 */
@@ -593,6 +596,10 @@
 		host->resetting = 0;
 	}
 
+	/* 
+	 * AK: unlikely race here: for some reason the timer could
+	 * expire before the serial number is set up below.
+	 */
 	scsi_add_timer(cmd, cmd->timeout_per_command, scsi_times_out);
 
 	scsi_log_send(cmd);
@@ -605,6 +612,8 @@
 	cmd->state = SCSI_STATE_QUEUED;
 	cmd->owner = SCSI_OWNER_LOWLEVEL;
 
+	atomic_inc(&cmd->device->iorequest_cnt);
+
 	/*
 	 * Before we queue this command, check if the command
 	 * length exceeds what the host adapter can handle.
@@ -619,6 +628,8 @@
 	}
 
 	spin_lock_irqsave(host->host_lock, flags);
+	scsi_cmd_get_serial(host, cmd); 
+
 	if (unlikely(test_bit(SHOST_CANCEL, &host->shost_state))) {
 		cmd->result = (DID_NO_CONNECT << 16);
 		scsi_done(cmd);
@@ -627,6 +638,7 @@
 	}
 	spin_unlock_irqrestore(host->host_lock, flags);
 	if (rtn) {
+		atomic_inc(&cmd->device->iodone_cnt);
 		scsi_queue_insert(cmd,
 				(rtn == SCSI_MLQUEUE_DEVICE_BUSY) ?
 				 rtn : SCSI_MLQUEUE_HOST_BUSY);
@@ -758,6 +770,10 @@
 	cmd->state = SCSI_STATE_BHQUEUE;
 	cmd->owner = SCSI_OWNER_BH_HANDLER;
 
+	atomic_inc(&cmd->device->iodone_cnt);
+	if (cmd->result)
+		atomic_inc(&cmd->device->ioerr_cnt);
+
 	/*
 	 * Next, enqueue the command into the done queue.
 	 * It is a per-CPU queue, so we just disable local interrupts
@@ -920,12 +936,9 @@
  * 		the right thing depending on whether or not the device is
  * 		currently active and whether or not it even has the
  * 		command blocks built yet.
- *
- * XXX(hch):	What exactly is device_request_lock trying to protect?
  */
 void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags)
 {
-	static DEFINE_SPINLOCK(device_request_lock);
 	unsigned long flags;
 
 	/*
@@ -934,8 +947,7 @@
 	if (tags <= 0)
 		return;
 
-	spin_lock_irqsave(&device_request_lock, flags);
-	spin_lock(sdev->request_queue->queue_lock);
+	spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
 
 	/* Check to see if the queue is managed by the block layer
 	 * if it is, and we fail to adjust the depth, exit */
@@ -964,8 +976,7 @@
 			break;
 	}
  out:
-	spin_unlock(sdev->request_queue->queue_lock);
-	spin_unlock_irqrestore(&device_request_lock, flags);
+	spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
 }
 EXPORT_SYMBOL(scsi_adjust_queue_depth);
 
@@ -1103,6 +1114,60 @@
 	}
 }
 EXPORT_SYMBOL(starget_for_each_device);
+
+/**
+ * __scsi_device_lookup_by_target - find a device given the target (UNLOCKED)
+ * @starget:	SCSI target pointer
+ * @lun:	SCSI Logical Unit Number
+ *
+ * Looks up the scsi_device with the specified @lun for a give
+ * @starget. The returned scsi_device does not have an additional
+ * reference.  You must hold the host's host_lock over this call and
+ * any access to the returned scsi_device.
+ *
+ * Note:  The only reason why drivers would want to use this is because
+ * they're need to access the device list in irq context.  Otherwise you
+ * really want to use scsi_device_lookup_by_target instead.
+ **/
+struct scsi_device *__scsi_device_lookup_by_target(struct scsi_target *starget,
+						   uint lun)
+{
+	struct scsi_device *sdev;
+
+	list_for_each_entry(sdev, &starget->devices, same_target_siblings) {
+		if (sdev->lun ==lun)
+			return sdev;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(__scsi_device_lookup_by_target);
+
+/**
+ * scsi_device_lookup_by_target - find a device given the target
+ * @starget:	SCSI target pointer
+ * @lun:	SCSI Logical Unit Number
+ *
+ * Looks up the scsi_device with the specified @channel, @id, @lun for a
+ * give host.  The returned scsi_device has an additional reference that
+ * needs to be release with scsi_host_put once you're done with it.
+ **/
+struct scsi_device *scsi_device_lookup_by_target(struct scsi_target *starget,
+						 uint lun)
+{
+	struct scsi_device *sdev;
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	unsigned long flags;
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	sdev = __scsi_device_lookup_by_target(starget, lun);
+	if (sdev && scsi_device_get(sdev))
+		sdev = NULL;
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
+	return sdev;
+}
+EXPORT_SYMBOL(scsi_device_lookup_by_target);
 
 /**
  * scsi_device_lookup - find a device given the host (UNLOCKED)
diff -Nru a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
--- a/drivers/scsi/scsi_devinfo.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/scsi_devinfo.c	2005-03-07 15:19:08 -08:00
@@ -63,6 +63,7 @@
 	{"MAXTOR", "XT-4170S", "B5A", BLIST_NOLUN},	/* locks up */
 	{"MAXTOR", "XT-8760S", "B7B", BLIST_NOLUN},	/* locks up */
 	{"MEDIAVIS", "RENO CD-ROMX2A", "2.03", BLIST_NOLUN},	/* responds to all lun */
+	{"MICROTEK", "ScanMakerIII", "2.30", BLIST_NOLUN},	/* responds to all lun */
 	{"NEC", "CD-ROM DRIVE:841", "1.0", BLIST_NOLUN},/* locks up */
 	{"PHILIPS", "PCA80SC", "V4-2", BLIST_NOLUN},	/* responds to all lun */
 	{"RODIME", "RO3000S", "2.33", BLIST_NOLUN},	/* locks up */
@@ -159,6 +160,7 @@
 	{"HP", "C3323-300", "4269", BLIST_NOTQ},
 	{"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN},
 	{"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"IBM", "2105", NULL, BLIST_RETRY_HWERROR},
 	{"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN},
 	{"IOMEGA", "Io20S         *F", NULL, BLIST_KEY},
 	{"INSITE", "Floptical   F*8I", NULL, BLIST_KEY},
@@ -192,6 +194,7 @@
 	{"SMSC", "USB 2 HS-CF", NULL, BLIST_SPARSELUN | BLIST_INQUIRY_36},
 	{"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN},
 	{"SONY", "TSL", NULL, BLIST_FORCELUN},		/* DDS3 & DDS4 autoloaders */
+	{"ST650211", "CF", NULL, BLIST_RETRY_HWERROR},
 	{"SUN", "T300", "*", BLIST_SPARSELUN},
 	{"SUN", "T4", "*", BLIST_SPARSELUN},
 	{"TEXEL", "CD-ROM", "1.06", BLIST_BORKEN},
@@ -201,6 +204,7 @@
 	{"WangDAT", "Model 2600", "01.7", BLIST_SELECT_NO_ATN},
 	{"WangDAT", "Model 3200", "02.2", BLIST_SELECT_NO_ATN},
 	{"WangDAT", "Model 1300", "02.4", BLIST_SELECT_NO_ATN},
+	{"WDC WD25", "00JB-00FUA0", NULL, BLIST_NOREPORTLUN},
 	{"XYRATEX", "RS", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
 	{"Zzyzx", "RocketStor 500S", NULL, BLIST_SPARSELUN},
 	{"Zzyzx", "RocketStor 2000", NULL, BLIST_SPARSELUN},
diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
--- a/drivers/scsi/scsi_error.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/scsi_error.c	2005-03-07 15:19:08 -08:00
@@ -31,6 +31,7 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
 #include <scsi/scsi_request.h>
+#include <scsi/scsi_devinfo.h>
 
 #include "scsi_priv.h"
 #include "scsi_logging.h"
@@ -350,10 +351,18 @@
 	case MEDIUM_ERROR:
 		return NEEDS_RETRY;
 
+	case HARDWARE_ERROR:
+		if (scsi_get_device_flags(scmd->device,
+					scmd->device->vendor,
+					scmd->device->model)
+				& BLIST_RETRY_HWERROR)
+			return NEEDS_RETRY;
+		else
+			return SUCCESS;
+
 	case ILLEGAL_REQUEST:
 	case BLANK_CHECK:
 	case DATA_PROTECT:
-	case HARDWARE_ERROR:
 	default:
 		return SUCCESS;
 	}
diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/scsi_lib.c	2005-03-07 15:19:08 -08:00
@@ -365,10 +365,11 @@
 {
 	struct Scsi_Host *shost = current_sdev->host;
 	struct scsi_device *sdev, *tmp;
+	struct scsi_target *starget = scsi_target(current_sdev);
 	unsigned long flags;
 
 	spin_lock_irqsave(shost->host_lock, flags);
-	scsi_target(current_sdev)->starget_sdev_user = NULL;
+	starget->starget_sdev_user = NULL;
 	spin_unlock_irqrestore(shost->host_lock, flags);
 
 	/*
@@ -380,10 +381,12 @@
 	blk_run_queue(current_sdev->request_queue);
 
 	spin_lock_irqsave(shost->host_lock, flags);
-	if (scsi_target(current_sdev)->starget_sdev_user)
+	if (starget->starget_sdev_user)
 		goto out;
-	list_for_each_entry_safe(sdev, tmp, &current_sdev->same_target_siblings,
+	list_for_each_entry_safe(sdev, tmp, &starget->devices,
 			same_target_siblings) {
+		if (sdev == current_sdev)
+			continue;
 		if (scsi_device_get(sdev))
 			continue;
 
diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
--- a/drivers/scsi/scsi_scan.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/scsi_scan.c	2005-03-07 15:19:08 -08:00
@@ -200,12 +200,12 @@
  * Return value:
  *     scsi_Device pointer, or NULL on failure.
  **/
-static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
-	       	uint channel, uint id, uint lun, void *hostdata)
+static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
+					   unsigned int lun, void *hostdata)
 {
 	struct scsi_device *sdev;
-	unsigned long flags;
 	int display_failure_msg = 1, ret;
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
 
 	sdev = kmalloc(sizeof(*sdev) + shost->transportt->device_size,
 		       GFP_ATOMIC);
@@ -217,9 +217,9 @@
 	sdev->model = scsi_null_device_strs;
 	sdev->rev = scsi_null_device_strs;
 	sdev->host = shost;
-	sdev->id = id;
+	sdev->id = starget->id;
 	sdev->lun = lun;
-	sdev->channel = channel;
+	sdev->channel = starget->channel;
 	sdev->sdev_state = SDEV_CREATED;
 	INIT_LIST_HEAD(&sdev->siblings);
 	INIT_LIST_HEAD(&sdev->same_target_siblings);
@@ -227,6 +227,9 @@
 	INIT_LIST_HEAD(&sdev->starved_entry);
 	spin_lock_init(&sdev->list_lock);
 
+	sdev->sdev_gendev.parent = get_device(&starget->dev);
+	sdev->sdev_target = starget;
+
 	/* usually NULL and set by ->slave_alloc instead */
 	sdev->hostdata = hostdata;
 
@@ -248,8 +251,12 @@
 
 	spin_lock_init(&sdev->sdev_lock);
 	sdev->request_queue = scsi_alloc_queue(sdev);
-	if (!sdev->request_queue)
-		goto out_free_dev;
+	if (!sdev->request_queue) {
+		/* release fn is set up in scsi_sysfs_device_initialise, so
+		 * have to free and put manually here */
+		put_device(&starget->dev);
+		goto out;
+	}
 
 	sdev->request_queue->queuedata = sdev;
 	scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
@@ -262,6 +269,8 @@
 			/*
 			 * if LLDD reports slave not present, don't clutter
 			 * console with alloc failure messages
+
+
 			 */
 			if (ret == -ENXIO)
 				display_failure_msg = 0;
@@ -269,32 +278,128 @@
 		}
 	}
 
-	/* NOTE: this target initialisation code depends critically on
-	 * lun scanning being sequential. */
-	if (scsi_sysfs_target_initialize(sdev))
-		goto out_remove_siblings;
-
 	return sdev;
 
-out_remove_siblings:
-	spin_lock_irqsave(shost->host_lock, flags);
-	list_del(&sdev->siblings);
-	list_del(&sdev->same_target_siblings);
-	spin_unlock_irqrestore(shost->host_lock, flags);
-
-	if (shost->hostt->slave_destroy)
-		shost->hostt->slave_destroy(sdev);
 out_device_destroy:
 	transport_destroy_device(&sdev->sdev_gendev);
 	scsi_free_queue(sdev->request_queue);
-out_free_dev:
-	kfree(sdev);
+	put_device(&sdev->sdev_gendev);
 out:
 	if (display_failure_msg)
 		printk(ALLOC_FAILURE_MSG, __FUNCTION__);
 	return NULL;
 }
 
+static void scsi_target_dev_release(struct device *dev)
+{
+	struct device *parent = dev->parent;
+	struct scsi_target *starget = to_scsi_target(dev);
+	kfree(starget);
+	put_device(parent);
+}
+
+int scsi_is_target_device(const struct device *dev)
+{
+	return dev->release == scsi_target_dev_release;
+}
+EXPORT_SYMBOL(scsi_is_target_device);
+
+static struct scsi_target *__scsi_find_target(struct device *parent,
+					      int channel, uint id)
+{
+	struct scsi_target *starget, *found_starget = NULL;
+	struct Scsi_Host *shost = dev_to_shost(parent);
+	/*
+	 * Search for an existing target for this sdev.
+	 */
+	list_for_each_entry(starget, &shost->__targets, siblings) {
+		if (starget->id == id &&
+		    starget->channel == channel) {
+			found_starget = starget;
+			break;
+		}
+	}
+	if (found_starget)
+		get_device(&found_starget->dev);
+
+	return found_starget;
+}
+
+static struct scsi_target *scsi_alloc_target(struct device *parent,
+					     int channel, uint id)
+{
+	struct Scsi_Host *shost = dev_to_shost(parent);
+	struct device *dev = NULL;
+	unsigned long flags;
+	const int size = sizeof(struct scsi_target)
+		+ shost->transportt->target_size;
+	struct scsi_target *starget = kmalloc(size, GFP_ATOMIC);
+	struct scsi_target *found_target;
+
+	if (!starget) {
+		printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
+		return NULL;
+	}
+	memset(starget, 0, size);
+	dev = &starget->dev;
+	device_initialize(dev);
+	starget->reap_ref = 1;
+	dev->parent = get_device(parent);
+	dev->release = scsi_target_dev_release;
+	sprintf(dev->bus_id, "target%d:%d:%d",
+		shost->host_no, channel, id);
+	starget->id = id;
+	starget->channel = channel;
+	INIT_LIST_HEAD(&starget->siblings);
+	INIT_LIST_HEAD(&starget->devices);
+	spin_lock_irqsave(shost->host_lock, flags);
+
+	found_target = __scsi_find_target(parent, channel, id);
+	if (found_target)
+		goto found;
+
+	list_add_tail(&starget->siblings, &shost->__targets);
+	spin_unlock_irqrestore(shost->host_lock, flags);
+	/* allocate and add */
+	transport_setup_device(&starget->dev);
+	device_add(&starget->dev);
+	transport_add_device(&starget->dev);
+	return starget;
+
+ found:
+	found_target->reap_ref++;
+	spin_unlock_irqrestore(shost->host_lock, flags);
+	put_device(parent);
+	kfree(starget);
+	return found_target;
+}
+
+/**
+ * scsi_target_reap - check to see if target is in use and destroy if not
+ *
+ * @starget: target to be checked
+ *
+ * This is used after removing a LUN or doing a last put of the target
+ * it checks atomically that nothing is using the target and removes
+ * it if so.
+ */
+void scsi_target_reap(struct scsi_target *starget)
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	unsigned long flags;
+	spin_lock_irqsave(shost->host_lock, flags);
+
+	if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
+		list_del_init(&starget->siblings);
+		spin_unlock_irqrestore(shost->host_lock, flags);
+		device_del(&starget->dev);
+		transport_unregister_device(&starget->dev);
+		put_device(&starget->dev);
+		return;
+	}
+	spin_unlock_irqrestore(shost->host_lock, flags);
+}
+
 /**
  * scsi_probe_lun - probe a single LUN using a SCSI INQUIRY
  * @sreq:	used to send the INQUIRY
@@ -637,6 +742,8 @@
 
 /**
  * scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it
+ * @starget:	pointer to target device structure
+ * @lun:	LUN of target device
  * @sdevscan:	probe the LUN corresponding to this Scsi_Device
  * @sdevnew:	store the value of any new Scsi_Device allocated
  * @bflagsp:	store bflags here if not NULL
@@ -651,45 +758,48 @@
  *         attached at the LUN
  *     SCSI_SCAN_LUN_PRESENT: a new Scsi_Device was allocated and initialized
  **/
-static int scsi_probe_and_add_lun(struct Scsi_Host *host,
-		uint channel, uint id, uint lun, int *bflagsp,
-		struct scsi_device **sdevp, int rescan, void *hostdata)
+static int scsi_probe_and_add_lun(struct scsi_target *starget,
+				  uint lun, int *bflagsp,
+				  struct scsi_device **sdevp, int rescan,
+				  void *hostdata)
 {
 	struct scsi_device *sdev;
 	struct scsi_request *sreq;
 	unsigned char *result;
 	int bflags, res = SCSI_SCAN_NO_RESPONSE;
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
 
 	/*
 	 * The rescan flag is used as an optimization, the first scan of a
 	 * host adapter calls into here with rescan == 0.
 	 */
 	if (rescan) {
-		sdev = scsi_device_lookup(host, channel, id, lun);
+		sdev = scsi_device_lookup_by_target(starget, lun);
 		if (sdev) {
 			SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
-				"scsi scan: device exists on <%d:%d:%d:%d>\n",
-				host->host_no, channel, id, lun));
+				"scsi scan: device exists on %s\n",
+				sdev->sdev_gendev.bus_id));
 			if (sdevp)
 				*sdevp = sdev;
+			else
+				scsi_device_put(sdev);
+
 			if (bflagsp)
 				*bflagsp = scsi_get_device_flags(sdev,
 								 sdev->vendor,
 								 sdev->model);
-			/* XXX: bandaid until callers do refcounting */
-			scsi_device_put(sdev);
 			return SCSI_SCAN_LUN_PRESENT;
 		}
 	}
 
-	sdev = scsi_alloc_sdev(host, channel, id, lun, hostdata);
+	sdev = scsi_alloc_sdev(starget, lun, hostdata);
 	if (!sdev)
 		goto out;
 	sreq = scsi_allocate_request(sdev, GFP_ATOMIC);
 	if (!sreq)
 		goto out_free_sdev;
 	result = kmalloc(256, GFP_ATOMIC |
-			(host->unchecked_isa_dma) ? __GFP_DMA : 0);
+			(shost->unchecked_isa_dma) ? __GFP_DMA : 0);
 	if (!result)
 		goto out_free_sreq;
 
@@ -734,8 +844,10 @@
 	scsi_release_request(sreq);
  out_free_sdev:
 	if (res == SCSI_SCAN_LUN_PRESENT) {
-		if (sdevp)
+		if (sdevp) {
+			scsi_device_get(sdev);
 			*sdevp = sdev;
+		}
 	} else {
 		if (sdev->host->hostt->slave_destroy)
 			sdev->host->hostt->slave_destroy(sdev);
@@ -748,7 +860,7 @@
 
 /**
  * scsi_sequential_lun_scan - sequentially scan a SCSI target
- * @sdevscan:	scan the host, channel, and id of this Scsi_Device
+ * @starget:	pointer to target structure to scan
  * @bflags:	black/white list flag for LUN 0
  * @lun0_res:	result of scanning LUN 0
  *
@@ -759,14 +871,15 @@
  *
  *     Modifies sdevscan->lun.
  **/
-static void scsi_sequential_lun_scan(struct Scsi_Host *shost, uint channel,
-		uint id, int bflags, int lun0_res, int scsi_level, int rescan)
+static void scsi_sequential_lun_scan(struct scsi_target *starget,
+				     int bflags, int lun0_res, int scsi_level,
+				     int rescan)
 {
 	unsigned int sparse_lun, lun, max_dev_lun;
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
 
 	SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: Sequential scan of"
-			" host %d channel %d id %d\n", shost->host_no,
-			channel, id));
+				    "%s\n", starget->dev.bus_id));
 
 	max_dev_lun = min(max_scsi_luns, shost->max_lun);
 	/*
@@ -828,8 +941,8 @@
 	 * sparse_lun.
 	 */
 	for (lun = 1; lun < max_dev_lun; ++lun)
-		if ((scsi_probe_and_add_lun(shost, channel, id, lun,
-		      NULL, NULL, rescan, NULL) != SCSI_SCAN_LUN_PRESENT) &&
+		if ((scsi_probe_and_add_lun(starget, lun, NULL, NULL, rescan,
+					    NULL) != SCSI_SCAN_LUN_PRESENT) &&
 		    !sparse_lun)
 			return;
 }
@@ -893,6 +1006,7 @@
 	struct scsi_request *sreq;
 	u8 *data;
 	struct scsi_sense_hdr sshdr;
+	struct scsi_target *starget = scsi_target(sdev);
 
 	/*
 	 * Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set.
@@ -1043,8 +1157,8 @@
 		} else {
 			int res;
 
-			res = scsi_probe_and_add_lun(sdev->host, sdev->channel,
-				sdev->id, lun, NULL, NULL, rescan, NULL);
+			res = scsi_probe_and_add_lun(starget,
+				lun, NULL, NULL, rescan, NULL);
 			if (res == SCSI_SCAN_NO_RESPONSE) {
 				/*
 				 * Got some results, but now none, abort.
@@ -1071,17 +1185,23 @@
 }
 
 struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
-		uint id, uint lun, void *hostdata)
+				      uint id, uint lun, void *hostdata)
 {
 	struct scsi_device *sdev;
+	struct device *parent = &shost->shost_gendev;
 	int res;
+	struct scsi_target *starget = scsi_alloc_target(parent, channel, id);
+
+	if (!starget)
+		return ERR_PTR(-ENOMEM);
 
 	down(&shost->scan_mutex);
-	res = scsi_probe_and_add_lun(shost, channel, id, lun, NULL,
-				     &sdev, 1, hostdata);
+	res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
 	if (res != SCSI_SCAN_LUN_PRESENT)
 		sdev = ERR_PTR(-ENODEV);
 	up(&shost->scan_mutex);
+	scsi_target_reap(starget);
+	put_device(&starget->dev);
 
 	return sdev;
 }
@@ -1122,12 +1242,14 @@
  *     First try a REPORT LUN scan, if that does not scan the target, do a
  *     sequential scan of LUNs on the target id.
  **/
-static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel,
-			     unsigned int id, unsigned int lun, int rescan)
+void scsi_scan_target(struct device *parent, unsigned int channel,
+		      unsigned int id, unsigned int lun, int rescan)
 {
+	struct Scsi_Host *shost = dev_to_shost(parent);
 	int bflags = 0;
 	int res;
-	struct scsi_device *sdev;
+	struct scsi_device *sdev = NULL;
+	struct scsi_target *starget;
 
 	if (shost->this_id == id)
 		/*
@@ -1135,28 +1257,33 @@
 		 */
 		return;
 
+
+	starget = scsi_alloc_target(parent, channel, id);
+
+	if (!starget)
+		return;
+
+	get_device(&starget->dev);
 	if (lun != SCAN_WILD_CARD) {
 		/*
 		 * Scan for a specific host/chan/id/lun.
 		 */
-		scsi_probe_and_add_lun(shost, channel, id, lun, NULL, NULL,
-				       rescan, NULL);
-		return;
+		scsi_probe_and_add_lun(starget, lun, NULL, NULL, rescan, NULL);
+		goto out_reap;
 	}
 
 	/*
 	 * Scan LUN 0, if there is some response, scan further. Ideally, we
 	 * would not configure LUN 0 until all LUNs are scanned.
 	 */
-	res = scsi_probe_and_add_lun(shost, channel, id, 0, &bflags, &sdev,
-				     rescan, NULL);
+	res = scsi_probe_and_add_lun(starget, 0, &bflags, &sdev, rescan, NULL);
 	if (res == SCSI_SCAN_LUN_PRESENT) {
 		if (scsi_report_lun_scan(sdev, bflags, rescan) != 0)
 			/*
 			 * The REPORT LUN did not scan the target,
 			 * do a sequential scan.
 			 */
-			scsi_sequential_lun_scan(shost, channel, id, bflags,
+			scsi_sequential_lun_scan(starget, bflags,
 				       	res, sdev->scsi_level, rescan);
 	} else if (res == SCSI_SCAN_TARGET_PRESENT) {
 		/*
@@ -1165,10 +1292,20 @@
 		 * sequential lun scan with a bflags of SPARSELUN and
 		 * a default scsi level of SCSI_2
 		 */
-		scsi_sequential_lun_scan(shost, channel, id, BLIST_SPARSELUN,
+		scsi_sequential_lun_scan(starget, BLIST_SPARSELUN,
 				SCSI_SCAN_TARGET_PRESENT, SCSI_2, rescan);
 	}
+	if (sdev)
+		scsi_device_put(sdev);
+
+ out_reap:
+	/* now determine if the target has any children at all
+	 * and if not, nuke it */
+	scsi_target_reap(starget);
+
+	put_device(&starget->dev);
 }
+EXPORT_SYMBOL(scsi_scan_target);
 
 static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel,
 			      unsigned int id, unsigned int lun, int rescan)
@@ -1193,10 +1330,10 @@
 				order_id = shost->max_id - id - 1;
 			else
 				order_id = id;
-			scsi_scan_target(shost, channel, order_id, lun, rescan);
+			scsi_scan_target(&shost->shost_gendev, channel, order_id, lun, rescan);
 		}
 	else
-		scsi_scan_target(shost, channel, id, lun, rescan);
+		scsi_scan_target(&shost->shost_gendev, channel, id, lun, rescan);
 }
 
 int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
@@ -1247,7 +1384,7 @@
 
 void scsi_forget_host(struct Scsi_Host *shost)
 {
-	struct scsi_device *sdev, *tmp;
+	struct scsi_target *starget, *tmp;
 	unsigned long flags;
 
 	/*
@@ -1260,9 +1397,9 @@
 	 * after that we don't look at sdev anymore.
 	 */
 	spin_lock_irqsave(shost->host_lock, flags);
-	list_for_each_entry_safe(sdev, tmp, &shost->__devices, siblings) {
+	list_for_each_entry_safe(starget, tmp, &shost->__targets, siblings) {
 		spin_unlock_irqrestore(shost->host_lock, flags);
-		scsi_remove_device(sdev);
+		scsi_remove_target(starget);
 		spin_lock_irqsave(shost->host_lock, flags);
 	}
 	spin_unlock_irqrestore(shost->host_lock, flags);
@@ -1291,11 +1428,18 @@
 struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
 {
 	struct scsi_device *sdev;
+	struct scsi_target *starget;
+
+	starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id);
+	if (!starget)
+		return NULL;
 
-	sdev = scsi_alloc_sdev(shost, 0, shost->this_id, 0, NULL);
+	sdev = scsi_alloc_sdev(starget, 0, NULL);
 	if (sdev) {
+		sdev->sdev_gendev.parent = get_device(&starget->dev);
 		sdev->borken = 0;
 	}
+	put_device(&starget->dev);
 	return sdev;
 }
 EXPORT_SYMBOL(scsi_get_host_dev);
diff -Nru a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
--- a/drivers/scsi/scsi_sysfs.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/scsi_sysfs.c	2005-03-07 15:19:08 -08:00
@@ -154,33 +154,25 @@
 {
 	struct scsi_device *sdev;
 	struct device *parent;
+	struct scsi_target *starget;
 	unsigned long flags;
-	int delete;
 
 	parent = dev->parent;
 	sdev = to_scsi_device(dev);
+	starget = to_scsi_target(parent);
 
 	spin_lock_irqsave(sdev->host->host_lock, flags);
-	/* If we're the last LUN on the target, destroy the target */
-	delete = list_empty(&sdev->same_target_siblings);
+	starget->reap_ref++;
 	list_del(&sdev->siblings);
 	list_del(&sdev->same_target_siblings);
 	list_del(&sdev->starved_entry);
 	spin_unlock_irqrestore(sdev->host->host_lock, flags);
 
-	if (delete) {
-		struct scsi_target *starget = to_scsi_target(parent);
-		if (!starget->create) {
-			transport_remove_device(&starget->dev);
-			device_del(parent);
-		}
-		transport_destroy_device(&starget->dev);
-
-		put_device(parent);
-	}
 	if (sdev->request_queue)
 		scsi_free_queue(sdev->request_queue);
 
+	scsi_target_reap(scsi_target(sdev));
+
 	kfree(sdev->inquiry);
 	kfree(sdev);
 
@@ -408,6 +400,28 @@
 
 static DEVICE_ATTR(queue_type, S_IRUGO, show_queue_type_field, NULL);
 
+static ssize_t
+show_iostat_counterbits(struct device *dev, char *buf)
+{
+	return snprintf(buf, 20, "%d\n", (int)sizeof(atomic_t) * 8);
+}
+
+static DEVICE_ATTR(iocounterbits, S_IRUGO, show_iostat_counterbits, NULL);
+
+#define show_sdev_iostat(field)						\
+static ssize_t								\
+show_iostat_##field(struct device *dev, char *buf)			\
+{									\
+	struct scsi_device *sdev = to_scsi_device(dev);			\
+	unsigned long long count = atomic_read(&sdev->field);		\
+	return snprintf(buf, 20, "0x%llx\n", count);			\
+}									\
+static DEVICE_ATTR(field, S_IRUGO, show_iostat_##field, NULL)
+
+show_sdev_iostat(iorequest_cnt);
+show_sdev_iostat(iodone_cnt);
+show_sdev_iostat(ioerr_cnt);
+
 
 /* Default template for device attributes.  May NOT be modified */
 static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
@@ -423,6 +437,10 @@
 	&dev_attr_delete,
 	&dev_attr_state,
 	&dev_attr_timeout,
+	&dev_attr_iocounterbits,
+	&dev_attr_iorequest_cnt,
+	&dev_attr_iodone_cnt,
+	&dev_attr_ioerr_cnt,
 	NULL
 };
 
@@ -534,14 +552,6 @@
 	return device_create_file(dev, attr);
 }
 
-static void scsi_target_dev_release(struct device *dev)
-{
-	struct scsi_target *starget = to_scsi_target(dev);
-	struct device *parent = dev->parent;
-	kfree(starget);
-	put_device(parent);
-}
-
 /**
  * scsi_sysfs_add_sdev - add scsi device to sysfs
  * @sdev:	scsi_device to add
@@ -551,25 +561,16 @@
  **/
 int scsi_sysfs_add_sdev(struct scsi_device *sdev)
 {
-	struct scsi_target *starget = sdev->sdev_target;
 	struct Scsi_Host *shost = sdev->host;
-	int error, i, create;
+	struct scsi_target *starget = scsi_target(sdev);
+	int error, i;
 	unsigned long flags;
 
 	spin_lock_irqsave(shost->host_lock, flags);
-	create = starget->create;
-	starget->create = 0;
+	list_add_tail(&sdev->same_target_siblings, &starget->devices);
+	list_add_tail(&sdev->siblings, &shost->__devices);
 	spin_unlock_irqrestore(shost->host_lock, flags);
 
-	if (create) {
-		error = device_add(&starget->dev);
-		if (error) {
-			printk(KERN_ERR "Target device_add failed\n");
-			return error;
-		}
-		transport_add_device(&starget->dev);
-	}
-
 	if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0)
 		return error;
 
@@ -617,7 +618,6 @@
  out:
 	return error;
 
-	class_device_del(&sdev->sdev_classdev);
  clean_device:
 	scsi_device_set_state(sdev, SDEV_CANCEL);
 
@@ -647,12 +647,40 @@
 		sdev->host->hostt->slave_destroy(sdev);
 	transport_unregister_device(&sdev->sdev_gendev);
 	put_device(&sdev->sdev_gendev);
-
 out:
 	up(&shost->scan_mutex);
 }
 EXPORT_SYMBOL(scsi_remove_device);
 
+/**
+ * scsi_remove_target - try to remove a target and all its devices
+ * @starget: the target to remove
+ *
+ * Note: This is slightly racy.  It is possible that if the user
+ * requests the addition of another device then the target won't be
+ * removed.
+ */
+void scsi_remove_target(struct scsi_target *starget)
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	unsigned long flags;
+	struct scsi_device *sdev, *tmp;
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	starget->reap_ref++;
+	list_for_each_entry_safe(sdev, tmp, &shost->__devices, siblings) {
+		if (sdev->channel != starget->channel ||
+		    sdev->id != starget->id)
+			continue;
+		spin_unlock_irqrestore(shost->host_lock, flags);
+		scsi_remove_device(sdev);
+		spin_lock_irqsave(shost->host_lock, flags);
+	}
+	spin_unlock_irqrestore(shost->host_lock, flags);
+	scsi_target_reap(starget);
+}
+EXPORT_SYMBOL(scsi_remove_target);
+
 int scsi_register_driver(struct device_driver *drv)
 {
 	drv->bus = &scsi_bus_type;
@@ -754,7 +782,7 @@
 	snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE,
 		 "%d:%d:%d:%d", sdev->host->host_no,
 		 sdev->channel, sdev->id, sdev->lun);
-
+	sdev->scsi_level = SCSI_2;
 	transport_setup_device(&sdev->sdev_gendev);
 }
 
@@ -763,73 +791,6 @@
 	return dev->release == scsi_device_dev_release;
 }
 EXPORT_SYMBOL(scsi_is_sdev_device);
-
-int scsi_sysfs_target_initialize(struct scsi_device *sdev)
-{
-	struct scsi_target *starget = NULL;
-	struct Scsi_Host *shost = sdev->host;
-	struct scsi_device *device;
-	struct device *dev = NULL;
-	unsigned long flags;
-	int create = 0;
-
-	spin_lock_irqsave(shost->host_lock, flags);
-	/*
-	 * Search for an existing target for this sdev.
-	 */
-	list_for_each_entry(device, &shost->__devices, siblings) {
-		if (device->id == sdev->id &&
-		    device->channel == sdev->channel) {
-			list_add_tail(&sdev->same_target_siblings,
-				      &device->same_target_siblings);
-			sdev->scsi_level = device->scsi_level;
-			starget = device->sdev_target;
-			break;
-		}
-	}
-			
-	if (!starget) {
-		const int size = sizeof(*starget) +
-			shost->transportt->target_size;
-		starget = kmalloc(size, GFP_ATOMIC);
-		if (!starget) {
-			printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
-			spin_unlock_irqrestore(shost->host_lock,
-					       flags);
-			return -ENOMEM;
-		}
-		memset(starget, 0, size);
-		dev = &starget->dev;
-		device_initialize(dev);
-		dev->parent = get_device(&shost->shost_gendev);
-		dev->release = scsi_target_dev_release;
-		sprintf(dev->bus_id, "target%d:%d:%d",
-			shost->host_no, sdev->channel, sdev->id);
-		starget->id = sdev->id;
-		starget->channel = sdev->channel;
-		create = starget->create = 1;
-		/*
-		 * If there wasn't another lun already configured at
-		 * this target, then default this device to SCSI_2
-		 * until we know better
-		 */
-		sdev->scsi_level = SCSI_2;
-	}
-	get_device(&starget->dev);
-	sdev->sdev_gendev.parent = &starget->dev;
-	sdev->sdev_target = starget;
-	list_add_tail(&sdev->siblings, &shost->__devices);
-	spin_unlock_irqrestore(shost->host_lock, flags);
-	if (create)
-		transport_setup_device(&starget->dev);
-	return 0;
-}
-
-int scsi_is_target_device(const struct device *dev)
-{
-	return dev->release == scsi_target_dev_release;
-}
-EXPORT_SYMBOL(scsi_is_target_device);
 
 /* A blank transport template that is used in drivers that don't
  * yet implement Transport Attributes */
diff -Nru a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
--- a/drivers/scsi/scsi_transport_fc.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/scsi_transport_fc.c	2005-03-07 15:19:08 -08:00
@@ -254,16 +254,8 @@
 		sizeof(fc_host_symbolic_name(shost)));
 	fc_host_supported_speeds(shost) = FC_PORTSPEED_UNKNOWN;
 	fc_host_maxframe_size(shost) = -1;
-	memset(fc_host_hardware_version(shost), 0,
-		sizeof(fc_host_hardware_version(shost)));
-	memset(fc_host_firmware_version(shost), 0,
-		sizeof(fc_host_firmware_version(shost)));
 	memset(fc_host_serial_number(shost), 0,
 		sizeof(fc_host_serial_number(shost)));
-	memset(fc_host_opt_rom_version(shost), 0,
-		sizeof(fc_host_opt_rom_version(shost)));
-	memset(fc_host_driver_version(shost), 0,
-		sizeof(fc_host_driver_version(shost)));
 
 	fc_host_port_id(shost) = -1;
 	fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
@@ -539,11 +531,7 @@
 fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
 fc_private_host_rd_attr(symbolic_name, "%s\n", (FC_SYMBOLIC_NAME_SIZE +1));
 fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20);
-fc_private_host_rd_attr(hardware_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
-fc_private_host_rd_attr(firmware_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
 fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
-fc_private_host_rd_attr(opt_rom_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
-fc_private_host_rd_attr(driver_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
 
 
 /* Dynamic Host Attributes */
@@ -817,11 +805,7 @@
 	SETUP_HOST_ATTRIBUTE_RD(symbolic_name);
 	SETUP_HOST_ATTRIBUTE_RD(supported_speeds);
 	SETUP_HOST_ATTRIBUTE_RD(maxframe_size);
-	SETUP_HOST_ATTRIBUTE_RD(hardware_version);
-	SETUP_HOST_ATTRIBUTE_RD(firmware_version);
 	SETUP_HOST_ATTRIBUTE_RD(serial_number);
-	SETUP_HOST_ATTRIBUTE_RD(opt_rom_version);
-	SETUP_HOST_ATTRIBUTE_RD(driver_version);
 
 	SETUP_HOST_ATTRIBUTE_RD(port_id);
 	SETUP_HOST_ATTRIBUTE_RD(port_type);
diff -Nru a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
--- a/drivers/scsi/scsi_transport_spi.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/scsi_transport_spi.c	2005-03-07 15:19:08 -08:00
@@ -18,15 +18,11 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <linux/module.h>
+#include <linux/ctype.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/workqueue.h>
-#include <asm/scatterlist.h>
-#include <asm/io.h>
+#include <asm/semaphore.h>
 #include <scsi/scsi.h>
 #include "scsi_priv.h"
 #include <scsi/scsi_device.h>
@@ -63,27 +59,47 @@
 
 #define to_spi_internal(tmpl)	container_of(tmpl, struct spi_internal, t)
 
-static const char *const ppr_to_ns[] = {
+static const int ppr_to_ps[] = {
 	/* The PPR values 0-6 are reserved, fill them in when
 	 * the committee defines them */
-	NULL,			/* 0x00 */
-	NULL,			/* 0x01 */
-	NULL,			/* 0x02 */
-	NULL,			/* 0x03 */
-	NULL,			/* 0x04 */
-	NULL,			/* 0x05 */
-	NULL,			/* 0x06 */
-	"3.125",		/* 0x07 */
-	"6.25",			/* 0x08 */
-	"12.5",			/* 0x09 */
-	"25",			/* 0x0a */
-	"30.3",			/* 0x0b */
-	"50",			/* 0x0c */
+	-1,			/* 0x00 */
+	-1,			/* 0x01 */
+	-1,			/* 0x02 */
+	-1,			/* 0x03 */
+	-1,			/* 0x04 */
+	-1,			/* 0x05 */
+	-1,			/* 0x06 */
+	 3125,			/* 0x07 */
+	 6250,			/* 0x08 */
+	12500,			/* 0x09 */
+	25000,			/* 0x0a */
+	30300,			/* 0x0b */
+	50000,			/* 0x0c */
 };
 /* The PPR values at which you calculate the period in ns by multiplying
  * by 4 */
 #define SPI_STATIC_PPR	0x0c
 
+static int sprint_frac(char *dest, int value, int denom)
+{
+	int frac = value % denom;
+	int result = sprintf(dest, "%d", value / denom);
+
+	if (frac == 0)
+		return result;
+	dest[result++] = '.';
+
+	do {
+		denom /= 10;
+		sprintf(dest + result, "%d", frac / denom);
+		result++;
+		frac %= denom;
+	} while (frac);
+
+	dest[result++] = '\0';
+	return result;
+}
+
 static struct {
 	enum spi_signal_type	value;
 	char			*name;
@@ -261,7 +277,7 @@
 	struct scsi_target *starget = transport_class_to_starget(cdev);
 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
 	struct spi_transport_attrs *tp;
-	const char *str;
+	int len, picosec;
 	struct spi_internal *i = to_spi_internal(shost->transportt);
 
 	tp = (struct spi_transport_attrs *)&starget->starget_data;
@@ -269,22 +285,20 @@
 	if (i->f->get_period)
 		i->f->get_period(starget);
 
-	switch(tp->period) {
-
-	case 0x07 ... SPI_STATIC_PPR:
-		str = ppr_to_ns[tp->period];
-		if(!str)
-			str = "reserved";
-		break;
-
-
-	case (SPI_STATIC_PPR+1) ... 0xff:
-		return sprintf(buf, "%d\n", tp->period * 4);
-
-	default:
-		str = "unknown";
+	if (tp->period < 0 || tp->period > 0xff) {
+		picosec = -1;
+	} else if (tp->period <= SPI_STATIC_PPR) {
+		picosec = ppr_to_ps[tp->period];
+	} else {
+		picosec = tp->period * 4000;
 	}
-	return sprintf(buf, "%s\n", str);
+
+	if (picosec == -1)
+		return sprintf(buf, "reserved");
+	len = sprint_frac(buf, picosec, 1000);
+	buf[len++] = '\n';
+	buf[len] = '\0';
+	return len;
 }
 
 static ssize_t
@@ -294,34 +308,30 @@
 	struct scsi_target *starget = transport_class_to_starget(cdev);
 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
 	struct spi_internal *i = to_spi_internal(shost->transportt);
-	int j, period = -1;
+	int j, picosec, period = -1;
+	char *endp;
 
-	for (j = 0; j < SPI_STATIC_PPR; j++) {
-		int len;
-
-		if(ppr_to_ns[j] == NULL)
-			continue;
-
-		len = strlen(ppr_to_ns[j]);
-
-		if(strncmp(ppr_to_ns[j], buf, len) != 0)
-			continue;
+	picosec = simple_strtoul(buf, &endp, 10) * 1000;
+	if (*endp == '.') {
+		int mult = 100;
+		do {
+			endp++;
+			if (!isdigit(*endp))
+				break;
+			picosec += (*endp - '0') * mult;
+			mult /= 10;
+		} while (mult > 0);
+	}
 
-		if(buf[len] != '\n')
+	for (j = 0; j <= SPI_STATIC_PPR; j++) {
+		if (ppr_to_ps[j] < picosec)
 			continue;
-		
 		period = j;
 		break;
 	}
 
-	if (period == -1) {
-		int val = simple_strtoul(buf, NULL, 0);
-
-
-		/* Should probably check limits here, but this
-		 * gets reasonably close to OK for most things */
-		period = val/4;
-	}
+	if (period == -1)
+		period = picosec / 4000;
 
 	if (period > 0xff)
 		period = 0xff;
@@ -330,7 +340,7 @@
 
 	return count;
 }
-	
+
 static CLASS_DEVICE_ATTR(period, S_IRUGO | S_IWUSR, 
 			 show_spi_transport_period,
 			 store_spi_transport_period);
@@ -794,6 +804,61 @@
 	schedule_work(&wqw->work);
 }
 EXPORT_SYMBOL(spi_schedule_dv_device);
+
+/**
+ * spi_display_xfer_agreement - Print the current target transfer agreement
+ * @starget: The target for which to display the agreement
+ *
+ * Each SPI port is required to maintain a transfer agreement for each
+ * other port on the bus.  This function prints a one-line summary of
+ * the current agreement; more detailed information is available in sysfs.
+ */
+void spi_display_xfer_agreement(struct scsi_target *starget)
+{
+	struct spi_transport_attrs *tp;
+	tp = (struct spi_transport_attrs *)&starget->starget_data;
+
+	if (tp->offset > 0 && tp->period > 0) {
+		unsigned int picosec, kb100;
+		char *scsi = "FAST-?";
+		char tmp[8];
+
+		if (tp->period <= SPI_STATIC_PPR) {
+			picosec = ppr_to_ps[tp->period];
+			switch (tp->period) {
+				case  7: scsi = "FAST-320"; break;
+				case  8: scsi = "FAST-160"; break;
+				case  9: scsi = "FAST-80"; break;
+				case 10:
+				case 11: scsi = "FAST-40"; break;
+				case 12: scsi = "FAST-20"; break;
+			}
+		} else {
+			picosec = tp->period * 4000;
+			if (tp->period < 25)
+				scsi = "FAST-20";
+			else if (tp->period < 50)
+				scsi = "FAST-10";
+			else
+				scsi = "FAST-5";
+		}
+
+		kb100 = (10000000 + picosec / 2) / picosec;
+		if (tp->width)
+			kb100 *= 2;
+		sprint_frac(tmp, picosec, 1000);
+
+		dev_info(&starget->dev,
+			"%s %sSCSI %d.%d MB/s %s%s%s (%s ns, offset %d)\n",
+			scsi, tp->width ? "WIDE " : "", kb100/10, kb100 % 10,
+			tp->dt ? "DT" : "ST", tp->iu ? " IU" : "",
+			tp->qas  ? " QAS" : "", tmp, tp->offset);
+	} else {
+		dev_info(&starget->dev, "%sasynchronous.\n",
+				tp->width ? "wide " : "");
+	}
+}
+EXPORT_SYMBOL(spi_display_xfer_agreement);
 
 #define SETUP_ATTRIBUTE(field)						\
 	i->private_attrs[count] = class_device_attr_##field;		\
diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c
--- a/drivers/scsi/sd.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/sd.c	2005-03-07 15:19:08 -08:00
@@ -741,11 +741,50 @@
 	sd_revalidate_disk(sdkp->disk);
 }
 
+
+#ifdef CONFIG_COMPAT
+/* 
+ * This gets directly called from VFS. When the ioctl 
+ * is not recognized we go back to the other translation paths. 
+ */
+static long sd_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct block_device *bdev = file->f_dentry->d_inode->i_bdev;
+	struct gendisk *disk = bdev->bd_disk;
+	struct scsi_device *sdev = scsi_disk(disk)->device;
+
+	/*
+	 * If we are in the middle of error recovery, don't let anyone
+	 * else try and use this device.  Also, if error recovery fails, it
+	 * may try and take the device offline, in which case all further
+	 * access to the device is prohibited.
+	 */
+	if (!scsi_block_when_processing_errors(sdev))
+		return -ENODEV;
+	       
+	if (sdev->host->hostt->compat_ioctl) {
+		int ret;
+
+		ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg);
+
+		return ret;
+	}
+
+	/* 
+	 * Let the static ioctl translation table take care of it.
+	 */
+	return -ENOIOCTLCMD; 
+}
+#endif
+
 static struct block_device_operations sd_fops = {
 	.owner			= THIS_MODULE,
 	.open			= sd_open,
 	.release		= sd_release,
 	.ioctl			= sd_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl		= sd_compat_ioctl,
+#endif
 	.media_changed		= sd_media_changed,
 	.revalidate_disk	= sd_revalidate_disk,
 };
diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c
--- a/drivers/scsi/sg.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/sg.c	2005-03-07 15:19:08 -08:00
@@ -1037,6 +1037,29 @@
 	}
 }
 
+#ifdef CONFIG_COMPAT
+static long sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
+{
+	Sg_device *sdp;
+	Sg_fd *sfp;
+	struct scsi_device *sdev;
+
+	if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
+		return -ENXIO;
+
+	sdev = sdp->device;
+	if (sdev->host->hostt->compat_ioctl) { 
+		int ret;
+
+		ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
+
+		return ret;
+	}
+	
+	return -ENOIOCTLCMD;
+}
+#endif
+
 static unsigned int
 sg_poll(struct file *filp, poll_table * wait)
 {
@@ -1346,6 +1369,9 @@
 	.write = sg_write,
 	.poll = sg_poll,
 	.ioctl = sg_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = sg_compat_ioctl,
+#endif
 	.open = sg_open,
 	.mmap = sg_mmap,
 	.release = sg_release,
diff -Nru a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c
--- a/drivers/scsi/sim710.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/sim710.c	2005-03-07 15:19:08 -08:00
@@ -47,7 +47,7 @@
 #define MAX_SLOTS 8
 static __u8 __initdata id_array[MAX_SLOTS] = { [0 ... MAX_SLOTS-1] = 7 };
 
-char *sim710;		/* command line passed by insmod */
+static char *sim710;		/* command line passed by insmod */
 
 MODULE_AUTHOR("Richard Hirst");
 MODULE_DESCRIPTION("Simple NCR53C710 driver");
@@ -61,7 +61,7 @@
 #define ARG_SEP ','
 #endif
 
-__init int
+static __init int
 param_setup(char *str)
 {
 	char *pos = str, *next;
@@ -314,7 +314,7 @@
 				   differential, scsi_id);
 }
 
-struct eisa_driver sim710_eisa_driver = {
+static struct eisa_driver sim710_eisa_driver = {
 	.id_table		= sim710_eisa_ids,
 	.driver = {
 		.name		= "sim710",
diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c
--- a/drivers/scsi/sr.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/sr.c	2005-03-07 15:19:08 -08:00
@@ -518,6 +518,10 @@
 	.release	= sr_block_release,
 	.ioctl		= sr_block_ioctl,
 	.media_changed	= sr_block_media_changed,
+	/* 
+	 * No compat_ioctl for now because sr_block_ioctl never
+	 * seems to pass arbitary ioctls down to host drivers.
+	 */
 };
 
 static int sr_open(struct cdrom_device_info *cdi, int purpose)
diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c
--- a/drivers/scsi/st.c	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/st.c	2005-03-07 15:19:08 -08:00
@@ -9,7 +9,7 @@
    Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky,
    Michael Schaefer, J"org Weule, and Eric Youngdale.
 
-   Copyright 1992 - 2004 Kai Makisara
+   Copyright 1992 - 2005 Kai Makisara
    email Kai.Makisara@kolumbus.fi
 
    Some small formal changes - aeb, 950809
@@ -17,7 +17,7 @@
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
  */
 
-static char *verstr = "20041025";
+static char *verstr = "20050213";
 
 #include <linux/module.h>
 
@@ -144,7 +144,7 @@
 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
 #endif
 
-DEB( static int debugging = DEBUG; )
+static int debugging = DEBUG;
 
 #define MAX_RETRIES 0
 #define MAX_WRITE_RETRIES 0
@@ -262,25 +262,57 @@
 	return tape->disk->disk_name;
 }
 
+
+static void st_analyze_sense(struct scsi_request *SRpnt, struct st_cmdstatus *s)
+{
+	const u8 *ucp;
+	const u8 *sense = SRpnt->sr_sense_buffer;
+
+	s->have_sense = scsi_request_normalize_sense(SRpnt, &s->sense_hdr);
+
+	if (s->have_sense) {
+		s->remainder_valid =
+			scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
+		switch (sense[0] & 0x7f) {
+		case 0x71:
+			s->deferred = 1;
+		case 0x70:
+			s->fixed_format = 1;
+			s->flags = sense[2] & 0xe0;
+			break;
+		case 0x73:
+			s->deferred = 1;
+		case 0x72:
+			s->fixed_format = 0;
+			ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
+			s->flags = ucp ? (ucp[3] & 0xe0) : 0;
+			break;
+		default:
+			s->flags = 0;
+		}
+	}
+}
+
+
 /* Convert the result to success code */
 static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
 {
 	int result = SRpnt->sr_result;
-	unsigned char *sense = SRpnt->sr_sense_buffer, scode;
+	u8 scode;
 	DEB(const char *stp;)
 	char *name = tape_name(STp);
+	struct st_cmdstatus *cmdstatp;
 
-	if (!result) {
-		sense[0] = 0;	/* We don't have sense data if this byte is zero */
+	if (!result)
 		return 0;
-	}
 
-	if ((driver_byte(result) & DRIVER_MASK) == DRIVER_SENSE)
-		scode = sense[2] & 0x0f;
-	else {
-		sense[0] = 0;
+		cmdstatp = &STp->buffer->cmdstat;
+	st_analyze_sense(STp->buffer->last_SRpnt, cmdstatp);
+
+	if (cmdstatp->have_sense)
+		scode = STp->buffer->cmdstat.sense_hdr.sense_key;
+	else
 		scode = 0;
-	}
 
         DEB(
         if (debugging) {
@@ -289,29 +321,30 @@
 		       SRpnt->sr_cmnd[0], SRpnt->sr_cmnd[1], SRpnt->sr_cmnd[2],
 		       SRpnt->sr_cmnd[3], SRpnt->sr_cmnd[4], SRpnt->sr_cmnd[5],
 		       SRpnt->sr_bufflen);
-		if (driver_byte(result) & DRIVER_SENSE)
-			scsi_print_req_sense("st", SRpnt);
-	} else ) /* end DEB */
-		if (!(driver_byte(result) & DRIVER_SENSE) ||
-		    ((sense[0] & 0x70) == 0x70 &&
-		     scode != NO_SENSE &&
-		     scode != RECOVERED_ERROR &&
-                     /* scode != UNIT_ATTENTION && */
-		     scode != BLANK_CHECK &&
-		     scode != VOLUME_OVERFLOW &&
-		     SRpnt->sr_cmnd[0] != MODE_SENSE &&
-		     SRpnt->sr_cmnd[0] != TEST_UNIT_READY)) {	/* Abnormal conditions for tape */
-		if (driver_byte(result) & DRIVER_SENSE) {
-			printk(KERN_WARNING "%s: Error with sense data: ", name);
+		if (cmdstatp->have_sense)
 			scsi_print_req_sense("st", SRpnt);
-		} else
+	} ) /* end DEB */
+	if (!debugging) { /* Abnormal conditions for tape */
+		if (!cmdstatp->have_sense)
 			printk(KERN_WARNING
 			       "%s: Error %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
 			       name, result, suggestion(result),
-                               driver_byte(result) & DRIVER_MASK, host_byte(result));
+			       driver_byte(result) & DRIVER_MASK, host_byte(result));
+		else if (cmdstatp->have_sense &&
+			 scode != NO_SENSE &&
+			 scode != RECOVERED_ERROR &&
+			 /* scode != UNIT_ATTENTION && */
+			 scode != BLANK_CHECK &&
+			 scode != VOLUME_OVERFLOW &&
+			 SRpnt->sr_cmnd[0] != MODE_SENSE &&
+			 SRpnt->sr_cmnd[0] != TEST_UNIT_READY) {
+				printk(KERN_WARNING "%s: Error with sense data: ", name);
+				scsi_print_req_sense("st", SRpnt);
+		}
 	}
 
-	if (STp->cln_mode >= EXTENDED_SENSE_START) {
+	if (cmdstatp->fixed_format &&
+	    STp->cln_mode >= EXTENDED_SENSE_START) {  /* Only fixed format sense */
 		if (STp->cln_sense_value)
 			STp->cleaning_req |= ((SRpnt->sr_sense_buffer[STp->cln_mode] &
 					       STp->cln_sense_mask) == STp->cln_sense_value);
@@ -319,12 +352,13 @@
 			STp->cleaning_req |= ((SRpnt->sr_sense_buffer[STp->cln_mode] &
 					       STp->cln_sense_mask) != 0);
 	}
-	if (sense[12] == 0 && sense[13] == 0x17) /* ASC and ASCQ => cleaning requested */
-		STp->cleaning_req = 1;
+	if (cmdstatp->have_sense &&
+	    cmdstatp->sense_hdr.asc == 0 && cmdstatp->sense_hdr.ascq == 0x17)
+		STp->cleaning_req = 1; /* ASC and ASCQ => cleaning requested */
 
 	STp->pos_unknown |= STp->device->was_reset;
 
-	if ((sense[0] & 0x70) == 0x70 &&
+	if (cmdstatp->have_sense &&
 	    scode == RECOVERED_ERROR
 #if ST_RECOVERED_WRITE_FATAL
 	    && SRpnt->sr_cmnd[0] != WRITE_6
@@ -346,7 +380,7 @@
 			       STp->recover_count);
 		} ) /* end DEB */
 
-		if ((sense[2] & 0xe0) == 0)
+		if (cmdstatp->flags == 0)
 			return 0;
 	}
 	return (-EIO);
@@ -356,28 +390,10 @@
 /* Wakeup from interrupt */
 static void st_sleep_done(struct scsi_cmnd * SCpnt)
 {
-	int remainder;
 	struct scsi_tape *STp = container_of(SCpnt->request->rq_disk->private_data,
 					     struct scsi_tape, driver);
 
-	if ((STp->buffer)->writing &&
-	    (SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
-	    (SCpnt->sense_buffer[2] & 0x40)) {
-		/* EOM at write-behind, has all been written? */
-		if ((SCpnt->sense_buffer[0] & 0x80) != 0)
-			remainder = (SCpnt->sense_buffer[3] << 24) |
-				(SCpnt->sense_buffer[4] << 16) |
-				(SCpnt->sense_buffer[5] << 8) |
-				SCpnt->sense_buffer[6];
-		else
-			remainder = 0;
-		if ((SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW ||
-		    remainder > 0)
-			(STp->buffer)->midlevel_result = SCpnt->result; /* Error */
-		else
-			(STp->buffer)->midlevel_result = INT_MAX;	/* OK */
-	} else
-		(STp->buffer)->midlevel_result = SCpnt->result;
+	(STp->buffer)->cmdstat.midlevel_result = SCpnt->result;
 	SCpnt->request->rq_status = RQ_SCSI_DONE;
 	(STp->buffer)->last_SRpnt = SCpnt->sc_request;
 	DEB( STp->write_pending = 0; )
@@ -421,6 +437,7 @@
 	SRpnt->sr_request->waiting = &(STp->wait);
 	SRpnt->sr_request->rq_status = RQ_SCSI_BUSY;
 	SRpnt->sr_request->rq_disk = STp->disk;
+	STp->buffer->cmdstat.have_sense = 0;
 
 	scsi_do_req(SRpnt, (void *) cmd, bp, bytes,
 		    st_sleep_done, timeout, retries);
@@ -434,13 +451,20 @@
 }
 
 
-/* Handle the write-behind checking (downs the semaphore) */
-static void write_behind_check(struct scsi_tape * STp)
+/* Handle the write-behind checking (waits for completion). Returns -ENOSPC if
+   write has been correct but EOM early warning reached, -EIO if write ended in
+   error or zero if write successful. Asynchronous writes are used only in
+   variable block mode. */
+static int write_behind_check(struct scsi_tape * STp)
 {
+	int retval = 0;
 	struct st_buffer *STbuffer;
 	struct st_partstat *STps;
+	struct st_cmdstatus *cmdstatp;
 
 	STbuffer = STp->buffer;
+	if (!STbuffer->writing)
+		return 0;
 
         DEB(
 	if (STp->write_pending)
@@ -463,9 +487,29 @@
 		else
 			STps->drv_block += STbuffer->writing / STp->block_size;
 	}
+
+	cmdstatp = &STbuffer->cmdstat;
+	if (STbuffer->syscall_result) {
+		retval = -EIO;
+		if (cmdstatp->have_sense && !cmdstatp->deferred &&
+		    (cmdstatp->flags & SENSE_EOM) &&
+		    (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
+		     cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR)) {
+			/* EOM at write-behind, has all data been written? */
+			if (!cmdstatp->remainder_valid ||
+			    cmdstatp->uremainder64 == 0)
+				retval = -ENOSPC;
+		}
+		if (retval == -EIO)
+			STps->drv_block = -1;
+	}
 	STbuffer->writing = 0;
 
-	return;
+	DEB(if (debugging && retval)
+	    printk(ST_DEB_MSG "%s: Async write error %x, return value %d.\n",
+		   tape_name(STp), STbuffer->cmdstat.midlevel_result, retval);) /* end DEB */
+
+	return retval;
 }
 
 
@@ -496,7 +540,7 @@
 	scsi_release_request(SRpnt);
 	SRpnt = NULL;
 
-	if ((STp->buffer)->midlevel_result != 0)
+	if ((STp->buffer)->cmdstat.midlevel_result != 0)
 		printk(KERN_ERR "%s: Stepping over filemark %s failed.\n",
 		   tape_name(STp), forward ? "forward" : "backward");
 
@@ -513,19 +557,9 @@
 	struct scsi_request *SRpnt;
 	struct st_partstat *STps;
 
-	if ((STp->buffer)->writing) {
-		write_behind_check(STp);
-		if ((STp->buffer)->syscall_result) {
-                        DEBC(printk(ST_DEB_MSG
-                                       "%s: Async write error (flush) %x.\n",
-				       tape_name(STp), (STp->buffer)->midlevel_result))
-			if ((STp->buffer)->midlevel_result == INT_MAX)
-				return (-ENOSPC);
-			return (-EIO);
-		}
-	}
-	if (STp->block_size == 0)
-		return 0;
+	result = write_behind_check(STp);
+	if (result)
+		return result;
 
 	result = 0;
 	if (STp->dirty == 1) {
@@ -553,18 +587,25 @@
 
 		STps = &(STp->ps[STp->partition]);
 		if ((STp->buffer)->syscall_result != 0) {
-			if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
-			    (SRpnt->sr_sense_buffer[2] & 0x40) &&
-			    (SRpnt->sr_sense_buffer[2] & 0x0f) == NO_SENSE) {
+			struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
+
+			if (cmdstatp->have_sense && !cmdstatp->deferred &&
+			    (cmdstatp->flags & SENSE_EOM) &&
+			    (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
+			     cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
+			    (!cmdstatp->remainder_valid ||
+			     cmdstatp->uremainder64 == 0)) { /* All written at EOM early warning */
 				STp->dirty = 0;
 				(STp->buffer)->buffer_bytes = 0;
+				if (STps->drv_block >= 0)
+					STps->drv_block += blks;
 				result = (-ENOSPC);
 			} else {
 				printk(KERN_ERR "%s: Error on flush.\n",
                                        tape_name(STp));
+				STps->drv_block = (-1);
 				result = (-EIO);
 			}
-			STps->drv_block = (-1);
 		} else {
 			if (STps->drv_block >= 0)
 				STps->drv_block += blks;
@@ -728,6 +769,7 @@
 	int retval = CHKRES_READY, new_session = 0;
 	unsigned char cmd[MAX_COMMAND_SIZE];
 	struct scsi_request *SRpnt = NULL;
+	struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
 
 	max_wait = do_wait ? ST_BLOCK_SECONDS : 0;
 
@@ -742,9 +784,9 @@
 			break;
 		}
 
-		if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70) {
+		if (cmdstatp->have_sense) {
 
-			scode = (SRpnt->sr_sense_buffer[2] & 0x0f);
+			scode = cmdstatp->sense_hdr.sense_key;
 
 			if (scode == UNIT_ATTENTION) { /* New media? */
 				new_session = 1;
@@ -760,9 +802,7 @@
 
 			if (scode == NOT_READY) {
 				if (waits < max_wait) {
-					set_current_state(TASK_INTERRUPTIBLE);
-					schedule_timeout(HZ);
-					if (signal_pending(current)) {
+					if (msleep_interruptible(1000)) {
 						retval = (-EINTR);
 						break;
 					}
@@ -771,7 +811,7 @@
 				}
 				else {
 					if ((STp->device)->scsi_level >= SCSI_2 &&
-					    SRpnt->sr_sense_buffer[12] == 0x3a)	/* Check ASC */
+					    cmdstatp->sense_hdr.asc == 0x3a)	/* Check ASC */
 						retval = CHKRES_NO_TAPE;
 					else
 						retval = CHKRES_NOT_READY;
@@ -877,7 +917,7 @@
 			goto err_out;
 		}
 
-		if (!SRpnt->sr_result && !SRpnt->sr_sense_buffer[0]) {
+		if (!SRpnt->sr_result && !STp->buffer->cmdstat.have_sense) {
 			STp->max_block = ((STp->buffer)->b_data[1] << 16) |
 			    ((STp->buffer)->b_data[2] << 8) | (STp->buffer)->b_data[3];
 			STp->min_block = ((STp->buffer)->b_data[4] << 8) |
@@ -1108,6 +1148,7 @@
 		       name, STp->nbr_requests, STp->nbr_dio, STp->nbr_pages, STp->nbr_combinable));
 
 	if (STps->rw == ST_WRITING && !STp->pos_unknown) {
+		struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
 
                 DEBC(printk(ST_DEB_MSG "%s: File length %lld bytes.\n",
                             name, (long long)filp->f_pos);
@@ -1126,20 +1167,13 @@
 			goto out;
 		}
 
-		if ((STp->buffer)->syscall_result != 0 &&
-		    ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
-		     (SRpnt->sr_sense_buffer[2] & 0x4f) != 0x40 ||
-		     ((SRpnt->sr_sense_buffer[0] & 0x80) != 0 &&
-		      (SRpnt->sr_sense_buffer[3] | SRpnt->sr_sense_buffer[4] |
-		       SRpnt->sr_sense_buffer[5] |
-		       SRpnt->sr_sense_buffer[6]) != 0))) {
-			/* Filter out successful write at EOM */
-			scsi_release_request(SRpnt);
-			SRpnt = NULL;
-			printk(KERN_ERR "%s: Error on write filemark.\n", name);
-			if (result == 0)
-				result = (-EIO);
-		} else {
+		if (STp->buffer->syscall_result == 0 ||
+		    (cmdstatp->have_sense && !cmdstatp->deferred &&
+		     (cmdstatp->flags & SENSE_EOM) &&
+		     (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
+		      cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
+		     (!cmdstatp->remainder_valid || cmdstatp->uremainder64 == 0))) {
+			/* Write successful at EOM */
 			scsi_release_request(SRpnt);
 			SRpnt = NULL;
 			if (STps->drv_file >= 0)
@@ -1149,6 +1183,13 @@
 				cross_eof(STp, 0);
 			STps->eof = ST_FM;
 		}
+		else { /* Write error */
+			scsi_release_request(SRpnt);
+			SRpnt = NULL;
+			printk(KERN_ERR "%s: Error on write filemark.\n", name);
+			if (result == 0)
+				result = (-EIO);
+		}
 
                 DEBC(printk(ST_DEB_MSG "%s: Buffer flushed, %d EOF(s) written\n",
                             name, cmd[4]));
@@ -1410,16 +1451,12 @@
 	}
 
 	STbp = STp->buffer;
-	if (STbp->writing) {
-		write_behind_check(STp);
-		if (STbp->syscall_result) {
-                        DEBC(printk(ST_DEB_MSG "%s: Async write error (write) %x.\n",
-                                    name, STbp->midlevel_result));
-			if (STbp->midlevel_result == INT_MAX)
-				STps->eof = ST_EOM_OK;
-			else
-				STps->eof = ST_EOM_ERROR;
-		}
+	i = write_behind_check(STp);
+	if (i) {
+		if (i == -ENOSPC)
+			STps->eof = ST_EOM_OK;
+		else
+			STps->eof = ST_EOM_ERROR;
 	}
 
 	if (STps->eof == ST_EOM_OK) {
@@ -1523,15 +1560,13 @@
 		}
 
 		if (STbp->syscall_result != 0) {
+			struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
+
                         DEBC(printk(ST_DEB_MSG "%s: Error on write:\n", name));
-			if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
-			    (SRpnt->sr_sense_buffer[2] & 0x40)) {
-				scode = SRpnt->sr_sense_buffer[2] & 0x0f;
-				if ((SRpnt->sr_sense_buffer[0] & 0x80) != 0)
-					undone = (SRpnt->sr_sense_buffer[3] << 24) |
-					    (SRpnt->sr_sense_buffer[4] << 16) |
-					    (SRpnt->sr_sense_buffer[5] << 8) |
-                                                SRpnt->sr_sense_buffer[6];
+			if (cmdstatp->have_sense && (cmdstatp->flags & SENSE_EOM)) {
+				scode = cmdstatp->sense_hdr.sense_key;
+				if (cmdstatp->remainder_valid)
+					undone = (int)cmdstatp->uremainder64;
 				else if (STp->block_size == 0 &&
 					 scode == VOLUME_OVERFLOW)
 					undone = transfer;
@@ -1556,11 +1591,11 @@
 						retval = (-ENOSPC); /* EOM within current request */
                                         DEBC(printk(ST_DEB_MSG
                                                        "%s: EOM with %d bytes unwritten.\n",
-						       name, count));
+						       name, (int)count));
 				} else {
 					/* EOT within data buffered earlier (possible only
 					   in fixed block mode without direct i/o) */
-					if (!retry_eot && (SRpnt->sr_sense_buffer[0] & 1) == 0 &&
+					if (!retry_eot && !cmdstatp->deferred &&
 					    (scode == NO_SENSE || scode == RECOVERED_ERROR)) {
 						move_buffer_data(STp->buffer, transfer - undone);
 						retry_eot = 1;
@@ -1690,6 +1725,8 @@
 
 	/* Something to check */
 	if (STbp->syscall_result) {
+		struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
+
 		retval = 1;
 		DEBC(printk(ST_DEB_MSG "%s: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
                             name,
@@ -1697,25 +1734,22 @@
                             SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[3],
                             SRpnt->sr_sense_buffer[4], SRpnt->sr_sense_buffer[5],
                             SRpnt->sr_sense_buffer[6], SRpnt->sr_sense_buffer[7]));
-		if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70) {	/* extended sense */
+		if (cmdstatp->have_sense) {
 
-			if ((SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK)
-				SRpnt->sr_sense_buffer[2] &= 0xcf;	/* No need for EOM in this case */
+			if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK)
+				cmdstatp->flags &= 0xcf;	/* No need for EOM in this case */
 
-			if ((SRpnt->sr_sense_buffer[2] & 0xe0) != 0) { /* EOF, EOM, or ILI */
+			if (cmdstatp->flags != 0) { /* EOF, EOM, or ILI */
 				/* Compute the residual count */
-				if ((SRpnt->sr_sense_buffer[0] & 0x80) != 0)
-					transfer = (SRpnt->sr_sense_buffer[3] << 24) |
-					    (SRpnt->sr_sense_buffer[4] << 16) |
-					    (SRpnt->sr_sense_buffer[5] << 8) |
-					    SRpnt->sr_sense_buffer[6];
+				if (cmdstatp->remainder_valid)
+					transfer = (int)cmdstatp->uremainder64;
 				else
 					transfer = 0;
 				if (STp->block_size == 0 &&
-				    (SRpnt->sr_sense_buffer[2] & 0x0f) == MEDIUM_ERROR)
+				    cmdstatp->sense_hdr.sense_key == MEDIUM_ERROR)
 					transfer = bytes;
 
-				if (SRpnt->sr_sense_buffer[2] & 0x20) {	/* ILI */
+				if (cmdstatp->flags & SENSE_ILI) {	/* ILI */
 					if (STp->block_size == 0) {
 						if (transfer <= 0) {
 							if (transfer < 0)
@@ -1749,7 +1783,7 @@
 						if (st_int_ioctl(STp, MTBSR, 1))
 							return (-EIO);
 					}
-				} else if (SRpnt->sr_sense_buffer[2] & 0x80) {	/* FM overrides EOM */
+				} else if (cmdstatp->flags & SENSE_FMK) {	/* FM overrides EOM */
 					if (STps->eof != ST_FM_HIT)
 						STps->eof = ST_FM_HIT;
 					else
@@ -1762,7 +1796,7 @@
                                         DEBC(printk(ST_DEB_MSG
                                                     "%s: EOF detected (%d bytes read).\n",
                                                     name, STbp->buffer_bytes));
-				} else if (SRpnt->sr_sense_buffer[2] & 0x40) {
+				} else if (cmdstatp->flags & SENSE_EOM) {
 					if (STps->eof == ST_FM)
 						STps->eof = ST_EOD_1;
 					else
@@ -1783,7 +1817,7 @@
                                             "%s: Tape error while reading.\n", name));
 				STps->drv_block = (-1);
 				if (STps->eof == ST_FM &&
-				    (SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK) {
+				    cmdstatp->sense_hdr.sense_key == BLANK_CHECK) {
                                         DEBC(printk(ST_DEB_MSG
                                                     "%s: Zero returned for first BLANK CHECK after EOF.\n",
                                                     name));
@@ -1907,7 +1941,7 @@
 				printk(ST_DEB_MSG
                                        "%s: EOF up (%d). Left %d, needed %d.\n", name,
 				       STps->eof, STbp->buffer_bytes,
-                                       count - total);
+                                       (int)(count - total));
                         ) /* end DEB */
 			transfer = STbp->buffer_bytes < count - total ?
 			    STbp->buffer_bytes : count - total;
@@ -2693,25 +2727,30 @@
 		else if (chg_eof)
 			STps->eof = ST_NOEOF;
 
+		if (cmd_in == MTWEOF)
+			STps->rw = ST_IDLE;
 	} else { /* SCSI command was not completely successful. Don't return
                     from this block without releasing the SCSI command block! */
+		struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
 
-		if (SRpnt->sr_sense_buffer[2] & 0x40) {
+		if (cmdstatp->flags & SENSE_EOM) {
 			if (cmd_in != MTBSF && cmd_in != MTBSFM &&
 			    cmd_in != MTBSR && cmd_in != MTBSS)
 				STps->eof = ST_EOM_OK;
 			STps->drv_block = 0;
 		}
 
-		undone = ((SRpnt->sr_sense_buffer[3] << 24) +
-			  (SRpnt->sr_sense_buffer[4] << 16) +
-			  (SRpnt->sr_sense_buffer[5] << 8) +
-			  SRpnt->sr_sense_buffer[6]);
+		if (cmdstatp->remainder_valid)
+			undone = (int)cmdstatp->uremainder64;
+		else
+			undone = 0;
 
 		if (cmd_in == MTWEOF &&
-		    (SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
-		    (SRpnt->sr_sense_buffer[2] & 0x4f) == 0x40 &&
-		 ((SRpnt->sr_sense_buffer[0] & 0x80) == 0 || undone == 0)) {
+		    cmdstatp->have_sense &&
+		    (cmdstatp->flags & SENSE_EOM) &&
+		    (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
+		     cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
+		    undone == 0) {
 			ioctl_result = 0;	/* EOF written succesfully at EOM */
 			if (fileno >= 0)
 				fileno++;
@@ -2732,7 +2771,7 @@
 			STps->drv_block = 0;
 			STps->eof = ST_NOEOF;
 		} else if (cmd_in == MTFSR) {
-			if (SRpnt->sr_sense_buffer[2] & 0x80) {	/* Hit filemark */
+			if (cmdstatp->flags & SENSE_FMK) {	/* Hit filemark */
 				if (STps->drv_file >= 0)
 					STps->drv_file++;
 				STps->drv_block = 0;
@@ -2745,7 +2784,7 @@
 				STps->eof = ST_NOEOF;
 			}
 		} else if (cmd_in == MTBSR) {
-			if (SRpnt->sr_sense_buffer[2] & 0x80) {	/* Hit filemark */
+			if (cmdstatp->flags & SENSE_FMK) {	/* Hit filemark */
 				STps->drv_file--;
 				STps->drv_block = (-1);
 			} else {
@@ -2763,7 +2802,7 @@
 			   cmd_in == MTSETDENSITY ||
 			   cmd_in == MTSETDRVBUFFER ||
 			   cmd_in == SET_DENS_AND_BLK) {
-			if ((SRpnt->sr_sense_buffer[2] & 0x0f) == ILLEGAL_REQUEST &&
+			if (cmdstatp->sense_hdr.sense_key == ILLEGAL_REQUEST &&
 			    !(STp->use_pf & PF_TESTED)) {
 				/* Try the other possible state of Page Format if not
 				   already tried */
@@ -2775,7 +2814,7 @@
 		} else if (chg_eof)
 			STps->eof = ST_NOEOF;
 
-		if ((SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK)
+		if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK)
 			STps->eof = ST_EOD;
 
 		scsi_release_request(SRpnt);
@@ -3198,6 +3237,17 @@
 				retval = i;
 				goto out;
 			}
+			if (STps->rw == ST_WRITING &&
+			    (mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
+			     mtc.mt_op == MTSEEK)) {
+				i = st_int_ioctl(STp, MTWEOF, 1);
+				if (i < 0) {
+					retval = i;
+					goto out;
+				}
+				STps->rw = ST_IDLE;
+			     }
+
 		} else {
 			/*
 			 * If there was a bus reset, block further access
@@ -3425,6 +3475,22 @@
 	up(&STp->lock);
 	return retval;
 }
+
+#ifdef CONFIG_COMPAT
+static long st_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct scsi_tape *STp = file->private_data;
+	struct scsi_device *sdev = STp->device;
+	int ret = -ENOIOCTLCMD;
+	if (sdev->host->hostt->compat_ioctl) { 
+
+		ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg);
+
+	}
+	return ret;
+}
+#endif
+
 
 
 /* Try to allocate a new tape buffer. Calling function must not hold
@@ -3716,6 +3782,9 @@
 	.read =		st_read,
 	.write =	st_write,
 	.ioctl =	st_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = st_compat_ioctl,
+#endif
 	.open =		st_open,
 	.flush =	st_flush,
 	.release =	st_release,
diff -Nru a/drivers/scsi/st.h b/drivers/scsi/st.h
--- a/drivers/scsi/st.h	2005-03-07 15:19:08 -08:00
+++ b/drivers/scsi/st.h	2005-03-07 15:19:08 -08:00
@@ -5,6 +5,18 @@
 #include <linux/completion.h>
 
 
+/* Descriptor for analyzed sense data */
+struct st_cmdstatus {
+	int midlevel_result;
+	struct scsi_sense_hdr sense_hdr;
+	int have_sense;
+	u64 uremainder64;
+	u8 flags;
+	u8 remainder_valid;
+	u8 fixed_format;
+	u8 deferred;
+};
+
 /* The tape buffer descriptor. */
 struct st_buffer {
 	unsigned char in_use;
@@ -15,9 +27,9 @@
 	int buffer_bytes;
 	int read_pointer;
 	int writing;
-	int midlevel_result;
 	int syscall_result;
 	struct scsi_request *last_SRpnt;
+	struct st_cmdstatus cmdstat;
 	unsigned char *b_data;
 	unsigned short use_sg;	/* zero or max number of s/g segments for this adapter */
 	unsigned short sg_segs;		/* number of segments in s/g list */
@@ -191,5 +203,10 @@
 #define ST_YES         2
 
 #define EXTENDED_SENSE_START  18
+
+/* Masks for some conditions in the sense data */
+#define SENSE_FMK   0x80
+#define SENSE_EOM   0x40
+#define SENSE_ILI   0x20
 
 #endif
diff -Nru a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
--- a/include/scsi/scsi_cmnd.h	2005-03-07 15:19:08 -08:00
+++ b/include/scsi/scsi_cmnd.h	2005-03-07 15:19:08 -08:00
@@ -54,6 +54,7 @@
 	 * completed and the SCSI Command structure has already being reused
 	 * for another command, so that we can avoid incorrectly aborting or
 	 * resetting the new command.
+	 * The serial number is only unique per host.
 	 */
 	unsigned long serial_number;
 	unsigned long serial_number_at_timeout;
@@ -139,7 +140,7 @@
 	int result;		/* Status code from lower level driver */
 
 	unsigned char tag;	/* SCSI-II queued command tag */
-	unsigned long pid;	/* Process ID, starts at 0 */
+	unsigned long pid;	/* Process ID, starts at 0. Unique per host. */
 };
 
 /*
diff -Nru a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
--- a/include/scsi/scsi_device.h	2005-03-07 15:19:08 -08:00
+++ b/include/scsi/scsi_device.h	2005-03-07 15:19:08 -08:00
@@ -118,6 +118,10 @@
 	unsigned int max_device_blocked; /* what device_blocked counts down from  */
 #define SCSI_DEFAULT_DEVICE_BLOCKED	3
 
+	atomic_t iorequest_cnt;
+	atomic_t iodone_cnt;
+	atomic_t ioerr_cnt;
+
 	int timeout;
 
 	struct device		sdev_gendev;
@@ -140,7 +144,10 @@
  */
 struct scsi_target {
 	struct scsi_device	*starget_sdev_user;
+	struct list_head	siblings;
+	struct list_head	devices;
 	struct device		dev;
+	unsigned int		reap_ref; /* protected by the host lock */
 	unsigned int		channel;
 	unsigned int		id; /* target id ... replace
 				     * scsi_device.id eventually */
@@ -169,6 +176,10 @@
 					      uint, uint, uint);
 extern struct scsi_device *__scsi_device_lookup(struct Scsi_Host *,
 						uint, uint, uint);
+extern struct scsi_device *scsi_device_lookup_by_target(struct scsi_target *,
+							uint);
+extern struct scsi_device *__scsi_device_lookup_by_target(struct scsi_target *,
+							  uint);
 extern void starget_for_each_device(struct scsi_target *, void *,
 		     void (*fn)(struct scsi_device *, void *));
 
@@ -222,6 +233,10 @@
 extern void scsi_device_resume(struct scsi_device *sdev);
 extern void scsi_target_quiesce(struct scsi_target *);
 extern void scsi_target_resume(struct scsi_target *);
+extern void scsi_scan_target(struct device *parent, unsigned int channel,
+			     unsigned int id, unsigned int lun, int rescan);
+extern void scsi_target_reap(struct scsi_target *);
+extern void scsi_remove_target(struct scsi_target *);
 extern const char *scsi_device_state_name(enum scsi_device_state);
 extern int scsi_is_sdev_device(const struct device *);
 extern int scsi_is_target_device(const struct device *);
diff -Nru a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h
--- a/include/scsi/scsi_devinfo.h	2005-03-07 15:19:08 -08:00
+++ b/include/scsi/scsi_devinfo.h	2005-03-07 15:19:08 -08:00
@@ -27,4 +27,5 @@
 #define BLIST_NOT_LOCKABLE	0x80000	/* don't use PREVENT-ALLOW commands */
 #define BLIST_NO_ULD_ATTACH	0x100000 /* device is actually for RAID config */
 #define BLIST_SELECT_NO_ATN	0x200000 /* select without ATN */
+#define BLIST_RETRY_HWERROR	0x400000 /* retry HARDWARE_ERROR */
 #endif
diff -Nru a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
--- a/include/scsi/scsi_host.h	2005-03-07 15:19:08 -08:00
+++ b/include/scsi/scsi_host.h	2005-03-07 15:19:08 -08:00
@@ -416,6 +416,7 @@
 	 * access this list directly from a driver.
 	 */
 	struct list_head	__devices;
+	struct list_head	__targets;
 	
 	struct scsi_host_cmd_pool *cmd_pool;
 	spinlock_t		free_list_lock;
@@ -483,7 +484,12 @@
 	short unsigned int sg_tablesize;
 	short unsigned int max_sectors;
 	unsigned long dma_boundary;
-
+	/* 
+	 * Used to assign serial numbers to the cmds.
+	 * Protected by the host lock.
+	 */
+	unsigned long cmd_serial_number, cmd_pid; 
+	
 	unsigned unchecked_isa_dma:1;
 	unsigned use_clustering:1;
 	unsigned use_blk_tcq:1;
@@ -548,11 +554,21 @@
 	unsigned long hostdata[0]  /* Used for storage of host specific stuff */
 		__attribute__ ((aligned (sizeof(unsigned long))));
 };
-#define		dev_to_shost(d)		\
-	container_of(d, struct Scsi_Host, shost_gendev)
+
 #define		class_to_shost(d)	\
 	container_of(d, struct Scsi_Host, shost_classdev)
 
+int scsi_is_host_device(const struct device *);
+
+static inline struct Scsi_Host *dev_to_shost(struct device *dev)
+{
+	while (!scsi_is_host_device(dev)) {
+		if (!dev->parent)
+			return NULL;
+		dev = dev->parent;
+	}
+	return container_of(dev, struct Scsi_Host, shost_gendev);
+}
 
 extern struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *, int);
 extern int __must_check scsi_add_host(struct Scsi_Host *, struct device *);
@@ -596,8 +612,6 @@
  */
 extern void scsi_free_host_dev(struct scsi_device *);
 extern struct scsi_device *scsi_get_host_dev(struct Scsi_Host *);
-int scsi_is_host_device(const struct device *);
-
 
 /* legacy interfaces */
 extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int);
diff -Nru a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
--- a/include/scsi/scsi_transport_fc.h	2005-03-07 15:19:08 -08:00
+++ b/include/scsi/scsi_transport_fc.h	2005-03-07 15:19:08 -08:00
@@ -197,11 +197,7 @@
 	char symbolic_name[FC_SYMBOLIC_NAME_SIZE];
 	u32 supported_speeds;
 	u32 maxframe_size;
-	char hardware_version[FC_VERSION_STRING_SIZE];
-	char firmware_version[FC_VERSION_STRING_SIZE];
 	char serial_number[FC_SERIAL_NUMBER_SIZE];
-	char opt_rom_version[FC_VERSION_STRING_SIZE];
-	char driver_version[FC_VERSION_STRING_SIZE];
 
 	/* Dynamic Attributes */
 	u32 port_id;
diff -Nru a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h
--- a/include/scsi/scsi_transport_spi.h	2005-03-07 15:19:08 -08:00
+++ b/include/scsi/scsi_transport_spi.h	2005-03-07 15:19:08 -08:00
@@ -130,5 +130,6 @@
 void spi_release_transport(struct scsi_transport_template *);
 void spi_schedule_dv_device(struct scsi_device *);
 void spi_dv_device(struct scsi_device *);
+void spi_display_xfer_agreement(struct scsi_target *);
 
 #endif /* SCSI_TRANSPORT_SPI_H */
