summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Documentation/scsi/ChangeLog.megaraid16
-rw-r--r--drivers/block/DAC960.c27
-rw-r--r--drivers/message/fusion/Kconfig2
-rw-r--r--drivers/message/fusion/Makefile7
-rw-r--r--drivers/message/fusion/lsi/mpi.h7
-rw-r--r--drivers/message/fusion/lsi/mpi_cnfg.h131
-rw-r--r--drivers/message/fusion/lsi/mpi_history.txt77
-rw-r--r--drivers/message/fusion/lsi/mpi_init.h7
-rw-r--r--drivers/message/fusion/lsi/mpi_ioc.h75
-rw-r--r--drivers/message/fusion/lsi/mpi_log_sas.h284
-rw-r--r--drivers/message/fusion/lsi/mpi_sas.h9
-rw-r--r--drivers/message/fusion/mptbase.c875
-rw-r--r--drivers/message/fusion/mptbase.h47
-rw-r--r--drivers/message/fusion/mptctl.c163
-rw-r--r--drivers/message/fusion/mptctl.h2
-rw-r--r--drivers/message/fusion/mptfc.c53
-rw-r--r--drivers/message/fusion/mptlan.c1
-rw-r--r--drivers/message/fusion/mptlan.h1
-rw-r--r--drivers/message/fusion/mptsas.c718
-rw-r--r--drivers/message/fusion/mptscsih.c997
-rw-r--r--drivers/message/fusion/mptscsih.h44
-rw-r--r--drivers/message/fusion/mptspi.c527
-rw-r--r--drivers/s390/scsi/zfcp_erp.c22
-rw-r--r--drivers/s390/scsi/zfcp_ext.h2
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c23
-rw-r--r--drivers/scsi/53c700.c24
-rw-r--r--drivers/scsi/53c700.h2
-rw-r--r--drivers/scsi/53c7xx.c4
-rw-r--r--drivers/scsi/BusLogic.c46
-rw-r--r--drivers/scsi/BusLogic.h300
-rw-r--r--drivers/scsi/FlashPoint.c4
-rw-r--r--drivers/scsi/Kconfig9
-rw-r--r--drivers/scsi/Makefile1
-rw-r--r--drivers/scsi/NCR_D700.c1
-rw-r--r--drivers/scsi/aacraid/Makefile2
-rw-r--r--drivers/scsi/aacraid/aachba.c602
-rw-r--r--drivers/scsi/aacraid/aacraid.h46
-rw-r--r--drivers/scsi/aacraid/comminit.c14
-rw-r--r--drivers/scsi/aacraid/commsup.c40
-rw-r--r--drivers/scsi/aacraid/linit.c17
-rw-r--r--drivers/scsi/aacraid/nark.c87
-rw-r--r--drivers/scsi/aacraid/rkt.c64
-rw-r--r--drivers/scsi/aacraid/rx.c263
-rw-r--r--drivers/scsi/aacraid/sa.c33
-rw-r--r--drivers/scsi/advansys.c7
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.h3
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c5
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c9
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h2
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm_pci.c19
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_pci.c2
-rw-r--r--drivers/scsi/aic94xx/aic94xx_dev.c16
-rw-r--r--drivers/scsi/aic94xx/aic94xx_dump.c2
-rw-r--r--drivers/scsi/aic94xx/aic94xx_init.c49
-rw-r--r--drivers/scsi/aic94xx/aic94xx_reg_def.h5
-rw-r--r--drivers/scsi/aic94xx/aic94xx_sas.h1
-rw-r--r--drivers/scsi/aic94xx/aic94xx_scb.c122
-rw-r--r--drivers/scsi/aic94xx/aic94xx_sds.c10
-rw-r--r--drivers/scsi/aic94xx/aic94xx_seq.c45
-rw-r--r--drivers/scsi/aic94xx/aic94xx_seq.h1
-rw-r--r--drivers/scsi/aic94xx/aic94xx_task.c9
-rw-r--r--drivers/scsi/aic94xx/aic94xx_tmf.c4
-rw-r--r--drivers/scsi/ipr.c91
-rw-r--r--drivers/scsi/ipr.h4
-rw-r--r--drivers/scsi/lasi700.c1
-rw-r--r--drivers/scsi/libsas/sas_discover.c62
-rw-r--r--drivers/scsi/libsas/sas_event.c6
-rw-r--r--drivers/scsi/libsas/sas_expander.c48
-rw-r--r--drivers/scsi/libsas/sas_init.c52
-rw-r--r--drivers/scsi/libsas/sas_internal.h9
-rw-r--r--drivers/scsi/libsas/sas_port.c14
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c290
-rw-r--r--drivers/scsi/megaraid/mbox_defs.h2
-rw-r--r--drivers/scsi/megaraid/mega_common.h122
-rw-r--r--drivers/scsi/megaraid/megaraid_ioctl.h36
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c421
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.h46
-rw-r--r--drivers/scsi/megaraid/megaraid_mm.c65
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h14
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.h66
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c68
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h38
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h6
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c218
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c245
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c18
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c24
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c348
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h2
-rw-r--r--drivers/scsi/scsi.c21
-rw-r--r--drivers/scsi/scsi_debug.c42
-rw-r--r--drivers/scsi/scsi_error.c256
-rw-r--r--drivers/scsi/scsi_lib.c4
-rw-r--r--drivers/scsi/scsi_priv.h6
-rw-r--r--drivers/scsi/scsi_scan.c2
-rw-r--r--drivers/scsi/scsi_transport_sas.c118
-rw-r--r--drivers/scsi/scsi_transport_spi.c1
-rw-r--r--drivers/scsi/sim710.c1
-rw-r--r--drivers/scsi/sni_53c710.c159
-rw-r--r--drivers/scsi/st.c23
-rw-r--r--drivers/scsi/st.h3
-rw-r--r--include/scsi/libsas.h19
-rw-r--r--include/scsi/scsi_transport_sas.h3
-rw-r--r--include/scsi/scsi_transport_spi.h1
104 files changed, 5827 insertions, 3135 deletions
diff --git a/Documentation/scsi/ChangeLog.megaraid b/Documentation/scsi/ChangeLog.megaraid
index a056bbe67c7e..37796fe45bd0 100644
--- a/Documentation/scsi/ChangeLog.megaraid
+++ b/Documentation/scsi/ChangeLog.megaraid
@@ -1,3 +1,19 @@
+Release Date	: Thu Nov 16 15:32:35 EST 2006 -
+				Sumant Patro <sumant.patro@lsi.com>
+Current Version : 2.20.5.1 (scsi module), 2.20.2.6 (cmm module)
+Older Version	: 2.20.4.9 (scsi module), 2.20.2.6 (cmm module)
+
+1.	Changes in Initialization to fix kdump failure.
+	Send SYNC command on loading.
+	This command clears the pending commands in the adapter
+	and re-initialize its internal RAID structure.
+	Without this change, megaraid driver either panics or fails to
+	initialize the adapter during kdump's second kernel boot
+	if there are pending commands or interrupts from other devices
+	sharing the same IRQ.
+2. 	Authors email-id domain name changed from lsil.com to lsi.com.
+	Also modified the MODULE_AUTHOR to megaraidlinux@lsi.com
+
 Release Date	: Fri May 19 09:31:45 EST 2006 - Seokmann Ju <sju@lsil.com>
 Current Version : 2.20.4.9 (scsi module), 2.20.2.6 (cmm module)
 Older Version	: 2.20.4.8 (scsi module), 2.20.2.6 (cmm module)
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 6ad28dfb1469..7b2fa3d8f61c 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -1373,8 +1373,7 @@ static bool DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T
   Controller->BounceBufferLimit = DAC690_V2_PciDmaMask;
 
   /* This is a temporary dma mapping, used only in the scope of this function */
-  CommandMailbox =
-	  (DAC960_V2_CommandMailbox_T *)pci_alloc_consistent( PCI_Device,
+  CommandMailbox = pci_alloc_consistent(PCI_Device,
 		sizeof(DAC960_V2_CommandMailbox_T), &CommandMailboxDMA);
   if (CommandMailbox == NULL)
 	  return false;
@@ -1879,8 +1878,8 @@ static bool DAC960_V2_ReadControllerConfiguration(DAC960_Controller_T
       if (NewLogicalDeviceInfo->LogicalDeviceState !=
 	  DAC960_V2_LogicalDevice_Offline)
 	Controller->LogicalDriveInitiallyAccessible[LogicalDeviceNumber] = true;
-      LogicalDeviceInfo = (DAC960_V2_LogicalDeviceInfo_T *)
-	kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T), GFP_ATOMIC);
+      LogicalDeviceInfo = kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T),
+				   GFP_ATOMIC);
       if (LogicalDeviceInfo == NULL)
 	return DAC960_Failure(Controller, "LOGICAL DEVICE ALLOCATION");
       Controller->V2.LogicalDeviceInformation[LogicalDeviceNumber] =
@@ -2113,8 +2112,8 @@ static bool DAC960_V2_ReadDeviceConfiguration(DAC960_Controller_T
       if (!DAC960_V2_NewPhysicalDeviceInfo(Controller, Channel, TargetID, LogicalUnit))
 	  break;
 
-      PhysicalDeviceInfo = (DAC960_V2_PhysicalDeviceInfo_T *)
-		kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC);
+      PhysicalDeviceInfo = kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T),
+				    GFP_ATOMIC);
       if (PhysicalDeviceInfo == NULL)
 		return DAC960_Failure(Controller, "PHYSICAL DEVICE ALLOCATION");
       Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex] =
@@ -2122,8 +2121,8 @@ static bool DAC960_V2_ReadDeviceConfiguration(DAC960_Controller_T
       memcpy(PhysicalDeviceInfo, NewPhysicalDeviceInfo,
 		sizeof(DAC960_V2_PhysicalDeviceInfo_T));
 
-      InquiryUnitSerialNumber = (DAC960_SCSI_Inquiry_UnitSerialNumber_T *)
-	kmalloc(sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), GFP_ATOMIC);
+      InquiryUnitSerialNumber = kmalloc(
+	      sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), GFP_ATOMIC);
       if (InquiryUnitSerialNumber == NULL) {
 	kfree(PhysicalDeviceInfo);
 	return DAC960_Failure(Controller, "SERIAL NUMBER ALLOCATION");
@@ -4949,8 +4948,8 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
 	      PhysicalDevice.LogicalUnit = NewLogicalDeviceInfo->LogicalUnit;
 	      Controller->V2.LogicalDriveToVirtualDevice[LogicalDeviceNumber] =
 		PhysicalDevice;
-	      LogicalDeviceInfo = (DAC960_V2_LogicalDeviceInfo_T *)
-		kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T), GFP_ATOMIC);
+	      LogicalDeviceInfo = kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T),
+					  GFP_ATOMIC);
 	      Controller->V2.LogicalDeviceInformation[LogicalDeviceNumber] =
 		LogicalDeviceInfo;
 	      DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
@@ -5709,14 +5708,14 @@ static bool DAC960_CheckStatusBuffer(DAC960_Controller_T *Controller,
       unsigned int NewStatusBufferLength = DAC960_InitialStatusBufferSize;
       while (NewStatusBufferLength < ByteCount)
 	NewStatusBufferLength *= 2;
-      Controller->CombinedStatusBuffer =
-	(unsigned char *) kmalloc(NewStatusBufferLength, GFP_ATOMIC);
+      Controller->CombinedStatusBuffer = kmalloc(NewStatusBufferLength,
+						  GFP_ATOMIC);
       if (Controller->CombinedStatusBuffer == NULL) return false;
       Controller->CombinedStatusBufferLength = NewStatusBufferLength;
       return true;
     }
-  NewStatusBuffer = (unsigned char *)
-    kmalloc(2 * Controller->CombinedStatusBufferLength, GFP_ATOMIC);
+  NewStatusBuffer = kmalloc(2 * Controller->CombinedStatusBufferLength,
+			     GFP_ATOMIC);
   if (NewStatusBuffer == NULL)
     {
       DAC960_Warning("Unable to expand Combined Status Buffer - Truncating\n",
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig
index ea31d8470510..71037f91c222 100644
--- a/drivers/message/fusion/Kconfig
+++ b/drivers/message/fusion/Kconfig
@@ -66,7 +66,7 @@ config FUSION_MAX_SGE
 
 config FUSION_CTL
 	tristate "Fusion MPT misc device (ioctl) driver"
-	depends on FUSION_SPI || FUSION_FC
+	depends on FUSION_SPI || FUSION_FC || FUSION_SAS
 	---help---
 	  The Fusion MPT misc device driver provides specialized control
 	  of MPT adapters via system ioctl calls.  Use of ioctl calls to
diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile
index 341691390e86..6003b46c8438 100644
--- a/drivers/message/fusion/Makefile
+++ b/drivers/message/fusion/Makefile
@@ -8,6 +8,9 @@
 #EXTRA_CFLAGS += -DMPT_DEBUG_INIT
 #EXTRA_CFLAGS += -DMPT_DEBUG_EXIT
 #EXTRA_CFLAGS += -DMPT_DEBUG_FAIL
+#EXTRA_CFLAGS += -DMPT_DEBUG_DV
+#EXTRA_CFLAGS += -DMPT_DEBUG_TM
+#EXTRA_CFLAGS += -DMPT_DEBUG_REPLY
 
 #
 # driver/module specifics...
@@ -20,11 +23,7 @@
 #CFLAGS_mptbase.o += -DMPT_DEBUG_RESET
 #
 #  For mptscsih:
-#CFLAGS_mptscsih.o += -DMPT_DEBUG_DV
-#CFLAGS_mptscsih.o += -DMPT_DEBUG_NEGO
-#CFLAGS_mptscsih.o += -DMPT_DEBUG_TM
 #CFLAGS_mptscsih.o += -DMPT_DEBUG_SCSI
-#CFLAGS_mptscsih.o += -DMPT_DEBUG_REPLY
 #
 #  For mptctl:
 #CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL
diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h
index 81ad77622dac..75223bf24ae8 100644
--- a/drivers/message/fusion/lsi/mpi.h
+++ b/drivers/message/fusion/lsi/mpi.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2005 LSI Logic Corporation.
+ *  Copyright (c) 2000-2006 LSI Logic Corporation.
  *
  *
  *           Name:  mpi.h
  *          Title:  MPI Message independent structures and definitions
  *  Creation Date:  July 27, 2000
  *
- *    mpi.h Version:  01.05.11
+ *    mpi.h Version:  01.05.12
  *
  *  Version History
  *  ---------------
@@ -77,6 +77,7 @@
  *  08-03-05  01.05.09  Bumped MPI_HEADER_VERSION_UNIT.
  *  08-30-05  01.05.10  Added 2 new IOCStatus codes for Target.
  *  03-27-06  01.05.11  Bumped MPI_HEADER_VERSION_UNIT.
+ *  10-11-06  01.05.12  Bumped MPI_HEADER_VERSION_UNIT.
  *  --------------------------------------------------------------------------
  */
 
@@ -107,7 +108,7 @@
 /* Note: The major versions of 0xe0 through 0xff are reserved */
 
 /* versioning for this MPI header set */
-#define MPI_HEADER_VERSION_UNIT             (0x0D)
+#define MPI_HEADER_VERSION_UNIT             (0x0E)
 #define MPI_HEADER_VERSION_DEV              (0x00)
 #define MPI_HEADER_VERSION_UNIT_MASK        (0xFF00)
 #define MPI_HEADER_VERSION_UNIT_SHIFT       (8)
diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h
index 47e13e360c10..0e4c8e77a81d 100644
--- a/drivers/message/fusion/lsi/mpi_cnfg.h
+++ b/drivers/message/fusion/lsi/mpi_cnfg.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2005 LSI Logic Corporation.
+ *  Copyright (c) 2000-2006 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_cnfg.h
  *          Title:  MPI Config message, structures, and Pages
  *  Creation Date:  July 27, 2000
  *
- *    mpi_cnfg.h Version:  01.05.12
+ *    mpi_cnfg.h Version:  01.05.13
  *
  *  Version History
  *  ---------------
@@ -276,6 +276,23 @@
  *                      Added AdditionalControlFlags, MaxTargetPortConnectTime,
  *                      ReportDeviceMissingDelay, and IODeviceMissingDelay
  *                      fields to SAS IO Unit Page 1.
+ *  10-11-06  01.05.13  Added NumForceWWID field and ForceWWID array to
+ *                      Manufacturing Page 5.
+ *                      Added Manufacturing pages 8 through 10.
+ *                      Added defines for supported metadata size bits in
+ *                      CapabilitiesFlags field of IOC Page 6.
+ *                      Added defines for metadata size bits in VolumeSettings
+ *                      field of RAID Volume Page 0.
+ *                      Added SATA Link Reset settings, Enable SATA Asynchronous
+ *                      Notification bit, and HideNonZeroAttachedPhyIdentifiers
+ *                      bit to AdditionalControlFlags field of SAS IO Unit
+ *                      Page 1.
+ *                      Added defines for Enclosure Devices Unmapped and
+ *                      Device Limit Exceeded bits in Status field of SAS IO
+ *                      Unit Page 2.
+ *                      Added more AccessStatus values for SAS Device Page 0.
+ *                      Added bit for SATA Asynchronous Notification Support in
+ *                      Flags field of SAS Device Page 0.
  *  --------------------------------------------------------------------------
  */
 
@@ -654,17 +671,24 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4
 #define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA                 (0x01)
 
 
+#ifndef MPI_MANPAGE5_NUM_FORCEWWID
+#define MPI_MANPAGE5_NUM_FORCEWWID      (1)
+#endif
+
 typedef struct _CONFIG_PAGE_MANUFACTURING_5
 {
     CONFIG_PAGE_HEADER              Header;             /* 00h */
     U64                             BaseWWID;           /* 04h */
     U8                              Flags;              /* 0Ch */
-    U8                              Reserved1;          /* 0Dh */
+    U8                              NumForceWWID;       /* 0Dh */
     U16                             Reserved2;          /* 0Eh */
+    U32                             Reserved3;          /* 10h */
+    U32                             Reserved4;          /* 14h */
+    U64                             ForceWWID[MPI_MANPAGE5_NUM_FORCEWWID]; /* 18h */
 } CONFIG_PAGE_MANUFACTURING_5, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_5,
   ManufacturingPage5_t, MPI_POINTER pManufacturingPage5_t;
 
-#define MPI_MANUFACTURING5_PAGEVERSION                  (0x01)
+#define MPI_MANUFACTURING5_PAGEVERSION                  (0x02)
 
 /* defines for the Flags field */
 #define MPI_MANPAGE5_TWO_WWID_PER_PHY                   (0x01)
@@ -740,6 +764,36 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_7
 #define MPI_MANPAGE7_FLAG_USE_SLOT_INFO                 (0x00000001)
 
 
+typedef struct _CONFIG_PAGE_MANUFACTURING_8
+{
+    CONFIG_PAGE_HEADER              Header;             /* 00h */
+    U32                             ProductSpecificInfo;/* 04h */
+} CONFIG_PAGE_MANUFACTURING_8, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_8,
+  ManufacturingPage8_t, MPI_POINTER pManufacturingPage8_t;
+
+#define MPI_MANUFACTURING8_PAGEVERSION                  (0x00)
+
+
+typedef struct _CONFIG_PAGE_MANUFACTURING_9
+{
+    CONFIG_PAGE_HEADER              Header;             /* 00h */
+    U32                             ProductSpecificInfo;/* 04h */
+} CONFIG_PAGE_MANUFACTURING_9, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_9,
+  ManufacturingPage9_t, MPI_POINTER pManufacturingPage9_t;
+
+#define MPI_MANUFACTURING6_PAGEVERSION                  (0x00)
+
+
+typedef struct _CONFIG_PAGE_MANUFACTURING_10
+{
+    CONFIG_PAGE_HEADER              Header;             /* 00h */
+    U32                             ProductSpecificInfo;/* 04h */
+} CONFIG_PAGE_MANUFACTURING_10, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_10,
+  ManufacturingPage10_t, MPI_POINTER pManufacturingPage10_t;
+
+#define MPI_MANUFACTURING10_PAGEVERSION                 (0x00)
+
+
 /****************************************************************************
 *   IO Unit Config Pages
 ****************************************************************************/
@@ -1080,10 +1134,14 @@ typedef struct _CONFIG_PAGE_IOC_6
 } CONFIG_PAGE_IOC_6, MPI_POINTER PTR_CONFIG_PAGE_IOC_6,
   IOCPage6_t, MPI_POINTER pIOCPage6_t;
 
-#define MPI_IOCPAGE6_PAGEVERSION                        (0x00)
+#define MPI_IOCPAGE6_PAGEVERSION                        (0x01)
 
 /* IOC Page 6 Capabilities Flags */
 
+#define MPI_IOCPAGE6_CAP_FLAGS_MASK_METADATA_SIZE       (0x00000006)
+#define MPI_IOCPAGE6_CAP_FLAGS_64MB_METADATA_SIZE       (0x00000000)
+#define MPI_IOCPAGE6_CAP_FLAGS_512MB_METADATA_SIZE      (0x00000002)
+
 #define MPI_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE         (0x00000001)
 
 
@@ -2160,6 +2218,11 @@ typedef struct _RAID_VOL0_SETTINGS
 #define MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE             (0x0004)
 #define MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC            (0x0008)
 #define MPI_RAIDVOL0_SETTING_FAST_DATA_SCRUBBING_0102   (0x0020) /* obsolete */
+
+#define MPI_RAIDVOL0_SETTING_MASK_METADATA_SIZE         (0x00C0)
+#define MPI_RAIDVOL0_SETTING_64MB_METADATA_SIZE         (0x0000)
+#define MPI_RAIDVOL0_SETTING_512MB_METADATA_SIZE        (0x0040)
+
 #define MPI_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX      (0x0010)
 #define MPI_RAIDVOL0_SETTING_USE_DEFAULTS               (0x8000)
 
@@ -2203,7 +2266,7 @@ typedef struct _CONFIG_PAGE_RAID_VOL_0
 } CONFIG_PAGE_RAID_VOL_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_0,
   RaidVolumePage0_t, MPI_POINTER pRaidVolumePage0_t;
 
-#define MPI_RAIDVOLPAGE0_PAGEVERSION                    (0x06)
+#define MPI_RAIDVOLPAGE0_PAGEVERSION                    (0x07)
 
 /* values for RAID Volume Page 0 InactiveStatus field */
 #define MPI_RAIDVOLPAGE0_UNKNOWN_INACTIVE               (0x00)
@@ -2518,7 +2581,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
 } CONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1,
   SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t;
 
-#define MPI_SASIOUNITPAGE1_PAGEVERSION      (0x06)
+#define MPI_SASIOUNITPAGE1_PAGEVERSION      (0x07)
 
 /* values for SAS IO Unit Page 1 ControlFlags */
 #define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST            (0x8000)
@@ -2544,7 +2607,13 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
 #define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION           (0x0001)
 
 /* values for SAS IO Unit Page 1 AdditionalControlFlags */
-#define MPI_SAS_IOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE       (0x0001)
+#define MPI_SAS_IOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION    (0x0040)
+#define MPI_SAS_IOUNIT1_ACONTROL_HIDE_NONZERO_ATTACHED_PHY_IDENT    (0x0020)
+#define MPI_SAS_IOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET   (0x0010)
+#define MPI_SAS_IOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET  (0x0008)
+#define MPI_SAS_IOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET   (0x0004)
+#define MPI_SAS_IOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET     (0x0002)
+#define MPI_SAS_IOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE               (0x0001)
 
 /* defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */
 #define MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK         (0x7F)
@@ -2585,9 +2654,11 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
 } CONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2,
   SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t;
 
-#define MPI_SASIOUNITPAGE2_PAGEVERSION      (0x05)
+#define MPI_SASIOUNITPAGE2_PAGEVERSION      (0x06)
 
 /* values for SAS IO Unit Page 2 Status field */
+#define MPI_SAS_IOUNIT2_STATUS_DEVICE_LIMIT_EXCEEDED        (0x08)
+#define MPI_SAS_IOUNIT2_STATUS_ENCLOSURE_DEVICES_UNMAPPED   (0x04)
 #define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02)
 #define MPI_SAS_IOUNIT2_STATUS_FULL_PERSISTENT_MAPPINGS     (0x01)
 
@@ -2739,24 +2810,38 @@ typedef struct _CONFIG_PAGE_SAS_DEVICE_0
 } CONFIG_PAGE_SAS_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_0,
   SasDevicePage0_t, MPI_POINTER pSasDevicePage0_t;
 
-#define MPI_SASDEVICE0_PAGEVERSION          (0x04)
+#define MPI_SASDEVICE0_PAGEVERSION          (0x05)
 
 /* values for SAS Device Page 0 AccessStatus field */
-#define MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS               (0x00)
-#define MPI_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED        (0x01)
-#define MPI_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED  (0x02)
+#define MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS                   (0x00)
+#define MPI_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED            (0x01)
+#define MPI_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED      (0x02)
+#define MPI_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT   (0x03)
+/* specific values for SATA Init failures */
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN                 (0x10)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT    (0x11)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_DIAG                    (0x12)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION          (0x13)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER             (0x14)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_PIO_SN                  (0x15)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN                 (0x16)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN                 (0x17)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION        (0x18)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE         (0x19)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_MAX                     (0x1F)
 
 /* values for SAS Device Page 0 Flags field */
-#define MPI_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE          (0x0200)
-#define MPI_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE        (0x0100)
-#define MPI_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED  (0x0080)
-#define MPI_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED      (0x0040)
-#define MPI_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED        (0x0020)
-#define MPI_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED        (0x0010)
-#define MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH      (0x0008)
-#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT        (0x0004)
-#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED             (0x0002)
-#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT            (0x0001)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY      (0x0400)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE              (0x0200)
+#define MPI_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE            (0x0100)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED      (0x0080)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED          (0x0040)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED            (0x0020)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED            (0x0010)
+#define MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH          (0x0008)
+#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT            (0x0004)
+#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED                 (0x0002)
+#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT                (0x0001)
 
 /* see mpi_sas.h for values for SAS Device Page 0 DeviceInfo values */
 
diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt
index 582cfe7c2aa1..d6b4c607453b 100644
--- a/drivers/message/fusion/lsi/mpi_history.txt
+++ b/drivers/message/fusion/lsi/mpi_history.txt
@@ -3,28 +3,28 @@
  MPI Header File Change History
  ==============================
 
- Copyright (c) 2000-2005 LSI Logic Corporation.
+ Copyright (c) 2000-2006 LSI Logic Corporation.
 
  ---------------------------------------
- Header Set Release Version:    01.05.13
- Header Set Release Date:       03-27-06
+ Header Set Release Version:    01.05.14
+ Header Set Release Date:       10-11-06
  ---------------------------------------
 
  Filename               Current version     Prior version
  ----------             ---------------     -------------
- mpi.h                  01.05.11            01.05.10
- mpi_ioc.h              01.05.11            01.05.10
- mpi_cnfg.h             01.05.12            01.05.11
- mpi_init.h             01.05.07            01.05.06
- mpi_targ.h             01.05.06            01.05.05
+ mpi.h                  01.05.12            01.05.11
+ mpi_ioc.h              01.05.12            01.05.11
+ mpi_cnfg.h             01.05.13            01.05.12
+ mpi_init.h             01.05.08            01.05.07
+ mpi_targ.h             01.05.06            01.05.06
  mpi_fc.h               01.05.01            01.05.01
  mpi_lan.h              01.05.01            01.05.01
  mpi_raid.h             01.05.02            01.05.02
  mpi_tool.h             01.05.03            01.05.03
  mpi_inb.h              01.05.01            01.05.01
- mpi_sas.h              01.05.03            01.05.02
+ mpi_sas.h              01.05.04            01.05.03
  mpi_type.h             01.05.02            01.05.02
- mpi_history.txt        01.05.13            01.05.12
+ mpi_history.txt        01.05.14            01.05.13
 
 
  *  Date      Version   Description
@@ -94,6 +94,7 @@ mpi.h
  *  08-03-05  01.05.09  Bumped MPI_HEADER_VERSION_UNIT.
  *  08-30-05  01.05.10  Added 2 new IOCStatus codes for Target.
  *  03-27-06  01.05.11  Bumped MPI_HEADER_VERSION_UNIT.
+ *  10-11-06  01.05.12  Bumped MPI_HEADER_VERSION_UNIT.
  *  --------------------------------------------------------------------------
 
 mpi_ioc.h
@@ -182,6 +183,14 @@ mpi_ioc.h
  *                      Added MPI_EVENT_SAS_INIT_TABLE_OVERFLOW and event
  *                      data structure.
  *                      Added MPI_EXT_IMAGE_TYPE_INITIALIZATION.
+ *  10-11-06  01.05.12  Added MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED.
+ *                      Added MaxInitiators field to PortFacts reply.
+ *                      Added SAS Device Status Change ReasonCode for
+ *                      asynchronous notificaiton.
+ *                      Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event
+ *                      data structure.
+ *                      Added new ImageType values for FWDownload and FWUpload
+ *                      requests.
  *  --------------------------------------------------------------------------
 
 mpi_cnfg.h
@@ -447,6 +456,23 @@ mpi_cnfg.h
  *                      Added AdditionalControlFlags, MaxTargetPortConnectTime,
  *                      ReportDeviceMissingDelay, and IODeviceMissingDelay
  *                      fields to SAS IO Unit Page 1.
+ *  10-11-06  01.05.13  Added NumForceWWID field and ForceWWID array to
+ *                      Manufacturing Page 5.
+ *                      Added Manufacturing pages 8 through 10.
+ *                      Added defines for supported metadata size bits in
+ *                      CapabilitiesFlags field of IOC Page 6.
+ *                      Added defines for metadata size bits in VolumeSettings
+ *                      field of RAID Volume Page 0.
+ *                      Added SATA Link Reset settings, Enable SATA Asynchronous
+ *                      Notification bit, and HideNonZeroAttachedPhyIdentifiers
+ *                      bit to AdditionalControlFlags field of SAS IO Unit
+ *                      Page 1.
+ *                      Added defines for Enclosure Devices Unmapped and
+ *                      Device Limit Exceeded bits in Status field of SAS IO
+ *                      Unit Page 2.
+ *                      Added more AccessStatus values for SAS Device Page 0.
+ *                      Added bit for SATA Asynchronous Notification Support in
+ *                      Flags field of SAS Device Page 0.
  *  --------------------------------------------------------------------------
 
 mpi_init.h
@@ -490,6 +516,7 @@ mpi_init.h
  *  08-03-05  01.05.06  Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
  *                      unique in the first 32 characters.
  *  03-27-06  01.05.07  Added Task Management type of Clear ACA.
+ *  10-11-06  01.05.08  Shortened define for Task Management type of Clear ACA.
  *  --------------------------------------------------------------------------
 
 mpi_targ.h
@@ -638,6 +665,8 @@ mpi_sas.h
  *                      and Remove Device operations to SAS IO Unit Control.
  *                      Added DevHandle field to SAS IO Unit Control request and
  *                      reply.
+ *  10-11-06  01.05.04  Fixed the name of a define for Operation field of SAS IO
+ *                      Unit Control request.
  *  --------------------------------------------------------------------------
 
 mpi_type.h
@@ -653,20 +682,20 @@ mpi_type.h
 
 mpi_history.txt         Parts list history
 
-Filename    01.05.13  01.05.12  01.05.11  01.05.10  01.05.09
-----------  --------  --------  --------  --------  --------
-mpi.h       01.05.11  01.05.10  01.05.09  01.05.08  01.05.07
-mpi_ioc.h   01.05.11  01.05.10  01.05.09  01.05.09  01.05.08
-mpi_cnfg.h  01.05.12  01.05.11  01.05.10  01.05.09  01.05.08
-mpi_init.h  01.05.07  01.05.06  01.05.06  01.05.05  01.05.04
-mpi_targ.h  01.05.06  01.05.05  01.05.05  01.05.05  01.05.04
-mpi_fc.h    01.05.01  01.05.01  01.05.01  01.05.01  01.05.01
-mpi_lan.h   01.05.01  01.05.01  01.05.01  01.05.01  01.05.01
-mpi_raid.h  01.05.02  01.05.02  01.05.02  01.05.02  01.05.02
-mpi_tool.h  01.05.03  01.05.03  01.05.03  01.05.03  01.05.03
-mpi_inb.h   01.05.01  01.05.01  01.05.01  01.05.01  01.05.01
-mpi_sas.h   01.05.03  01.05.02  01.05.01  01.05.01  01.05.01
-mpi_type.h  01.05.02  01.05.02  01.05.01  01.05.01  01.05.01
+Filename    01.05.13   01.05.13   01.05.12   01.05.11   01.05.10   01.05.09
+----------  --------   --------   --------   --------   --------   --------
+mpi.h       01.05.12   01.05.11   01.05.10   01.05.09   01.05.08   01.05.07
+mpi_ioc.h   01.05.12   01.05.11   01.05.10   01.05.09   01.05.09   01.05.08
+mpi_cnfg.h  01.05.13   01.05.12   01.05.11   01.05.10   01.05.09   01.05.08
+mpi_init.h  01.05.08   01.05.07   01.05.06   01.05.06   01.05.05   01.05.04
+mpi_targ.h  01.05.06   01.05.06   01.05.05   01.05.05   01.05.05   01.05.04
+mpi_fc.h    01.05.01   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01
+mpi_lan.h   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01
+mpi_raid.h  01.05.02   01.05.02   01.05.02   01.05.02   01.05.02   01.05.02
+mpi_tool.h  01.05.03   01.05.03   01.05.03   01.05.03   01.05.03   01.05.03
+mpi_inb.h   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01
+mpi_sas.h   01.05.04   01.05.03   01.05.02   01.05.01   01.05.01   01.05.01
+mpi_type.h  01.05.02   01.05.02   01.05.02   01.05.01   01.05.01   01.05.01
 
 Filename    01.05.08   01.05.07   01.05.06   01.05.05   01.05.04   01.05.03
 ----------  --------   --------   --------   --------   --------   --------
diff --git a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h
index c1c678989a23..ec9dff2249a7 100644
--- a/drivers/message/fusion/lsi/mpi_init.h
+++ b/drivers/message/fusion/lsi/mpi_init.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2005 LSI Logic Corporation.
+ *  Copyright (c) 2000-2006 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_init.h
  *          Title:  MPI initiator mode messages and structures
  *  Creation Date:  June 8, 2000
  *
- *    mpi_init.h Version:  01.05.07
+ *    mpi_init.h Version:  01.05.08
  *
  *  Version History
  *  ---------------
@@ -53,6 +53,7 @@
  *  08-03-05  01.05.06  Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
  *                      unique in the first 32 characters.
  *  03-27-06  01.05.07  Added Task Management type of Clear ACA.
+ *  10-11-06  01.05.08  Shortened define for Task Management type of Clear ACA.
  *  --------------------------------------------------------------------------
  */
 
@@ -428,7 +429,7 @@ typedef struct _MSG_SCSI_TASK_MGMT
 #define MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET    (0x05)
 #define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET        (0x06)
 #define MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK            (0x07)
-#define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_ACA             (0x08)
+#define MPI_SCSITASKMGMT_TASKTYPE_CLR_ACA               (0x08)
 
 /* MsgFlags bits */
 #define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION   (0x00)
diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h
index 18ba407fd399..6c33e3353375 100644
--- a/drivers/message/fusion/lsi/mpi_ioc.h
+++ b/drivers/message/fusion/lsi/mpi_ioc.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2005 LSI Logic Corporation.
+ *  Copyright (c) 2000-2006 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_ioc.h
  *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
  *  Creation Date:  August 11, 2000
  *
- *    mpi_ioc.h Version:  01.05.11
+ *    mpi_ioc.h Version:  01.05.12
  *
  *  Version History
  *  ---------------
@@ -98,6 +98,14 @@
  *                      Added MPI_EVENT_SAS_INIT_TABLE_OVERFLOW and event
  *                      data structure.
  *                      Added MPI_EXT_IMAGE_TYPE_INITIALIZATION.
+ *  10-11-06  01.05.12  Added MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED.
+ *                      Added MaxInitiators field to PortFacts reply.
+ *                      Added SAS Device Status Change ReasonCode for
+ *                      asynchronous notificaiton.
+ *                      Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event
+ *                      data structure.
+ *                      Added new ImageType values for FWDownload and FWUpload
+ *                      requests.
  *  --------------------------------------------------------------------------
  */
 
@@ -264,6 +272,7 @@ typedef struct _MSG_IOC_FACTS_REPLY
 #define MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID         (0x0002)
 #define MPI_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL            (0x0004)
 #define MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL       (0x0008)
+#define MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED        (0x0010)
 
 #define MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT             (0x01)
 #define MPI_IOCFACTS_FLAGS_REPLY_FIFO_HOST_SIGNAL       (0x02)
@@ -328,7 +337,8 @@ typedef struct _MSG_PORT_FACTS_REPLY
      U16                    MaxPostedCmdBuffers;        /* 1Ch */
      U16                    MaxPersistentIDs;           /* 1Eh */
      U16                    MaxLanBuckets;              /* 20h */
-     U16                    Reserved4;                  /* 22h */
+     U8                     MaxInitiators;              /* 22h */
+     U8                     Reserved4;                  /* 23h */
      U32                    Reserved5;                  /* 24h */
 } MSG_PORT_FACTS_REPLY, MPI_POINTER PTR_MSG_PORT_FACTS_REPLY,
   PortFactsReply_t, MPI_POINTER pPortFactsReply_t;
@@ -487,6 +497,7 @@ typedef struct _MSG_EVENT_ACK_REPLY
 #define MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x00000018)
 #define MPI_EVENT_SAS_INIT_TABLE_OVERFLOW       (0x00000019)
 #define MPI_EVENT_SAS_SMP_ERROR                 (0x0000001A)
+#define MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE    (0x0000001B)
 #define MPI_EVENT_LOG_ENTRY_ADDED               (0x00000021)
 
 /* AckRequired field values */
@@ -593,6 +604,7 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
 #define MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL   (0x0A)
 #define MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL   (0x0B)
 #define MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL       (0x0C)
+#define MPI_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION        (0x0D)
 
 
 /* SCSI Event data for Queue Full event */
@@ -895,6 +907,54 @@ typedef struct _EVENT_DATA_SAS_INIT_TABLE_OVERFLOW
   MpiEventDataSasInitTableOverflow_t,
   MPI_POINTER pMpiEventDataSasInitTableOverflow_t;
 
+/* SAS Expander Status Change Event data */
+
+typedef struct _EVENT_DATA_SAS_EXPANDER_STATUS_CHANGE
+{
+    U8                      ReasonCode;             /* 00h */
+    U8                      Reserved1;              /* 01h */
+    U16                     Reserved2;              /* 02h */
+    U8                      PhysicalPort;           /* 04h */
+    U8                      Reserved3;              /* 05h */
+    U16                     EnclosureHandle;        /* 06h */
+    U64                     SASAddress;             /* 08h */
+    U32                     DiscoveryStatus;        /* 10h */
+    U16                     DevHandle;              /* 14h */
+    U16                     ParentDevHandle;        /* 16h */
+    U16                     ExpanderChangeCount;    /* 18h */
+    U16                     ExpanderRouteIndexes;   /* 1Ah */
+    U8                      NumPhys;                /* 1Ch */
+    U8                      SASLevel;               /* 1Dh */
+    U8                      Flags;                  /* 1Eh */
+    U8                      Reserved4;              /* 1Fh */
+} EVENT_DATA_SAS_EXPANDER_STATUS_CHANGE,
+  MPI_POINTER PTR_EVENT_DATA_SAS_EXPANDER_STATUS_CHANGE,
+  MpiEventDataSasExpanderStatusChange_t,
+  MPI_POINTER pMpiEventDataSasExpanderStatusChange_t;
+
+/* values for ReasonCode field of SAS Expander Status Change Event data */
+#define MPI_EVENT_SAS_EXP_RC_ADDED                      (0x00)
+#define MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING             (0x01)
+
+/* values for DiscoveryStatus field of SAS Expander Status Change Event data */
+#define MPI_EVENT_SAS_EXP_DS_LOOP_DETECTED              (0x00000001)
+#define MPI_EVENT_SAS_EXP_DS_UNADDRESSABLE_DEVICE       (0x00000002)
+#define MPI_EVENT_SAS_EXP_DS_MULTIPLE_PORTS             (0x00000004)
+#define MPI_EVENT_SAS_EXP_DS_EXPANDER_ERR               (0x00000008)
+#define MPI_EVENT_SAS_EXP_DS_SMP_TIMEOUT                (0x00000010)
+#define MPI_EVENT_SAS_EXP_DS_OUT_ROUTE_ENTRIES          (0x00000020)
+#define MPI_EVENT_SAS_EXP_DS_INDEX_NOT_EXIST            (0x00000040)
+#define MPI_EVENT_SAS_EXP_DS_SMP_FUNCTION_FAILED        (0x00000080)
+#define MPI_EVENT_SAS_EXP_DS_SMP_CRC_ERROR              (0x00000100)
+#define MPI_EVENT_SAS_EXP_DS_SUBTRACTIVE_LINK           (0x00000200)
+#define MPI_EVENT_SAS_EXP_DS_TABLE_LINK                 (0x00000400)
+#define MPI_EVENT_SAS_EXP_DS_UNSUPPORTED_DEVICE         (0x00000800)
+
+/* values for Flags field of SAS Expander Status Change Event data */
+#define MPI_EVENT_SAS_EXP_FLAGS_ROUTE_TABLE_CONFIG      (0x02)
+#define MPI_EVENT_SAS_EXP_FLAGS_CONFIG_IN_PROGRESS      (0x01)
+
+
 
 /*****************************************************************************
 *
@@ -926,6 +986,10 @@ typedef struct _MSG_FW_DOWNLOAD
 #define MPI_FW_DOWNLOAD_ITYPE_BIOS              (0x02)
 #define MPI_FW_DOWNLOAD_ITYPE_NVDATA            (0x03)
 #define MPI_FW_DOWNLOAD_ITYPE_BOOTLOADER        (0x04)
+#define MPI_FW_DOWNLOAD_ITYPE_MANUFACTURING     (0x06)
+#define MPI_FW_DOWNLOAD_ITYPE_CONFIG_1          (0x07)
+#define MPI_FW_DOWNLOAD_ITYPE_CONFIG_2          (0x08)
+#define MPI_FW_DOWNLOAD_ITYPE_MEGARAID          (0x09)
 
 
 typedef struct _FWDownloadTCSGE
@@ -980,6 +1044,11 @@ typedef struct _MSG_FW_UPLOAD
 #define MPI_FW_UPLOAD_ITYPE_NVDATA          (0x03)
 #define MPI_FW_UPLOAD_ITYPE_BOOTLOADER      (0x04)
 #define MPI_FW_UPLOAD_ITYPE_FW_BACKUP       (0x05)
+#define MPI_FW_UPLOAD_ITYPE_MANUFACTURING   (0x06)
+#define MPI_FW_UPLOAD_ITYPE_CONFIG_1        (0x07)
+#define MPI_FW_UPLOAD_ITYPE_CONFIG_2        (0x08)
+#define MPI_FW_UPLOAD_ITYPE_MEGARAID        (0x09)
+#define MPI_FW_UPLOAD_ITYPE_COMPLETE        (0x0A)
 
 typedef struct _FWUploadTCSGE
 {
diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h
index 871ebc08b706..635bbe04513e 100644
--- a/drivers/message/fusion/lsi/mpi_log_sas.h
+++ b/drivers/message/fusion/lsi/mpi_log_sas.h
@@ -1,4 +1,3 @@
-
 /***************************************************************************
  *                                                                         *
  *  Copyright 2003 LSI Logic Corporation.  All rights reserved.            *
@@ -14,7 +13,7 @@
 #define IOPI_IOCLOGINFO_H_INCLUDED
 
 #define SAS_LOGINFO_NEXUS_LOSS		0x31170000
-#define SAS_LOGINFO_MASK			0xFFFF0000
+#define SAS_LOGINFO_MASK		0xFFFF0000
 
 /****************************************************************************/
 /*  IOC LOGINFO defines, 0x00000000 - 0x0FFFFFFF                            */
@@ -43,129 +42,172 @@
 /****************************************************************************/
 /* IOP LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IOP          */
 /****************************************************************************/
-#define IOP_LOGINFO_CODE_INVALID_SAS_ADDRESS            (0x00010000)
-#define IOP_LOGINFO_CODE_UNUSED2                        (0x00020000)
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE            (0x00030000)
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_RT         (0x00030100) /* Route Table Entry not found */
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PN         (0x00030200) /* Invalid Page Number */
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM       (0x00030300) /* Invalid FORM */
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT         (0x00030400) /* Invalid Page Type */
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM        (0x00030500) /* Device Not Mapped */
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST    (0x00030600) /* Persistent Page not found */
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT    (0x00030700) /* Default Page not found */
-
-#define IOP_LOGINFO_CODE_DIAG_MSG_ERROR                 (0x00040000) /* Error handling diag msg - or'd with diag status */
-
-#define IOP_LOGINFO_CODE_TASK_TERMINATED                (0x00050000)
-
-#define IOP_LOGINFO_CODE_ENCL_MGMT_READ_ACTION_ERR0R    (0x00060001) /* Read Action not supported for SEP msg */
-#define IOP_LOGINFO_CODE_ENCL_MGMT_INVALID_BUS_ID_ERR0R (0x00060002) /* Invalid Bus/ID in SEP msg */
-
-#define IOP_LOGINFO_CODE_TARGET_ASSIST_TERMINATED       (0x00070001)
-#define IOP_LOGINFO_CODE_TARGET_STATUS_SEND_TERMINATED  (0x00070002)
-#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_ALL_IO       (0x00070003)
-#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO     (0x00070004)
-#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO_REQ (0x00070005)
+#define IOP_LOGINFO_CODE_INVALID_SAS_ADDRESS                 (0x00010000)
+#define IOP_LOGINFO_CODE_UNUSED2                             (0x00020000)
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE                 (0x00030000)
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_RT              (0x00030100) /* Route Table Entry not found */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PN              (0x00030200) /* Invalid Page Number */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM            (0x00030300) /* Invalid FORM */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT              (0x00030400) /* Invalid Page Type */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM             (0x00030500) /* Device Not Mapped */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST         (0x00030600) /* Persistent Page not found */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT         (0x00030700) /* Default Page not found */
+
+#define IOP_LOGINFO_CODE_FWUPLOAD_NO_FLASH_AVAILABLE         (0x0003E000) /* Tried to upload from flash, but there is none */
+#define IOP_LOGINFO_CODE_FWUPLOAD_UNKNOWN_IMAGE_TYPE         (0x0003E001) /* ImageType field contents were invalid */
+#define IOP_LOGINFO_CODE_FWUPLOAD_WRONG_IMAGE_SIZE           (0x0003E002) /* ImageSize field in TCSGE was bad/offset in MfgPg 4 was wrong */
+#define IOP_LOGINFO_CODE_FWUPLOAD_ENTIRE_FLASH_UPLOAD_FAILED (0x0003E003) /* Error occured while attempting to upload the entire flash */
+#define IOP_LOGINFO_CODE_FWUPLOAD_REGION_UPLOAD_FAILED       (0x0003E004) /* Error occured while attempting to upload single flash region */
+#define IOP_LOGINFO_CODE_FWUPLOAD_DMA_FAILURE                (0x0003E005) /* Problem occured while DMAing FW to host memory */
+
+#define IOP_LOGINFO_CODE_DIAG_MSG_ERROR                      (0x00040000) /* Error handling diag msg - or'd with diag status */
+
+#define IOP_LOGINFO_CODE_TASK_TERMINATED                     (0x00050000)
+
+#define IOP_LOGINFO_CODE_ENCL_MGMT_READ_ACTION_ERR0R         (0x00060001) /* Read Action not supported for SEP msg */
+#define IOP_LOGINFO_CODE_ENCL_MGMT_INVALID_BUS_ID_ERR0R      (0x00060002) /* Invalid Bus/ID in SEP msg */
+
+#define IOP_LOGINFO_CODE_TARGET_ASSIST_TERMINATED            (0x00070001)
+#define IOP_LOGINFO_CODE_TARGET_STATUS_SEND_TERMINATED       (0x00070002)
+#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_ALL_IO            (0x00070003)
+#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO          (0x00070004)
+#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO_REQ      (0x00070005)
 
 /****************************************************************************/
 /* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL            */
 /****************************************************************************/
-#define PL_LOGINFO_CODE_OPEN_FAILURE                        (0x00010000)
-#define PL_LOG_INFO_CODE_OPEN_FAILURE_NO_DEST_TIME_OUT      (0x00010001)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_BAD_DESTINATION        (0x00010011)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_PROTOCOL_NOT_SUPPORTED (0x00010013)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_STP_RESOURCES_BSY      (0x00010018)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_WRONG_DESTINATION      (0x00010019)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_ORR_TIMEOUT            (0X0001001A)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_PATHWAY_BLOCKED        (0x0001001B)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_AWT_MAXED              (0x0001001C)
-#define PL_LOGINFO_CODE_INVALID_SGL                         (0x00020000)
-#define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH       (0x00030000)
-#define PL_LOGINFO_CODE_FRAME_XFER_ERROR                    (0x00040000)
-#define PL_LOGINFO_CODE_TX_FM_CONNECTED_LOW                 (0x00050000)
-#define PL_LOGINFO_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET         (0x00060000)
-#define PL_LOGINFO_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR      (0x00070000)
-#define PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR     (0x00080000)
-#define PL_LOGINFO_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS     (0x00090000)
-#define PL_LOGINFO_CODE_RX_FM_INVALID_MESSAGE               (0x000A0000)
-#define PL_LOGINFO_CODE_RX_CTX_MESSAGE_VALID_ERROR          (0x000B0000)
-#define PL_LOGINFO_CODE_RX_FM_CURRENT_FRAME_ERROR           (0x000C0000)
-#define PL_LOGINFO_CODE_SATA_LINK_DOWN                      (0x000D0000)
-#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS           (0x000E0000)
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE                 (0x000F0000)
-#define PL_LOGINFO_CODE_CONFIG_PL_NOT_INITIALIZED           (0x000F0001) /* PL not yet initialized, can't do config page req. */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT              (0x000F0100) /* Invalid Page Type */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS        (0x000F0200) /* Invalid Number of Phys */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP         (0x000F0300) /* Case Not Handled */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_DEV          (0x000F0400) /* No Device Found */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM            (0x000F0500) /* Invalid FORM */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY             (0x000F0600) /* Invalid Phy */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER        (0x000F0700) /* No Owner Found */
-#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT            (0x00100000)
-#define PL_LOGINFO_CODE_RESET                               (0x00110000) /* See Sub-Codes below */
-#define PL_LOGINFO_CODE_ABORT                               (0x00120000) /* See Sub-Codes below */
-#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED                 (0x00130000)
-#define PL_LOGINFO_CODE_IO_EXECUTED                         (0x00140000)
-#define PL_LOGINFO_CODE_PERS_RESV_OUT_NOT_AFFIL_OWNER       (0x00150000)
-#define PL_LOGINFO_CODE_OPEN_TXDMA_ABORT                    (0x00160000)
-#define PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY       (0x00170000)
-#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE                    (0x00000100)
-#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_NO_DEST_TIMEOUT    (0x00000101)
-#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ORR_TIMEOUT        (0x0000011A) /* Open Reject (Retry) Timeout */
-#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_PATHWAY_BLOCKED    (0x0000011B)
-#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_AWT_MAXED          (0x0000011C) /* Arbitration Wait Timer Maxed */
-
-#define PL_LOGINFO_SUB_CODE_TARGET_BUS_RESET                (0x00000120)
-#define PL_LOGINFO_SUB_CODE_TRANSPORT_LAYER                 (0x00000130)  /* Leave lower nibble (1-f) reserved. */
-#define PL_LOGINFO_SUB_CODE_PORT_LAYER                      (0x00000140)  /* Leave lower nibble (1-f) reserved. */
-
-
-#define PL_LOGINFO_SUB_CODE_INVALID_SGL                     (0x00000200)
-#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH   (0x00000300)
-#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR                (0x00000400)
-#define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW             (0x00000500)
-#define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET     (0x00000600)
-#define PL_LOGINFO_SUB_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR  (0x00000700)
-#define PL_LOGINFO_SUB_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00000800)
-#define PL_LOGINFO_SUB_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00000900)
-#define PL_LOGINFO_SUB_CODE_RX_FM_INVALID_MESSAGE           (0x00000A00)
-#define PL_LOGINFO_SUB_CODE_RX_CTX_MESSAGE_VALID_ERROR      (0x00000B00)
-#define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR       (0x00000C00)
-#define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN                  (0x00000D00)
-#define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS       (0x00000E00)
-#define PL_LOGINFO_SUB_CODE_DISCOVERY_REMOTE_SEP_RESET      (0x00000E01)
-#define PL_LOGINFO_SUB_CODE_SECOND_OPEN                     (0x00000F00)
-#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT        (0x00001000)
-
-
-#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE         (0x00200000) /* Can't get SMP Frame */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR            (0x00200010) /* Error occured on SMP Read */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR           (0x00200020) /* Error occured on SMP Write */
-#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL     (0x00200040) /* Encl Mgmt services not available for this WWID */
-#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED   (0x00200050) /* Address Mode not suppored */
-#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM              (0x00200060) /* Invalid Slot Number in SEP Msg */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT         (0x00200070) /* SGPIO not present/enabled */
-#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_NOT_CONFIGURED       (0x00200080) /* GPIO not configured */
-#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_FRAME_ERROR          (0x00200090) /* GPIO can't allocate a frame */
-#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_CONFIG_PAGE_ERROR    (0x002000A0) /* GPIO failed config page request */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SES_FRAME_ALLOC_ERROR     (0x002000B0) /* Can't get frame for SES command */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SES_IO_ERROR              (0x002000C0) /* I/O execution error */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SES_RETRIES_EXHAUSTED     (0x002000D0) /* SEP I/O retries exhausted */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_ALLOC_ERROR     (0x002000E0) /* Can't get frame for SMP command */
-
-#define PL_LOGINFO_DA_SEP_NOT_PRESENT                       (0x00200100) /* SEP not present when msg received */
-#define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR               (0x00200101) /* Can only accept 1 msg at a time */
-#define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE          (0x00200102) /* ISTWI interrupt recvd. while IDLE */
-#define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE          (0x00200103) /* SEP NACK'd, it is busy */
-#define PL_LOGINFO_DA_SEP_DID_NOT_RECEIVE_ACK               (0x00200104) /* SEP didn't rcv. ACK (Last Rcvd Bit = 1) */
-#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM             (0x00200105) /* SEP stopped or sent bad chksum in Hdr */
-#define PL_LOGINFO_DA_SEP_STOP_ON_DATA                      (0x00200106) /* SEP stopped while transfering data */
-#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA                (0x00200107) /* SEP stopped while transfering sense data */
-#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1         (0x00200108) /* SEP returned unknown scsi status */
-#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2         (0x00200109) /* SEP returned unknown scsi status */
-#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP           (0x0020010A) /* SEP returned bad chksum after STOP */
-#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA   (0x0020010B) /* SEP returned bad chksum after STOP while gettin data*/
-#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND               (0x0020010C) /* SEP doesn't support CDB opcode */
+#define PL_LOGINFO_CODE_OPEN_FAILURE                         (0x00010000) /* see SUB_CODE_OPEN_FAIL_ below */
+
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_NO_DEST_TIME_OUT       (0x00000001)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_PATHWAY_BLOCKED        (0x00000002)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_CONTINUE0          (0x00000003)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_CONTINUE1          (0x00000004)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_INITIALIZE0        (0x00000005)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_INITIALIZE1        (0x00000006)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_STOP0              (0x00000007)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_STOP1              (0x00000008)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RETRY                  (0x00000009)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_BREAK                  (0x0000000A)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_UNUSED_0B              (0x0000000B)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_OPEN_TIMEOUT_EXP       (0x0000000C)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_UNUSED_0D              (0x0000000D)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_DVTBLE_ACCSS_FAIL      (0x0000000E)
+#define PL_LOGINFO_SUB CODE_OPEN_FAIL_BAD_DEST               (0x00000011)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RATE_NOT_SUPP          (0x00000012)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_PROT_NOT_SUPP          (0x00000013)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON0      (0x00000014)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON1      (0x00000015)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON2      (0x00000016)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON3      (0x00000017)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_STP_RESOURCES_BSY      (0x00000018)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_WRONG_DESTINATION      (0x00000019)
+
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_PATH_BLOCKED           (0x0000001B) /* Retry Timeout */
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_AWT_MAXED              (0x0000001C) /* Retry Timeout */
+
+
+
+#define PL_LOGINFO_CODE_INVALID_SGL                          (0x00020000)
+#define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH        (0x00030000)
+#define PL_LOGINFO_CODE_FRAME_XFER_ERROR                     (0x00040000)
+#define PL_LOGINFO_CODE_TX_FM_CONNECTED_LOW                  (0x00050000)
+#define PL_LOGINFO_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET          (0x00060000)
+#define PL_LOGINFO_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR       (0x00070000)
+#define PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR      (0x00080000)
+#define PL_LOGINFO_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS      (0x00090000)
+#define PL_LOGINFO_CODE_RX_FM_INVALID_MESSAGE                (0x000A0000)
+#define PL_LOGINFO_CODE_RX_CTX_MESSAGE_VALID_ERROR           (0x000B0000)
+#define PL_LOGINFO_CODE_RX_FM_CURRENT_FRAME_ERROR            (0x000C0000)
+#define PL_LOGINFO_CODE_SATA_LINK_DOWN                       (0x000D0000)
+#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS            (0x000E0000)
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE                  (0x000F0000)
+#define PL_LOGINFO_CODE_CONFIG_PL_NOT_INITIALIZED            (0x000F0001) /* PL not yet initialized, can't do config page req. */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT               (0x000F0100) /* Invalid Page Type */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS         (0x000F0200) /* Invalid Number of Phys */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP          (0x000F0300) /* Case Not Handled */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_DEV           (0x000F0400) /* No Device Found */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM             (0x000F0500) /* Invalid FORM */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY              (0x000F0600) /* Invalid Phy */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER         (0x000F0700) /* No Owner Found */
+#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT             (0x00100000)
+#define PL_LOGINFO_CODE_RESET                                (0x00110000) /* See Sub-Codes below (PL_LOGINFO_SUB_CODE) */
+#define PL_LOGINFO_CODE_ABORT                                (0x00120000) /* See Sub-Codes below  (PL_LOGINFO_SUB_CODE)*/
+#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED                  (0x00130000)
+#define PL_LOGINFO_CODE_IO_EXECUTED                          (0x00140000)
+#define PL_LOGINFO_CODE_PERS_RESV_OUT_NOT_AFFIL_OWNER        (0x00150000)
+#define PL_LOGINFO_CODE_OPEN_TXDMA_ABORT                     (0x00160000)
+#define PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY        (0x00170000)
+#define PL_LOGINFO_CODE_IO_CANCELLED_DUE_TO_R_ERR            (0x00180000)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE                     (0x00000100)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_NO_DEST_TIMEOUT     (0x00000101)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_SATA_NEG_RATE_2HI   (0x00000102)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_RATE_NOT_SUPPORTED  (0x00000103)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_BREAK               (0x00000104)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ZONE_VIOLATION      (0x00000114)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON0            (0x00000114) /* Open Reject (Zone Violation) - available on SAS-2 devices */
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON1            (0x00000115)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON2            (0x00000116)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON3            (0x00000117)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ORR_TIMEOUT         (0x0000011A) /* Open Reject (Retry) Timeout */
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_PATH_BLOCKED        (0x0000011B)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_AWT_MAXED           (0x0000011C) /* Arbitration Wait Timer Maxed */
+
+#define PL_LOGINFO_SUB_CODE_TARGET_BUS_RESET                 (0x00000120)
+#define PL_LOGINFO_SUB_CODE_TRANSPORT_LAYER                  (0x00000130)  /* Leave lower nibble (1-f) reserved. */
+#define PL_LOGINFO_SUB_CODE_PORT_LAYER                       (0x00000140)  /* Leave lower nibble (1-f) reserved. */
+
+
+#define PL_LOGINFO_SUB_CODE_INVALID_SGL                      (0x00000200)
+#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH    (0x00000300)
+#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR                 (0x00000400) /* Bits 0-3 encode Transport Status Register (offset 0x08) */
+                                                                          /* Bit 0 is Status Bit 0: FrameXferErr */
+                                                                          /* Bit 1 & 2 are Status Bits 16 and 17: FrameXmitErrStatus */
+                                                                          /* Bit 3 is Status Bit 18 WriteDataLenghtGTDataLengthErr */
+
+#define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW              (0x00000500)
+#define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET      (0x00000600)
+#define PL_LOGINFO_SUB_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR   (0x00000700)
+#define PL_LOGINFO_SUB_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR  (0x00000800)
+#define PL_LOGINFO_SUB_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS  (0x00000900)
+#define PL_LOGINFO_SUB_CODE_RX_FM_INVALID_MESSAGE            (0x00000A00)
+#define PL_LOGINFO_SUB_CODE_RX_CTX_MESSAGE_VALID_ERROR       (0x00000B00)
+#define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR        (0x00000C00)
+#define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN                   (0x00000D00)
+#define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS        (0x00000E00)
+#define PL_LOGINFO_SUB_CODE_DISCOVERY_REMOTE_SEP_RESET       (0x00000E01)
+#define PL_LOGINFO_SUB_CODE_SECOND_OPEN                      (0x00000F00)
+#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT         (0x00001000)
+
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE          (0x00200000) /* Can't get SMP Frame */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR             (0x00200010) /* Error occured on SMP Read */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR            (0x00200020) /* Error occured on SMP Write */
+#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL      (0x00200040) /* Encl Mgmt services not available for this WWID */
+#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED    (0x00200050) /* Address Mode not suppored */
+#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM               (0x00200060) /* Invalid Slot Number in SEP Msg */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT          (0x00200070) /* SGPIO not present/enabled */
+#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_NOT_CONFIGURED        (0x00200080) /* GPIO not configured */
+#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_FRAME_ERROR           (0x00200090) /* GPIO can't allocate a frame */
+#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_CONFIG_PAGE_ERROR     (0x002000A0) /* GPIO failed config page request */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SES_FRAME_ALLOC_ERROR      (0x002000B0) /* Can't get frame for SES command */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SES_IO_ERROR               (0x002000C0) /* I/O execution error */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SES_RETRIES_EXHAUSTED      (0x002000D0) /* SEP I/O retries exhausted */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_ALLOC_ERROR      (0x002000E0) /* Can't get frame for SMP command */
+
+#define PL_LOGINFO_DA_SEP_NOT_PRESENT                        (0x00200100) /* SEP not present when msg received */
+#define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR                (0x00200101) /* Can only accept 1 msg at a time */
+#define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE           (0x00200102) /* ISTWI interrupt recvd. while IDLE */
+#define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE           (0x00200103) /* SEP NACK'd, it is busy */
+#define PL_LOGINFO_DA_SEP_DID_NOT_RECEIVE_ACK                (0x00200104) /* SEP didn't rcv. ACK (Last Rcvd Bit = 1) */
+#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM              (0x00200105) /* SEP stopped or sent bad chksum in Hdr */
+#define PL_LOGINFO_DA_SEP_STOP_ON_DATA                       (0x00200106) /* SEP stopped while transfering data */
+#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA                 (0x00200107) /* SEP stopped while transfering sense data */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1          (0x00200108) /* SEP returned unknown scsi status */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2          (0x00200109) /* SEP returned unknown scsi status */
+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP            (0x0020010A) /* SEP returned bad chksum after STOP */
+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA    (0x0020010B) /* SEP returned bad chksum after STOP while gettin data*/
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND                (0x0020010C) /* SEP doesn't support CDB opcode f/w location 1 */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND_2              (0x0020010D) /* SEP doesn't support CDB opcode f/w location 2 */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND_3              (0x0020010E) /* SEP doesn't support CDB opcode f/w location 3 */
 
 
 /****************************************************************************/
diff --git a/drivers/message/fusion/lsi/mpi_sas.h b/drivers/message/fusion/lsi/mpi_sas.h
index 50b8f0a8f456..8e990a0fa7a2 100644
--- a/drivers/message/fusion/lsi/mpi_sas.h
+++ b/drivers/message/fusion/lsi/mpi_sas.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2004 LSI Logic Corporation.
+ *  Copyright (c) 2004-2006 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_sas.h
  *          Title:  MPI Serial Attached SCSI structures and definitions
  *  Creation Date:  August 19, 2004
  *
- *    mpi_sas.h Version:  01.05.03
+ *    mpi_sas.h Version:  01.05.04
  *
  *  Version History
  *  ---------------
@@ -21,6 +21,8 @@
  *                      and Remove Device operations to SAS IO Unit Control.
  *                      Added DevHandle field to SAS IO Unit Control request and
  *                      reply.
+ *  10-11-06  01.05.04  Fixed the name of a define for Operation field of SAS IO
+ *                      Unit Control request.
  *  --------------------------------------------------------------------------
  */
 
@@ -237,7 +239,8 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST
 #define MPI_SAS_OP_SEND_PRIMITIVE               (0x0A)
 #define MPI_SAS_OP_FORCE_FULL_DISCOVERY         (0x0B)
 #define MPI_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL  (0x0C)
-#define MPI_SAS_OP_TRANSMIT_REMOVE_DEVICE       (0x0D)
+#define MPI_SAS_OP_TRANSMIT_REMOVE_DEVICE       (0x0D)  /* obsolete name */
+#define MPI_SAS_OP_REMOVE_DEVICE                (0x0D)
 
 /* values for the PrimFlags field */
 #define MPI_SAS_PRIMFLAGS_SINGLE                (0x08)
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index b3f28a03b6a9..083acfd91d8b 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -6,7 +6,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -82,6 +82,10 @@ static int mpt_msi_enable;
 module_param(mpt_msi_enable, int, 0);
 MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
 
+static int mpt_channel_mapping;
+module_param(mpt_channel_mapping, int, 0);
+MODULE_PARM_DESC(mpt_channel_mapping, " Mapping id's to channels (default=0)");
+
 #ifdef MFCNT
 static int mfcounter = 0;
 #define PRINT_MF_COUNT 20000
@@ -173,11 +177,14 @@ static void	mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
 
 //int		mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
 static int	ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
-static void	mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
+#ifdef MPT_DEBUG_REPLY
+static void	mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
+#endif
 static void	mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
 static void	mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
 static void	mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
 static int	mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
+static void	mpt_inactive_raid_list_free(MPT_ADAPTER *ioc);
 
 /* module entry point */
 static int  __init    fusion_init  (void);
@@ -319,13 +326,11 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
 		else if (ioc->bus_type == SAS)
 			mpt_sas_log_info(ioc, log_info);
 	}
-	if (ioc_stat & MPI_IOCSTATUS_MASK) {
-		if (ioc->bus_type == SPI &&
-		    cb_idx != mpt_stm_index &&
-		    cb_idx != mpt_lan_index)
-			mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
-	}
 
+#ifdef MPT_DEBUG_REPLY
+	if (ioc_stat & MPI_IOCSTATUS_MASK)
+		mpt_iocstatus_info(ioc, (u32)ioc_stat, mf);
+#endif
 
 	/*  Check for (valid) IO callback!  */
 	if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
@@ -911,7 +916,7 @@ mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
 int
 mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
 {
-	int		 r = 0;
+	int	r = 0;
 	u8	*req_as_bytes;
 	int	 ii;
 
@@ -1811,6 +1816,13 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 	 *	and we try GetLanConfigPages again...
 	 */
 	if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
+
+		/*
+		 * Initalize link list for inactive raid volumes.
+		 */
+		init_MUTEX(&ioc->raid_data.inactive_list_mutex);
+		INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
+
 		if (ioc->bus_type == SAS) {
 
 			/* clear persistency table */
@@ -2017,6 +2029,8 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
 	}
 
 	kfree(ioc->spi_data.nvram);
+	mpt_inactive_raid_list_free(ioc);
+	kfree(ioc->raid_data.pIocPg2);
 	kfree(ioc->raid_data.pIocPg3);
 	ioc->spi_data.nvram = NULL;
 	ioc->raid_data.pIocPg3 = NULL;
@@ -2413,6 +2427,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
 			facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
 
 		facts->ProductID = le16_to_cpu(facts->ProductID);
+		if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
+		    > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
+			ioc->ir_firmware = 1;
 		facts->CurrentHostMfaHighAddr =
 				le32_to_cpu(facts->CurrentHostMfaHighAddr);
 		facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
@@ -2505,6 +2522,7 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
 	int			 ii;
 	int			 req_sz;
 	int			 reply_sz;
+	int			 max_id;
 
 	/* IOC *must* NOT be in RESET state! */
 	if (ioc->last_state == MPI_IOC_STATE_RESET) {
@@ -2552,6 +2570,21 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
 	pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
 	pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
 
+	max_id = (ioc->bus_type == SAS) ? pfacts->PortSCSIID :
+	    pfacts->MaxDevices;
+	ioc->devices_per_bus = (max_id > 255) ? 256 : max_id;
+	ioc->number_of_buses = (ioc->devices_per_bus < 256) ? 1 : max_id/256;
+
+	/*
+	 * Place all the devices on channels
+	 *
+	 * (for debuging)
+	 */
+	if (mpt_channel_mapping) {
+		ioc->devices_per_bus = 1;
+		ioc->number_of_buses = (max_id > 255) ? 255 : max_id;
+	}
+
 	return 0;
 }
 
@@ -2592,13 +2625,8 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
 	ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
 		   ioc->name, ioc->upload_fw, ioc->facts.Flags));
 
-	if(ioc->bus_type == SAS)
-		ioc_init.MaxDevices = ioc->facts.MaxDevices;
-	else if(ioc->bus_type == FC)
-		ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
-	else
-		ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
-	ioc_init.MaxBuses = MPT_MAX_BUS;
+	ioc_init.MaxDevices = (U8)ioc->devices_per_bus;
+	ioc_init.MaxBuses = (U8)ioc->number_of_buses;
 	dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
 		   ioc->name, ioc->facts.MsgVersion));
 	if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
@@ -2720,9 +2748,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
 
 	/* RAID FW may take a long time to enable
 	 */
-	if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
-	    > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
-	    (ioc->bus_type == SAS)) {
+	if (ioc->ir_firmware || ioc->bus_type == SAS) {
 		rc = mpt_handshake_req_reply_wait(ioc, req_sz,
 		(u32*)&port_enable, reply_sz, (u16*)&reply_buf,
 		300 /*seconds*/, sleepFlag);
@@ -3193,6 +3219,9 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
 	u32 diag1val = 0;
 #endif
 
+	/* Clear any existing interrupts */
+	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+
 	if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
 		drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
 			"address=%p\n",  ioc->name, __FUNCTION__,
@@ -3212,7 +3241,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
 			        " count=%d\n",
 				ioc->name, doorbell, count));
 			if (doorbell == MPI_IOC_STATE_READY) {
-				return 0;
+				return 1;
 			}
 
 			/* wait 1 sec */
@@ -3224,9 +3253,6 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
 		return -1;
 	}
 
-	/* Clear any existing interrupts */
-	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
-
 	/* Use "Diagnostic reset" method! (only thing available!) */
 	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
 
@@ -3942,7 +3968,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
 		}
 	} else {
 		while (--cntdn) {
-			mdelay (1);
+			udelay (1000);
 			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
 			if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
 				break;
@@ -3994,7 +4020,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
 			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
 			if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
 				break;
-			mdelay(1);
+			udelay (1000);
 			count++;
 		}
 	}
@@ -4310,8 +4336,8 @@ mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
 	if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
 	     reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
 	    (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
-		printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n",
-			ioc->name, disk);
+		printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d id=%d\n",
+			ioc->name, disk, volume);
 	} else {
 		printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
 			ioc->name, volume);
@@ -4712,7 +4738,187 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
 	return 0;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mpt_inactive_raid_list_free
+ *
+ * This clears this link list.
+ *
+ * @ioc - pointer to per adapter structure
+ *
+ **/
+static void
+mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
+{
+	struct inactive_raid_component_info *component_info, *pNext;
+
+	if (list_empty(&ioc->raid_data.inactive_list))
+		return;
+
+	down(&ioc->raid_data.inactive_list_mutex);
+	list_for_each_entry_safe(component_info, pNext,
+	    &ioc->raid_data.inactive_list, list) {
+		list_del(&component_info->list);
+		kfree(component_info);
+	}
+	up(&ioc->raid_data.inactive_list_mutex);
+}
+
+/**
+ * mpt_inactive_raid_volumes
+ *
+ * This sets up link list of phy_disk_nums for devices belonging in an inactive volume
+ *
+ * @ioc - pointer to per adapter structure
+ * @channel - volume channel
+ * @id - volume target id
+ *
+ *
+ **/
+static void
+mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
+{
+	CONFIGPARMS			cfg;
+	ConfigPageHeader_t		hdr;
+	dma_addr_t			dma_handle;
+	pRaidVolumePage0_t		buffer = NULL;
+	int				i;
+	RaidPhysDiskPage0_t 		phys_disk;
+	struct inactive_raid_component_info *component_info;
+	int				handle_inactive_volumes;
+
+	memset(&cfg, 0 , sizeof(CONFIGPARMS));
+	memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+	hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
+	cfg.pageAddr = (channel << 8) + id;
+	cfg.cfghdr.hdr = &hdr;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+
+	if (mpt_config(ioc, &cfg) != 0)
+		goto out;
+
+	if (!hdr.PageLength)
+		goto out;
+
+	buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
+	    &dma_handle);
+
+	if (!buffer)
+		goto out;
+
+	cfg.physAddr = dma_handle;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+	if (mpt_config(ioc, &cfg) != 0)
+		goto out;
+
+	if (!buffer->NumPhysDisks)
+		goto out;
+
+	handle_inactive_volumes =
+	   (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE ||
+	   (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) == 0 ||
+	    buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_FAILED ||
+	    buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_MISSING) ? 1 : 0;
+
+	if (!handle_inactive_volumes)
+		goto out;
+
+	down(&ioc->raid_data.inactive_list_mutex);
+	for (i = 0; i < buffer->NumPhysDisks; i++) {
+		if(mpt_raid_phys_disk_pg0(ioc,
+		    buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
+			continue;
+
+		if ((component_info = kmalloc(sizeof (*component_info),
+		 GFP_KERNEL)) == NULL)
+			continue;
+
+		component_info->volumeID = id;
+		component_info->volumeBus = channel;
+		component_info->d.PhysDiskNum = phys_disk.PhysDiskNum;
+		component_info->d.PhysDiskBus = phys_disk.PhysDiskBus;
+		component_info->d.PhysDiskID = phys_disk.PhysDiskID;
+		component_info->d.PhysDiskIOC = phys_disk.PhysDiskIOC;
+
+		list_add_tail(&component_info->list,
+		    &ioc->raid_data.inactive_list);
+	}
+	up(&ioc->raid_data.inactive_list_mutex);
+
+ out:
+	if (buffer)
+		pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
+		    dma_handle);
+}
+
+/**
+ *	mpt_raid_phys_disk_pg0 - returns phys disk page zero
+ *	@ioc: Pointer to a Adapter Structure
+ *	@phys_disk_num: io unit unique phys disk num generated by the ioc
+ *	@phys_disk: requested payload data returned
+ *
+ *	Return:
+ *	0 on success
+ *	-EFAULT if read of config page header fails or data pointer not NULL
+ *	-ENOMEM if pci_alloc failed
+ **/
+int
+mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk)
+{
+	CONFIGPARMS		 	cfg;
+	ConfigPageHeader_t	 	hdr;
+	dma_addr_t			dma_handle;
+	pRaidPhysDiskPage0_t		buffer = NULL;
+	int				rc;
+
+	memset(&cfg, 0 , sizeof(CONFIGPARMS));
+	memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+
+	hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
+	cfg.cfghdr.hdr = &hdr;
+	cfg.physAddr = -1;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+
+	if (mpt_config(ioc, &cfg) != 0) {
+		rc = -EFAULT;
+		goto out;
+	}
+
+	if (!hdr.PageLength) {
+		rc = -EFAULT;
+		goto out;
+	}
+
+	buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
+	    &dma_handle);
+
+	if (!buffer) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	cfg.physAddr = dma_handle;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+	cfg.pageAddr = phys_disk_num;
+
+	if (mpt_config(ioc, &cfg) != 0) {
+		rc = -EFAULT;
+		goto out;
+	}
+
+	rc = 0;
+	memcpy(phys_disk, buffer, sizeof(*buffer));
+	phys_disk->MaxLBA = le32_to_cpu(buffer->MaxLBA);
+
+ out:
+
+	if (buffer)
+		pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
+		    dma_handle);
+
+	return rc;
+}
+
 /**
  *	mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
  *	@ioc: Pointer to a Adapter Strucutre
@@ -4722,21 +4928,27 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
  *	0 on success
  *	-EFAULT if read of config page header fails or data pointer not NULL
  *	-ENOMEM if pci_alloc failed
- */
+ **/
 int
 mpt_findImVolumes(MPT_ADAPTER *ioc)
 {
 	IOCPage2_t		*pIoc2;
 	u8			*mem;
-	ConfigPageIoc2RaidVol_t	*pIocRv;
 	dma_addr_t		 ioc2_dma;
 	CONFIGPARMS		 cfg;
 	ConfigPageHeader_t	 header;
-	int			 jj;
 	int			 rc = 0;
 	int			 iocpage2sz;
-	u8			 nVols, nPhys;
-	u8			 vid, vbus, vioc;
+	int			 i;
+
+	if (!ioc->ir_firmware)
+		return 0;
+
+	/* Free the old page
+	 */
+	kfree(ioc->raid_data.pIocPg2);
+	ioc->raid_data.pIocPg2 = NULL;
+	mpt_inactive_raid_list_free(ioc);
 
 	/* Read IOCP2 header then the page.
 	 */
@@ -4764,55 +4976,23 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
 	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
 	cfg.physAddr = ioc2_dma;
 	if (mpt_config(ioc, &cfg) != 0)
-		goto done_and_free;
+		goto out;
+
+	mem = kmalloc(iocpage2sz, GFP_KERNEL);
+	if (!mem)
+		goto out;
 
-	if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
-		mem = kmalloc(iocpage2sz, GFP_ATOMIC);
-		if (mem) {
-			ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
-		} else {
-			goto done_and_free;
-		}
-	}
 	memcpy(mem, (u8 *)pIoc2, iocpage2sz);
+	ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
 
-	/* Identify RAID Volume Id's */
-	nVols = pIoc2->NumActiveVolumes;
-	if ( nVols == 0) {
-		/* No RAID Volume.
-		 */
-		goto done_and_free;
-	} else {
-		/* At least 1 RAID Volume
-		 */
-		pIocRv = pIoc2->RaidVolume;
-		ioc->raid_data.isRaid = 0;
-		for (jj = 0; jj < nVols; jj++, pIocRv++) {
-			vid = pIocRv->VolumeID;
-			vbus = pIocRv->VolumeBus;
-			vioc = pIocRv->VolumeIOC;
-
-			/* find the match
-			 */
-			if (vbus == 0) {
-				ioc->raid_data.isRaid |= (1 << vid);
-			} else {
-				/* Error! Always bus 0
-				 */
-			}
-		}
-	}
+	mpt_read_ioc_pg_3(ioc);
 
-	/* Identify Hidden Physical Disk Id's */
-	nPhys = pIoc2->NumActivePhysDisks;
-	if (nPhys == 0) {
-		/* No physical disks.
-		 */
-	} else {
-		mpt_read_ioc_pg_3(ioc);
-	}
+	for (i = 0; i < pIoc2->NumActiveVolumes ; i++)
+		mpt_inactive_raid_volumes(ioc,
+		    pIoc2->RaidVolume[i].VolumeBus,
+		    pIoc2->RaidVolume[i].VolumeID);
 
-done_and_free:
+ out:
 	pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
 
 	return rc;
@@ -4865,7 +5045,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
 	cfg.physAddr = ioc3_dma;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
 	if (mpt_config(ioc, &cfg) == 0) {
-		mem = kmalloc(iocpage3sz, GFP_ATOMIC);
+		mem = kmalloc(iocpage3sz, GFP_KERNEL);
 		if (mem) {
 			memcpy(mem, (u8 *)pIoc3, iocpage3sz);
 			ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
@@ -5679,8 +5859,6 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
 	return rc;
 }
 
-# define EVENT_DESCR_STR_SZ		100
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static void
 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
@@ -5708,9 +5886,6 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
 		break;
 	case MPI_EVENT_RESCAN:
 		ds = "Bus Rescan Event";
-		/* Ok, do we need to do anything here? As far as
-		   I can tell, this is when a new device gets added
-		   to the loop. */
 		break;
 	case MPI_EVENT_LINK_STATUS_CHANGE:
 		if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
@@ -5787,48 +5962,63 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
 	case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
 	{
 		u8 id = (u8)(evData0);
+		u8 channel = (u8)(evData0 >> 8);
 		u8 ReasonCode = (u8)(evData0 >> 16);
 		switch (ReasonCode) {
 		case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: Added: id=%d", id);
+			    "SAS Device Status Change: Added: "
+			    "id=%d channel=%d", id, channel);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: Deleted: id=%d", id);
+			    "SAS Device Status Change: Deleted: "
+			    "id=%d channel=%d", id, channel);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: SMART Data: id=%d",
-			    id);
+			    "SAS Device Status Change: SMART Data: "
+			    "id=%d channel=%d", id, channel);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: No Persistancy: id=%d", id);
+			    "SAS Device Status Change: No Persistancy: "
+			    "id=%d channel=%d", id, channel);
+			break;
+		case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS Device Status Change: Unsupported Device "
+			    "Discovered : id=%d channel=%d", id, channel);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: Internal Device Reset : id=%d", id);
+			    "SAS Device Status Change: Internal Device "
+			    "Reset : id=%d channel=%d", id, channel);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: Internal Task Abort : id=%d", id);
+			    "SAS Device Status Change: Internal Task "
+			    "Abort : id=%d channel=%d", id, channel);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: Internal Abort Task Set : id=%d", id);
+			    "SAS Device Status Change: Internal Abort "
+			    "Task Set : id=%d channel=%d", id, channel);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: Internal Clear Task Set : id=%d", id);
+			    "SAS Device Status Change: Internal Clear "
+			    "Task Set : id=%d channel=%d", id, channel);
 			break;
 		case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: Internal Query Task : id=%d", id);
+			    "SAS Device Status Change: Internal Query "
+			    "Task : id=%d channel=%d", id, channel);
 			break;
 		default:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
-			    "SAS Device Status Change: Unknown: id=%d", id);
+			    "SAS Device Status Change: Unknown: "
+			    "id=%d channel=%d", id, channel);
 			break;
 		}
 		break;
@@ -5837,8 +6027,16 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
 		ds = "Bus Timer Expired";
 		break;
 	case MPI_EVENT_QUEUE_FULL:
-		ds = "Queue Full";
+	{
+		u16 curr_depth = (u16)(evData0 >> 16);
+		u8 channel = (u8)(evData0 >> 8);
+		u8 id = (u8)(evData0);
+
+		snprintf(evStr, EVENT_DESCR_STR_SZ,
+		   "Queue Full: channel=%d id=%d depth=%d",
+		   channel, id, curr_depth);
 		break;
+	}
 	case MPI_EVENT_SAS_SES:
 		ds = "SAS SES Event";
 		break;
@@ -5942,6 +6140,76 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
 		ds = "SAS Log Entry Added";
 		break;
 
+	case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
+	{
+		u8 phy_num = (u8)(evData0);
+		u8 port_num = (u8)(evData0 >> 8);
+		u8 port_width = (u8)(evData0 >> 16);
+		u8 primative = (u8)(evData0 >> 24);
+		snprintf(evStr, EVENT_DESCR_STR_SZ,
+		    "SAS Broadcase Primative: phy=%d port=%d "
+		    "width=%d primative=0x%02x",
+		    phy_num, port_num, port_width, primative);
+		break;
+	}
+
+	case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
+	{
+		u8 reason = (u8)(evData0);
+		u8 port_num = (u8)(evData0 >> 8);
+		u16 handle = le16_to_cpu(evData0 >> 16);
+
+		snprintf(evStr, EVENT_DESCR_STR_SZ,
+		    "SAS Initiator Device Status Change: reason=0x%02x "
+		    "port=%d handle=0x%04x",
+		    reason, port_num, handle);
+		break;
+	}
+
+	case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW:
+	{
+		u8 max_init = (u8)(evData0);
+		u8 current_init = (u8)(evData0 >> 8);
+
+		snprintf(evStr, EVENT_DESCR_STR_SZ,
+		    "SAS Initiator Device Table Overflow: max initiators=%02d "
+		    "current initators=%02d",
+		    max_init, current_init);
+		break;
+	}
+	case MPI_EVENT_SAS_SMP_ERROR:
+	{
+		u8 status = (u8)(evData0);
+		u8 port_num = (u8)(evData0 >> 8);
+		u8 result = (u8)(evData0 >> 16);
+
+		if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID)
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS SMP Error: port=%d result=0x%02x",
+			    port_num, result);
+		else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR)
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS SMP Error: port=%d : CRC Error",
+			    port_num);
+		else if (status == MPI_EVENT_SAS_SMP_TIMEOUT)
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS SMP Error: port=%d : Timeout",
+			    port_num);
+		else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION)
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS SMP Error: port=%d : No Destination",
+			    port_num);
+		else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION)
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS SMP Error: port=%d : Bad Destination",
+			    port_num);
+		else
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "SAS SMP Error: port=%d : status=0x%02x",
+			    port_num, status);
+		break;
+	}
+
 	/*
 	 *  MPT base "custom" events may be added here...
 	 */
@@ -6205,10 +6473,11 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
 		"Abort",					/* 12h */
 		"IO Not Yet Executed",				/* 13h */
 		"IO Executed",					/* 14h */
-		"Persistent Reservation Out Not Affiliation Owner", /* 15h */
+		"Persistent Reservation Out Not Affiliation "
+		    "Owner", 					/* 15h */
 		"Open Transmit DMA Abort",			/* 16h */
 		"IO Device Missing Delay Retry",		/* 17h */
-		NULL,						/* 18h */
+		"IO Cancelled Due to Recieve Error",		/* 18h */
 		NULL,						/* 19h */
 		NULL,						/* 1Ah */
 		NULL,						/* 1Bh */
@@ -6218,6 +6487,96 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
 		NULL,						/* 1Fh */
 		"Enclosure Management"				/* 20h */
 	};
+	static char *ir_code_str[] = {
+		"Raid Action Error",				/* 00h */
+		NULL,						/* 00h */
+		NULL,						/* 01h */
+		NULL,						/* 02h */
+		NULL,						/* 03h */
+		NULL,						/* 04h */
+		NULL,						/* 05h */
+		NULL,						/* 06h */
+		NULL						/* 07h */
+	};
+	static char *raid_sub_code_str[] = {
+		NULL, 						/* 00h */
+		"Volume Creation Failed: Data Passed too "
+		    "Large", 					/* 01h */
+		"Volume Creation Failed: Duplicate Volumes "
+		    "Attempted", 				/* 02h */
+		"Volume Creation Failed: Max Number "
+		    "Supported Volumes Exceeded",		/* 03h */
+		"Volume Creation Failed: DMA Error",		/* 04h */
+		"Volume Creation Failed: Invalid Volume Type",	/* 05h */
+		"Volume Creation Failed: Error Reading "
+		    "MFG Page 4", 				/* 06h */
+		"Volume Creation Failed: Creating Internal "
+		    "Structures", 				/* 07h */
+		NULL,						/* 08h */
+		NULL,						/* 09h */
+		NULL,						/* 0Ah */
+		NULL,						/* 0Bh */
+		NULL,						/* 0Ch */
+		NULL,						/* 0Dh */
+		NULL,						/* 0Eh */
+		NULL,						/* 0Fh */
+		"Activation failed: Already Active Volume", 	/* 10h */
+		"Activation failed: Unsupported Volume Type", 	/* 11h */
+		"Activation failed: Too Many Active Volumes", 	/* 12h */
+		"Activation failed: Volume ID in Use", 		/* 13h */
+		"Activation failed: Reported Failure", 		/* 14h */
+		"Activation failed: Importing a Volume", 	/* 15h */
+		NULL,						/* 16h */
+		NULL,						/* 17h */
+		NULL,						/* 18h */
+		NULL,						/* 19h */
+		NULL,						/* 1Ah */
+		NULL,						/* 1Bh */
+		NULL,						/* 1Ch */
+		NULL,						/* 1Dh */
+		NULL,						/* 1Eh */
+		NULL,						/* 1Fh */
+		"Phys Disk failed: Too Many Phys Disks", 	/* 20h */
+		"Phys Disk failed: Data Passed too Large",	/* 21h */
+		"Phys Disk failed: DMA Error", 			/* 22h */
+		"Phys Disk failed: Invalid <channel:id>", 	/* 23h */
+		"Phys Disk failed: Creating Phys Disk Config "
+		    "Page", 					/* 24h */
+		NULL,						/* 25h */
+		NULL,						/* 26h */
+		NULL,						/* 27h */
+		NULL,						/* 28h */
+		NULL,						/* 29h */
+		NULL,						/* 2Ah */
+		NULL,						/* 2Bh */
+		NULL,						/* 2Ch */
+		NULL,						/* 2Dh */
+		NULL,						/* 2Eh */
+		NULL,						/* 2Fh */
+		"Compatibility Error: IR Disabled",		/* 30h */
+		"Compatibility Error: Inquiry Comand Failed",	/* 31h */
+		"Compatibility Error: Device not Direct Access "
+		    "Device ",					/* 32h */
+		"Compatibility Error: Removable Device Found",	/* 33h */
+		"Compatibility Error: Device SCSI Version not "
+		    "2 or Higher", 				/* 34h */
+		"Compatibility Error: SATA Device, 48 BIT LBA "
+		    "not Supported", 				/* 35h */
+		"Compatibility Error: Device doesn't have "
+		    "512 Byte Block Sizes", 			/* 36h */
+		"Compatibility Error: Volume Type Check Failed", /* 37h */
+		"Compatibility Error: Volume Type is "
+		    "Unsupported by FW", 			/* 38h */
+		"Compatibility Error: Disk Drive too Small for "
+		    "use in Volume", 				/* 39h */
+		"Compatibility Error: Phys Disk for Create "
+		    "Volume not Found", 			/* 3Ah */
+		"Compatibility Error: Too Many or too Few "
+		    "Disks for Volume Type", 			/* 3Bh */
+		"Compatibility Error: Disk stripe Sizes "
+		    "Must be 64KB", 				/* 3Ch */
+		"Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */
+	};
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
@@ -6226,7 +6585,7 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
  *	@log_info: U32 LogInfo reply word from the IOC
  *
  *	Refer to lsi/mpi_log_sas.h.
- */
+ **/
 static void
 mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
 {
@@ -6240,56 +6599,165 @@ union loginfo_type {
 	}dw;
 };
 	union loginfo_type sas_loginfo;
+	char *originator_desc = NULL;
 	char *code_desc = NULL;
+	char *sub_code_desc = NULL;
 
 	sas_loginfo.loginfo = log_info;
 	if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
 	    (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
 		return;
-	if ((sas_loginfo.dw.originator == 0 /*IOP*/) &&
-	    (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) {
-		code_desc = iop_code_str[sas_loginfo.dw.code];
-	}else if ((sas_loginfo.dw.originator == 1 /*PL*/) &&
-	    (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) {
-		code_desc = pl_code_str[sas_loginfo.dw.code];
+
+	originator_desc = originator_str[sas_loginfo.dw.originator];
+
+	switch (sas_loginfo.dw.originator) {
+
+		case 0:  /* IOP */
+			if (sas_loginfo.dw.code <
+			    sizeof(iop_code_str)/sizeof(char*))
+				code_desc = iop_code_str[sas_loginfo.dw.code];
+			break;
+		case 1:  /* PL */
+			if (sas_loginfo.dw.code <
+			    sizeof(pl_code_str)/sizeof(char*))
+				code_desc = pl_code_str[sas_loginfo.dw.code];
+			break;
+		case 2:  /* IR */
+			if (sas_loginfo.dw.code >=
+			    sizeof(ir_code_str)/sizeof(char*))
+				break;
+			code_desc = ir_code_str[sas_loginfo.dw.code];
+			if (sas_loginfo.dw.subcode >=
+			    sizeof(raid_sub_code_str)/sizeof(char*))
+			break;
+			if (sas_loginfo.dw.code == 0)
+				sub_code_desc =
+				    raid_sub_code_str[sas_loginfo.dw.subcode];
+			break;
+		default:
+			return;
 	}
 
-	if (code_desc != NULL)
+	if (sub_code_desc != NULL)
+		printk(MYIOC_s_INFO_FMT
+			"LogInfo(0x%08x): Originator={%s}, Code={%s},"
+			" SubCode={%s}\n",
+			ioc->name, log_info, originator_desc, code_desc,
+			sub_code_desc);
+	else if (code_desc != NULL)
 		printk(MYIOC_s_INFO_FMT
 			"LogInfo(0x%08x): Originator={%s}, Code={%s},"
 			" SubCode(0x%04x)\n",
-			ioc->name,
-			log_info,
-			originator_str[sas_loginfo.dw.originator],
-			code_desc,
+			ioc->name, log_info, originator_desc, code_desc,
 			sas_loginfo.dw.subcode);
 	else
 		printk(MYIOC_s_INFO_FMT
 			"LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
 			" SubCode(0x%04x)\n",
-			ioc->name,
-			log_info,
-			originator_str[sas_loginfo.dw.originator],
-			sas_loginfo.dw.code,
-			sas_loginfo.dw.subcode);
+			ioc->name, log_info, originator_desc,
+			sas_loginfo.dw.code, sas_loginfo.dw.subcode);
 }
 
+#ifdef MPT_DEBUG_REPLY
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *	mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
+ *	mpt_iocstatus_info_config - IOCSTATUS information for config pages
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	ioc_status: U32 IOCStatus word from IOC
+ *	@mf: Pointer to MPT request frame
+ *
+ *	Refer to lsi/mpi.h.
+ **/
+static void
+mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
+{
+	Config_t *pReq = (Config_t *)mf;
+	char extend_desc[EVENT_DESCR_STR_SZ];
+	char *desc = NULL;
+	u32 form;
+	u8 page_type;
+
+	if (pReq->Header.PageType == MPI_CONFIG_PAGETYPE_EXTENDED)
+		page_type = pReq->ExtPageType;
+	else
+		page_type = pReq->Header.PageType;
+
+	/*
+	 * ignore invalid page messages for GET_NEXT_HANDLE
+	 */
+	form = le32_to_cpu(pReq->PageAddress);
+	if (ioc_status == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
+		if (page_type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE ||
+		    page_type == MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER ||
+		    page_type == MPI_CONFIG_EXTPAGETYPE_ENCLOSURE) {
+			if ((form >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT) ==
+				MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE)
+				return;
+		}
+		if (page_type == MPI_CONFIG_PAGETYPE_FC_DEVICE)
+			if ((form & MPI_FC_DEVICE_PGAD_FORM_MASK) ==
+				MPI_FC_DEVICE_PGAD_FORM_NEXT_DID)
+				return;
+	}
+
+	snprintf(extend_desc, EVENT_DESCR_STR_SZ,
+	    "type=%02Xh, page=%02Xh, action=%02Xh, form=%08Xh",
+	    page_type, pReq->Header.PageNumber, pReq->Action, form);
+
+	switch (ioc_status) {
+
+	case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
+		desc = "Config Page Invalid Action";
+		break;
+
+	case MPI_IOCSTATUS_CONFIG_INVALID_TYPE:   /* 0x0021 */
+		desc = "Config Page Invalid Type";
+		break;
+
+	case MPI_IOCSTATUS_CONFIG_INVALID_PAGE:   /* 0x0022 */
+		desc = "Config Page Invalid Page";
+		break;
+
+	case MPI_IOCSTATUS_CONFIG_INVALID_DATA:   /* 0x0023 */
+		desc = "Config Page Invalid Data";
+		break;
+
+	case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS:    /* 0x0024 */
+		desc = "Config Page No Defaults";
+		break;
+
+	case MPI_IOCSTATUS_CONFIG_CANT_COMMIT:    /* 0x0025 */
+		desc = "Config Page Can't Commit";
+		break;
+	}
+
+	if (!desc)
+		return;
+
+	printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n",
+	    ioc->name, ioc_status, desc, extend_desc);
+}
+
+/**
+ *	mpt_iocstatus_info - IOCSTATUS information returned from IOC.
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@ioc_status: U32 IOCStatus word from IOC
  *	@mf: Pointer to MPT request frame
  *
  *	Refer to lsi/mpi.h.
- */
+ **/
 static void
-mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
+mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
 {
 	u32 status = ioc_status & MPI_IOCSTATUS_MASK;
 	char *desc = NULL;
 
 	switch (status) {
+
+/****************************************************************************/
+/*  Common IOCStatus values for all replies                                 */
+/****************************************************************************/
+
 	case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
 		desc = "Invalid Function";
 		break;
@@ -6322,84 +6790,180 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
 		desc = "Invalid State";
 		break;
 
+/****************************************************************************/
+/*  Config IOCStatus values                                                 */
+/****************************************************************************/
+
 	case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
 	case MPI_IOCSTATUS_CONFIG_INVALID_TYPE:   /* 0x0021 */
 	case MPI_IOCSTATUS_CONFIG_INVALID_PAGE:   /* 0x0022 */
 	case MPI_IOCSTATUS_CONFIG_INVALID_DATA:   /* 0x0023 */
 	case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS:    /* 0x0024 */
 	case MPI_IOCSTATUS_CONFIG_CANT_COMMIT:    /* 0x0025 */
-		/* No message for Config IOCStatus values */
+		mpt_iocstatus_info_config(ioc, status, mf);
 		break;
 
+/****************************************************************************/
+/*  SCSIIO Reply (SPI, FCP, SAS) initiator values                           */
+/*                                                                          */
+/*  Look at mptscsih_iocstatus_info_scsiio in mptscsih.c */
+/*                                                                          */
+/****************************************************************************/
+
 	case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
-		/* No message for recovered error
-		desc = "SCSI Recovered Error";
-		*/
+	case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
+	case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
+	case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
+	case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
+	case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
+	case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
+	case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
+	case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
+	case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
+	case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
+	case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
+	case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
 		break;
 
-	case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
-		desc = "SCSI Invalid Bus";
+/****************************************************************************/
+/*  SCSI Target values                                                      */
+/****************************************************************************/
+
+	case MPI_IOCSTATUS_TARGET_PRIORITY_IO: /* 0x0060 */
+		desc = "Target: Priority IO";
 		break;
 
-	case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
-		desc = "SCSI Invalid TargetID";
+	case MPI_IOCSTATUS_TARGET_INVALID_PORT: /* 0x0061 */
+		desc = "Target: Invalid Port";
 		break;
 
-	case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
-	  {
-		SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
-		U8 cdb = pScsiReq->CDB[0];
-		if (cdb != 0x12) { /* Inquiry is issued for device scanning */
-			desc = "SCSI Device Not There";
-		}
+	case MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX: /* 0x0062 */
+		desc = "Target Invalid IO Index:";
 		break;
-	  }
 
-	case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
-		desc = "SCSI Data Overrun";
+	case MPI_IOCSTATUS_TARGET_ABORTED: /* 0x0063 */
+		desc = "Target: Aborted";
 		break;
 
-	case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
-		/* This error is checked in scsi_io_done(). Skip.
-		desc = "SCSI Data Underrun";
-		*/
+	case MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: /* 0x0064 */
+		desc = "Target: No Conn Retryable";
 		break;
 
-	case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
-		desc = "SCSI I/O Data Error";
+	case MPI_IOCSTATUS_TARGET_NO_CONNECTION: /* 0x0065 */
+		desc = "Target: No Connection";
 		break;
 
-	case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
-		desc = "SCSI Protocol Error";
+	case MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: /* 0x006A */
+		desc = "Target: Transfer Count Mismatch";
 		break;
 
-	case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
-		desc = "SCSI Task Terminated";
+	case MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT: /* 0x006B */
+		desc = "Target: STS Data not Sent";
 		break;
 
-	case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
-		desc = "SCSI Residual Mismatch";
+	case MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: /* 0x006D */
+		desc = "Target: Data Offset Error";
 		break;
 
-	case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
-		desc = "SCSI Task Management Failed";
+	case MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: /* 0x006E */
+		desc = "Target: Too Much Write Data";
 		break;
 
-	case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
-		desc = "SCSI IOC Terminated";
+	case MPI_IOCSTATUS_TARGET_IU_TOO_SHORT: /* 0x006F */
+		desc = "Target: IU Too Short";
 		break;
 
-	case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
-		desc = "SCSI Ext Terminated";
+	case MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: /* 0x0070 */
+		desc = "Target: ACK NAK Timeout";
+		break;
+
+	case MPI_IOCSTATUS_TARGET_NAK_RECEIVED: /* 0x0071 */
+		desc = "Target: Nak Received";
+		break;
+
+/****************************************************************************/
+/*  Fibre Channel Direct Access values                                      */
+/****************************************************************************/
+
+	case MPI_IOCSTATUS_FC_ABORTED: /* 0x0066 */
+		desc = "FC: Aborted";
+		break;
+
+	case MPI_IOCSTATUS_FC_RX_ID_INVALID: /* 0x0067 */
+		desc = "FC: RX ID Invalid";
+		break;
+
+	case MPI_IOCSTATUS_FC_DID_INVALID: /* 0x0068 */
+		desc = "FC: DID Invalid";
+		break;
+
+	case MPI_IOCSTATUS_FC_NODE_LOGGED_OUT: /* 0x0069 */
+		desc = "FC: Node Logged Out";
+		break;
+
+	case MPI_IOCSTATUS_FC_EXCHANGE_CANCELED: /* 0x006C */
+		desc = "FC: Exchange Canceled";
+		break;
+
+/****************************************************************************/
+/*  LAN values                                                              */
+/****************************************************************************/
+
+	case MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND: /* 0x0080 */
+		desc = "LAN: Device not Found";
+		break;
+
+	case MPI_IOCSTATUS_LAN_DEVICE_FAILURE: /* 0x0081 */
+		desc = "LAN: Device Failure";
+		break;
+
+	case MPI_IOCSTATUS_LAN_TRANSMIT_ERROR: /* 0x0082 */
+		desc = "LAN: Transmit Error";
+		break;
+
+	case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED: /* 0x0083 */
+		desc = "LAN: Transmit Aborted";
+		break;
+
+	case MPI_IOCSTATUS_LAN_RECEIVE_ERROR: /* 0x0084 */
+		desc = "LAN: Receive Error";
+		break;
+
+	case MPI_IOCSTATUS_LAN_RECEIVE_ABORTED: /* 0x0085 */
+		desc = "LAN: Receive Aborted";
+		break;
+
+	case MPI_IOCSTATUS_LAN_PARTIAL_PACKET: /* 0x0086 */
+		desc = "LAN: Partial Packet";
+		break;
+
+	case MPI_IOCSTATUS_LAN_CANCELED: /* 0x0087 */
+		desc = "LAN: Canceled";
+		break;
+
+/****************************************************************************/
+/*  Serial Attached SCSI values                                             */
+/****************************************************************************/
+
+	case MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED: /* 0x0090 */
+		desc = "SAS: SMP Request Failed";
+		break;
+
+	case MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN: /* 0x0090 */
+		desc = "SAS: SMP Data Overrun";
 		break;
 
 	default:
 		desc = "Others";
 		break;
 	}
-	if (desc != NULL)
-		printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
+
+	if (!desc)
+		return;
+
+	printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s\n", ioc->name, status, desc);
 }
+#endif
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 EXPORT_SYMBOL(mpt_attach);
@@ -6434,6 +6998,7 @@ EXPORT_SYMBOL(mpt_findImVolumes);
 EXPORT_SYMBOL(mpt_alloc_fw_memory);
 EXPORT_SYMBOL(mpt_free_fw_memory);
 EXPORT_SYMBOL(mptbase_sas_persist_operation);
+EXPORT_SYMBOL(mpt_raid_phys_disk_pg0);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index e316708f76bd..e3a39272aad6 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -6,7 +6,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -75,8 +75,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2007 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.04.03"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.03"
+#define MPT_LINUX_VERSION_COMMON	"3.04.04"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.04"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -172,6 +172,9 @@
 #define MPT_SCSI_SG_DEPTH	40
 #endif
 
+/* debug print string length used for events and iocstatus */
+# define EVENT_DESCR_STR_SZ             100
+
 #ifdef __KERNEL__	/* { */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
@@ -334,8 +337,8 @@ typedef struct _VirtTarget {
 	struct scsi_target	*starget;
 	u8			 tflags;
 	u8			 ioc_id;
-	u8			 target_id;
-	u8			 bus_id;
+	u8			 id;
+	u8			 channel;
 	u8			 minSyncFactor;	/* 0xFF is async */
 	u8			 maxOffset;	/* 0 if async */
 	u8			 maxWidth;	/* 0 if narrow, 1 if wide */
@@ -344,13 +347,12 @@ typedef struct _VirtTarget {
 	u8			 type;		/* byte 0 of Inquiry data */
 	u8			 deleted;	/* target in process of being removed */
 	u32			 num_luns;
-	u32			 luns[8];		/* Max LUNs is 256 */
 } VirtTarget;
 
 typedef struct _VirtDevice {
 	VirtTarget		*vtarget;
 	u8			 configured_lun;
-	u32			 lun;
+	int			 lun;
 } VirtDevice;
 
 /*
@@ -412,7 +414,7 @@ typedef struct _MPT_IOCTL {
 	u8			 rsvd;
 	u8			 status;	/* current command status */
 	u8			 reset;		/* 1 if bus reset allowed */
-	u8			 target;	/* target for reset */
+	u8			 id;		/* target for reset */
 	struct mutex		 ioctl_mutex;
 } MPT_IOCTL;
 
@@ -483,10 +485,24 @@ typedef	struct _SasCfgData {
 						 */
 }SasCfgData;
 
+/*
+ * Inactive volume link list of raid component data
+ * @inactive_list
+ */
+struct inactive_raid_component_info {
+	struct 	 list_head list;
+	u8		 volumeID;		/* volume target id */
+	u8		 volumeBus;		/* volume channel */
+	IOC_3_PHYS_DISK	 d;			/* phys disk info */
+};
+
 typedef	struct _RaidCfgData {
 	IOCPage2_t	*pIocPg2;		/* table of Raid Volumes */
 	IOCPage3_t	*pIocPg3;		/* table of physical disks */
-	int		 isRaid;		/* bit field, 1 if RAID */
+	struct semaphore	inactive_list_mutex;
+	struct list_head	inactive_list; /* link list for physical
+						disk that belong in
+						inactive volumes */
 }RaidCfgData;
 
 typedef struct _FcCfgData {
@@ -528,6 +544,8 @@ typedef struct _MPT_ADAPTER
 	u32			 mem_phys;	/* == f4020000 (mmap) */
 	u32			 pio_mem_phys;	/* Programmed IO (downloadboot) */
 	int			 mem_size;	/* mmap memory size */
+	int			 number_of_buses;
+	int			 devices_per_bus;
 	int			 alloc_total;
 	u32			 last_state;
 	int			 active;
@@ -607,6 +625,8 @@ typedef struct _MPT_ADAPTER
 	u8			 persist_reply_frame[MPT_DEFAULT_FRAME_SIZE]; /* persist reply */
 	LANPage0_t		 lan_cnfg_page0;
 	LANPage1_t		 lan_cnfg_page1;
+
+	u8			 ir_firmware; /* =1 if IR firmware detected */
 	/*
 	 * Description: errata_flag_1064
 	 * If a PCIX read occurs within 1 or 2 cycles after the chip receives
@@ -790,12 +810,6 @@ typedef struct _mpt_sge {
 #define ddvprintk(x)
 #endif
 
-#ifdef MPT_DEBUG_NEGO
-#define dnegoprintk(x)  printk x
-#else
-#define dnegoprintk(x)
-#endif
-
 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
 #define ddvtprintk(x)  printk x
 #else
@@ -957,7 +971,6 @@ typedef struct _MPT_SCSI_HOST {
 	int			  port;
 	u32			  pad0;
 	struct scsi_cmnd	**ScsiLookup;
-	VirtTarget		**Targets;
 	MPT_LOCAL_REPLY		 *pLocal;		/* used for internal commands */
 	struct timer_list	  timer;
 		/* Pool of memory for holding SCpnts before doing
@@ -981,6 +994,7 @@ typedef struct _MPT_SCSI_HOST {
 	int			  scandv_wait_done;
 	long			  last_queue_full;
 	u16			  tm_iocstatus;
+	struct list_head	  target_reset_list;
 } MPT_SCSI_HOST;
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1046,6 +1060,7 @@ extern void	 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size);
 extern void	 mpt_free_fw_memory(MPT_ADAPTER *ioc);
 extern int	 mpt_findImVolumes(MPT_ADAPTER *ioc);
 extern int	 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
+extern int	 mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk);
 
 /*
  *  Public data decl's...
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 504632da4347..b0b80428d110 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -5,7 +5,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -313,7 +313,7 @@ static void mptctl_timeout_expired (MPT_IOCTL *ioctl)
 		 */
 		dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
 			 ioctl->ioc->name));
-		mpt_HardResetHandler(ioctl->ioc, NO_SLEEP);
+		mpt_HardResetHandler(ioctl->ioc, CAN_SLEEP);
 	}
 	return;
 
@@ -361,7 +361,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
 			ioctl->ioc->name, mf));
 
 	pScsiTm = (SCSITaskMgmt_t *) mf;
-	pScsiTm->TargetID = ioctl->target;
+	pScsiTm->TargetID = ioctl->id;
 	pScsiTm->Bus = hd->port;	/* 0 */
 	pScsiTm->ChainOffset = 0;
 	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
@@ -1159,15 +1159,12 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
 	struct mpt_ioctl_iocinfo *karg;
 	MPT_ADAPTER		*ioc;
 	struct pci_dev		*pdev;
-	struct Scsi_Host	*sh;
-	MPT_SCSI_HOST		*hd;
 	int			iocnum;
-	int			numDevices = 0;
-	unsigned int		max_id;
-	int			ii;
 	unsigned int		port;
 	int			cim_rev;
 	u8			revision;
+	struct scsi_device 	*sdev;
+	VirtDevice		*vdev;
 
 	dctlprintk((": mptctl_getiocinfo called.\n"));
 	/* Add of PCI INFO results in unaligned access for
@@ -1257,23 +1254,16 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
 
 	/* Get number of devices
          */
-	if ((sh = ioc->sh) != NULL) {
-		 /* sh->max_id = maximum target ID + 1
-		 */
-		max_id = sh->max_id - 1;
-		hd = (MPT_SCSI_HOST *) sh->hostdata;
-
-		/* Check all of the target structures and
-		 * keep a counter.
-		 */
-		if (hd && hd->Targets) {
-			for (ii = 0; ii <= max_id; ii++) {
-				if (hd->Targets[ii])
-					numDevices++;
-			}
+	karg->numDevices = 0;
+	if (ioc->sh) {
+		shost_for_each_device(sdev, ioc->sh) {
+			vdev = sdev->hostdata;
+			if (vdev->vtarget->tflags &
+			    MPT_TARGET_FLAGS_RAID_COMPONENT)
+				continue;
+			karg->numDevices++;
 		}
 	}
-	karg->numDevices = numDevices;
 
 	/* Set the BIOS and FW Version
 	 */
@@ -1319,21 +1309,16 @@ mptctl_gettargetinfo (unsigned long arg)
 	struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_targetinfo karg;
 	MPT_ADAPTER		*ioc;
-	struct Scsi_Host	*sh;
-	MPT_SCSI_HOST		*hd;
-	VirtTarget		*vdev;
+	VirtDevice		*vdev;
 	char			*pmem;
 	int			*pdata;
-	IOCPage2_t		*pIoc2;
-	IOCPage3_t		*pIoc3;
 	int			iocnum;
 	int			numDevices = 0;
-	unsigned int		max_id;
-	int			id, jj, indexed_lun, lun_index;
-	u32			lun;
+	int			lun;
 	int			maxWordsLeft;
 	int			numBytes;
-	u8			port, devType, bus_id;
+	u8			port;
+	struct scsi_device 	*sdev;
 
 	dctlprintk(("mptctl_gettargetinfo called.\n"));
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) {
@@ -1389,74 +1374,22 @@ mptctl_gettargetinfo (unsigned long arg)
 
 	/* Get number of devices
          */
-	if ((sh = ioc->sh) != NULL) {
-
-		max_id = sh->max_id - 1;
-		hd = (MPT_SCSI_HOST *) sh->hostdata;
-
-		/* Check all of the target structures.
-		 * Save the Id and increment the counter,
-		 * if ptr non-null.
-		 * sh->max_id = maximum target ID + 1
-		 */
-		if (hd && hd->Targets) {
-			mpt_findImVolumes(ioc);
-			pIoc2 = ioc->raid_data.pIocPg2;
-			for ( id = 0; id <= max_id; ) {
-				if ( pIoc2 && pIoc2->NumActiveVolumes ) {
-					if ( id == pIoc2->RaidVolume[0].VolumeID ) {
-						if (maxWordsLeft <= 0) {
-							printk(KERN_ERR "mptctl_gettargetinfo - "
-			"buffer is full but volume is available on ioc %d\n, numDevices=%d", iocnum, numDevices);
-							goto data_space_full;
-						}
-						if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 )
-                        				devType = 0x80;
-                    				else
-                        				devType = 0xC0;
-						bus_id = pIoc2->RaidVolume[0].VolumeBus;
-	            				numDevices++;
-                    				*pdata = ( (devType << 24) | (bus_id << 8) | id );
-						dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
-		"volume ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
-                    				pdata++;
-						--maxWordsLeft;
-						goto next_id;
-					} else {
-						pIoc3 = ioc->raid_data.pIocPg3;
-            					for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) {
-                    					if ( pIoc3->PhysDisk[jj].PhysDiskID == id )
-								goto next_id;
-						}
-					}
-				}
-				if ( (vdev = hd->Targets[id]) ) {
-					for (jj = 0; jj <= MPT_LAST_LUN; jj++) {
-						lun_index = (jj >> 5);
-						indexed_lun = (jj % 32);
-						lun = (1 << indexed_lun);
-						if (vdev->luns[lun_index] & lun) {
-							if (maxWordsLeft <= 0) {
-								printk(KERN_ERR "mptctl_gettargetinfo - "
-			"buffer is full but more targets are available on ioc %d numDevices=%d\n", iocnum, numDevices);
-								goto data_space_full;
-							}
-							bus_id = vdev->bus_id;
-							numDevices++;
-                            				*pdata = ( (jj << 16) | (bus_id << 8) | id );
-							dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
-		"target ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
-							pdata++;
-							--maxWordsLeft;
-						}
-					}
-				}
-next_id:
-				id++;
-			}
+	if (ioc->sh){
+		shost_for_each_device(sdev, ioc->sh) {
+			if (!maxWordsLeft)
+				continue;
+			vdev = sdev->hostdata;
+			if (vdev->vtarget->tflags &
+			    MPT_TARGET_FLAGS_RAID_COMPONENT)
+				continue;
+			lun = (vdev->vtarget->raidVolume) ? 0x80 : vdev->lun;
+			*pdata = (((u8)lun << 16) + (vdev->vtarget->channel << 8) +
+			    (vdev->vtarget->id ));
+			pdata++;
+			numDevices++;
+			--maxWordsLeft;
 		}
 	}
-data_space_full:
 	karg.numDevices = numDevices;
 
 	/* Copy part of the data from kernel memory to user memory
@@ -1821,6 +1754,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 	int		msgContext;
 	u16		req_idx;
 	ulong 		timeout;
+	struct scsi_device *sdev;
 
 	dctlprintk(("mptctl_do_mpt_command called.\n"));
 	bufIn.kptr = bufOut.kptr = NULL;
@@ -1902,14 +1836,13 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 	case MPI_FUNCTION_SCSI_IO_REQUEST:
 		if (ioc->sh) {
 			SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
-			VirtTarget	*pTarget = NULL;
-			MPT_SCSI_HOST	*hd = NULL;
 			int qtag = MPI_SCSIIO_CONTROL_UNTAGGED;
 			int scsidir = 0;
-			int target = (int) pScsiReq->TargetID;
 			int dataSize;
+			u32 id;
 
-			if ((target < 0) || (target >= ioc->sh->max_id)) {
+			id = (ioc->devices_per_bus == 0) ? 256 : ioc->devices_per_bus;
+			if (pScsiReq->TargetID > id) {
 				printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
 					"Target ID out of bounds. \n",
 					__FILE__, __LINE__);
@@ -1917,6 +1850,14 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 				goto done_free_mem;
 			}
 
+			if (pScsiReq->Bus >= ioc->number_of_buses) {
+				printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+					"Target Bus out of bounds. \n",
+					__FILE__, __LINE__);
+				rc = -ENODEV;
+				goto done_free_mem;
+			}
+
 			pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
 			pScsiReq->MsgFlags |= mpt_msg_flags();
 
@@ -1936,13 +1877,15 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 				cpu_to_le32(ioc->sense_buf_low_dma
 				   + (req_idx * MPT_SENSE_BUFFER_ALLOC));
 
-			if ((hd = (MPT_SCSI_HOST *) ioc->sh->hostdata)) {
-				if (hd->Targets)
-					pTarget = hd->Targets[target];
-			}
+			shost_for_each_device(sdev, ioc->sh) {
+				struct scsi_target *starget = scsi_target(sdev);
+				VirtTarget *vtarget = starget->hostdata;
 
-			if (pTarget &&(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
-				qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;
+				if ((pScsiReq->TargetID == vtarget->id) &&
+				    (pScsiReq->Bus == vtarget->channel) &&
+				    (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
+					qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;
+			}
 
 			/* Have the IOCTL driver set the direction based
 			 * on the dataOutSize (ordering issue with Sparc).
@@ -1959,7 +1902,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 			pScsiReq->DataLength = cpu_to_le32(dataSize);
 
 			ioc->ioctl->reset = MPTCTL_RESET_OK;
-			ioc->ioctl->target = target;
+			ioc->ioctl->id = pScsiReq->TargetID;
 
 		} else {
 			printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
@@ -2038,7 +1981,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 			pScsiReq->DataLength = cpu_to_le32(dataSize);
 
 			ioc->ioctl->reset = MPTCTL_RESET_OK;
-			ioc->ioctl->target = pScsiReq->TargetID;
+			ioc->ioctl->id = pScsiReq->TargetID;
 		} else {
 			printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
 				"SCSI driver is not loaded. \n",
diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h
index e65a1cf5eb0b..f7e72c5e47de 100644
--- a/drivers/message/fusion/mptctl.h
+++ b/drivers/message/fusion/mptctl.h
@@ -6,7 +6,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index c819c23b55b1..b7d4c7265ec6 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -4,7 +4,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -86,6 +86,12 @@ MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
 				     " return following a device loss event."
 				     "  Default=60.");
 
+/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
+#define MPTFC_MAX_LUN (16895)
+static int max_lun = MPTFC_MAX_LUN;
+module_param(max_lun, int, 0);
+MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
+
 static int	mptfcDoneCtx = -1;
 static int	mptfcTaskCtx = -1;
 static int	mptfcInternalCtx = -1; /* Used only for internal commands */
@@ -292,10 +298,9 @@ mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
 	U32			 port_id = 0xffffff;
 	int			 num_targ = 0;
 	int			 max_bus = ioc->facts.MaxBuses;
-	int			 max_targ = ioc->facts.MaxDevices;
+	int			 max_targ;
 
-	if (max_bus == 0 || max_targ == 0)
-		goto out;
+	max_targ = (ioc->facts.MaxDevices == 0) ? 256 : ioc->facts.MaxDevices;
 
 	data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
 	p_p0 = p0_array =  kzalloc(data_sz, GFP_KERNEL);
@@ -467,8 +472,8 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
 			if (ri->starget) {
 				vtarget = ri->starget->hostdata;
 				if (vtarget) {
-					vtarget->target_id = pg0->CurrentTargetID;
-					vtarget->bus_id = pg0->CurrentBus;
+					vtarget->id = pg0->CurrentTargetID;
+					vtarget->channel = pg0->CurrentBus;
 				}
 			}
 			*((struct mptfc_rport_info **)rport->dd_data) = ri;
@@ -540,8 +545,8 @@ mptfc_target_alloc(struct scsi_target *starget)
 	if (rport) {
 		ri = *((struct mptfc_rport_info **)rport->dd_data);
 		if (ri) {	/* better be! */
-			vtarget->target_id = ri->pg0.CurrentTargetID;
-			vtarget->bus_id = ri->pg0.CurrentBus;
+			vtarget->id = ri->pg0.CurrentTargetID;
+			vtarget->channel = ri->pg0.CurrentBus;
 			ri->starget = starget;
 			rc = 0;
 		}
@@ -592,7 +597,6 @@ mptfc_slave_alloc(struct scsi_device *sdev)
 	if (vtarget->num_luns == 0) {
 		vtarget->ioc_id = hd->ioc->id;
 		vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
-		hd->Targets[sdev->id] = vtarget;
 	}
 
 	vdev->vtarget = vtarget;
@@ -630,16 +634,17 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	struct mptfc_rport_info	*ri;
 	struct fc_rport	*rport = starget_to_rport(scsi_target(SCpnt->device));
 	int		err;
+	VirtDevice	*vdev = SCpnt->device->hostdata;
 
-	err = fc_remote_port_chkready(rport);
-	if (unlikely(err)) {
-		SCpnt->result = err;
+	if (!vdev || !vdev->vtarget) {
+		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
 		return 0;
 	}
 
-	if (!SCpnt->device->hostdata) {	/* vdev */
-		SCpnt->result = DID_NO_CONNECT << 16;
+	err = fc_remote_port_chkready(rport);
+	if (unlikely(err)) {
+		SCpnt->result = err;
 		done(SCpnt);
 		return 0;
 	}
@@ -1143,7 +1148,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		printk(MYIOC_s_WARN_FMT
 			"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
 			ioc->name, ioc);
-		return -ENODEV;
+		return 0;
 	}
 
 	sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
@@ -1173,10 +1178,9 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	/* set 16 byte cdb's */
 	sh->max_cmd_len = 16;
 
-	sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
+	sh->max_id = ioc->pfacts->MaxDevices;
+	sh->max_lun = max_lun;
 
-	sh->max_lun = MPT_LAST_LUN + 1;
-	sh->max_channel = 0;
 	sh->this_id = ioc->pfacts[0].PortSCSIID;
 
 	/* Required entry.
@@ -1230,19 +1234,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
 		 ioc->name, hd->ScsiLookup));
 
-	/* Allocate memory for the device structures.
-	 * A non-Null pointer at an offset
-	 * indicates a device exists.
-	 * max_id = 1 + maximum id (hosts.h)
-	 */
-	hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
-	if (!hd->Targets) {
-		error = -ENOMEM;
-		goto out_mptfc_probe;
-	}
-
-	dprintk((KERN_INFO "  vdev @ %p\n", hd->Targets));
-
 	/* Clear the TM flags
 	 */
 	hd->tmPending = 0;
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index 2936204d8ad6..b691292ff599 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -5,6 +5,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 2000-2007 LSI Logic Corporation
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h
index 70ab75e7c263..fe438bf119f6 100644
--- a/drivers/message/fusion/mptlan.h
+++ b/drivers/message/fusion/mptlan.h
@@ -5,6 +5,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 2000-2007 LSI Logic Corporation
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 09e9a9d96410..84b8b485e95b 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -4,7 +4,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  (mailto:mpt_linux_developer@lsi.com)
  *  Copyright (c) 2005-2007 Dell
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -83,17 +83,31 @@ MODULE_PARM_DESC(mpt_pt_clear,
 		" Clear persistency table: enable=1  "
 		"(default=MPTSCSIH_PT_CLEAR=0)");
 
+/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
+#define MPTSAS_MAX_LUN (16895)
+static int max_lun = MPTSAS_MAX_LUN;
+module_param(max_lun, int, 0);
+MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
+
 static int	mptsasDoneCtx = -1;
 static int	mptsasTaskCtx = -1;
 static int	mptsasInternalCtx = -1; /* Used only for internal commands */
 static int	mptsasMgmtCtx = -1;
 
+static void mptsas_hotplug_work(struct work_struct *work);
+
+struct mptsas_target_reset_event {
+	struct list_head 	list;
+	EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data;
+	u8	target_reset_issued;
+};
 
 enum mptsas_hotplug_action {
 	MPTSAS_ADD_DEVICE,
 	MPTSAS_DEL_DEVICE,
 	MPTSAS_ADD_RAID,
 	MPTSAS_DEL_RAID,
+	MPTSAS_ADD_INACTIVE_VOLUME,
 	MPTSAS_IGNORE_EVENT,
 };
 
@@ -102,14 +116,15 @@ struct mptsas_hotplug_event {
 	MPT_ADAPTER		*ioc;
 	enum mptsas_hotplug_action event_type;
 	u64			sas_address;
-	u32			channel;
-	u32			id;
+	u8			channel;
+	u8			id;
 	u32			device_info;
 	u16			handle;
 	u16			parent_handle;
 	u8			phy_id;
-	u8			phys_disk_num;
-	u8			phys_disk_num_valid;
+	u8			phys_disk_num_valid;	/* hrc (hidden raid component) */
+	u8			phys_disk_num;		/* hrc - unique index*/
+	u8			hidden_raid_component;	/* hrc - don't expose*/
 };
 
 struct mptsas_discovery_event {
@@ -134,6 +149,7 @@ struct mptsas_devinfo {
 	u8	port_id;	/* sas physical port this device
 				   is assoc'd with */
 	u8	id;		/* logical target id of this device */
+	u32	phys_disk_num;	/* phys disk id, for csmi-ioctls */
 	u8	channel;	/* logical bus number of this device */
 	u64	sas_address;    /* WWN of this device,
 				   SATA is assigned by HBA,expander */
@@ -153,6 +169,7 @@ struct mptsas_portinfo_details{
 };
 
 struct mptsas_phyinfo {
+	u16	handle;			/* unique id to address this */
 	u8	phy_id; 		/* phy index */
 	u8	port_id; 		/* firmware port identifier */
 	u8	negotiated_link_rate;	/* nego'd link rate for this phy */
@@ -168,7 +185,6 @@ struct mptsas_phyinfo {
 
 struct mptsas_portinfo {
 	struct list_head list;
-	u16		handle;		/* unique id to address this */
 	u16		num_phys;	/* number of phys */
 	struct mptsas_phyinfo *phy_info;
 };
@@ -561,22 +577,273 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
 	mutex_unlock(&ioc->sas_topology_mutex);
 }
 
+/**
+ * csmisas_find_vtarget
+ *
+ * @ioc
+ * @volume_id
+ * @volume_bus
+ *
+ **/
+static VirtTarget *
+mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
+{
+	struct scsi_device 		*sdev;
+	VirtDevice			*vdev;
+	VirtTarget 			*vtarget = NULL;
+
+	shost_for_each_device(sdev, ioc->sh) {
+		if ((vdev = sdev->hostdata) == NULL)
+			continue;
+		if (vdev->vtarget->id == id &&
+		    vdev->vtarget->channel == channel)
+			vtarget = vdev->vtarget;
+	}
+	return vtarget;
+}
+
+/**
+ * mptsas_target_reset
+ *
+ * Issues TARGET_RESET to end device using handshaking method
+ *
+ * @ioc
+ * @channel
+ * @id
+ *
+ * Returns (1) success
+ *         (0) failure
+ *
+ **/
+static int
+mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
+{
+	MPT_FRAME_HDR	*mf;
+	SCSITaskMgmt_t	*pScsiTm;
+
+	if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
+		dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n",
+		    ioc->name,__FUNCTION__, __LINE__));
+		return 0;
+	}
+
+	/* Format the Request
+	 */
+	pScsiTm = (SCSITaskMgmt_t *) mf;
+	memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
+	pScsiTm->TargetID = id;
+	pScsiTm->Bus = channel;
+	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
+	pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
+	pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
+
+	DBG_DUMP_TM_REQUEST_FRAME(mf);
+
+	if (mpt_send_handshake_request(ioc->TaskCtx, ioc,
+	    sizeof(SCSITaskMgmt_t), (u32 *)mf, NO_SLEEP)) {
+		mpt_free_msg_frame(ioc, mf);
+		dfailprintk((MYIOC_s_WARN_FMT "%s, tm handshake failed @%d!!\n",
+		    ioc->name,__FUNCTION__, __LINE__));
+		return 0;
+	}
+
+	return 1;
+}
+
+/**
+ * mptsas_target_reset_queue
+ *
+ * Receive request for TARGET_RESET after recieving an firmware
+ * event NOT_RESPONDING_EVENT, then put command in link list
+ * and queue if task_queue already in use.
+ *
+ * @ioc
+ * @sas_event_data
+ *
+ **/
 static void
-mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget)
+mptsas_target_reset_queue(MPT_ADAPTER *ioc,
+    EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
 {
-	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+	MPT_SCSI_HOST	*hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+	VirtTarget *vtarget = NULL;
+	struct mptsas_target_reset_event *target_reset_list;
+	u8		id, channel;
 
-	if (mptscsih_TMHandler(hd,
-	     MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
-	     vtarget->bus_id, vtarget->target_id, 0, 0, 5) < 0) {
-		hd->tmPending = 0;
-		hd->tmState = TM_STATE_NONE;
-		printk(MYIOC_s_WARN_FMT
-	       "Error processing TaskMgmt id=%d TARGET_RESET\n",
-			ioc->name, vtarget->target_id);
+	id = sas_event_data->TargetID;
+	channel = sas_event_data->Bus;
+
+	if (!(vtarget = mptsas_find_vtarget(ioc, channel, id)))
+		return;
+
+	vtarget->deleted = 1; /* block IO */
+
+	target_reset_list = kzalloc(sizeof(*target_reset_list),
+	    GFP_ATOMIC);
+	if (!target_reset_list) {
+		dfailprintk((MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
+		    ioc->name,__FUNCTION__, __LINE__));
+		return;
+	}
+
+	memcpy(&target_reset_list->sas_event_data, sas_event_data,
+		sizeof(*sas_event_data));
+	list_add_tail(&target_reset_list->list, &hd->target_reset_list);
+
+	if (hd->resetPending)
+		return;
+
+	if (mptsas_target_reset(ioc, channel, id)) {
+		target_reset_list->target_reset_issued = 1;
+		hd->resetPending = 1;
 	}
 }
 
+/**
+ * mptsas_dev_reset_complete
+ *
+ * Completion for TARGET_RESET after NOT_RESPONDING_EVENT,
+ * enable work queue to finish off removing device from upper layers.
+ * then send next TARGET_RESET in the queue.
+ *
+ * @ioc
+ *
+ **/
+static void
+mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
+{
+	MPT_SCSI_HOST	*hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+        struct list_head *head = &hd->target_reset_list;
+	struct mptsas_target_reset_event *target_reset_list;
+	struct mptsas_hotplug_event *ev;
+	EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
+	u8		id, channel;
+	__le64		sas_address;
+
+	if (list_empty(head))
+		return;
+
+	target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, list);
+
+	sas_event_data = &target_reset_list->sas_event_data;
+	id = sas_event_data->TargetID;
+	channel = sas_event_data->Bus;
+	hd->resetPending = 0;
+
+	/*
+	 * retry target reset
+	 */
+	if (!target_reset_list->target_reset_issued) {
+		if (mptsas_target_reset(ioc, channel, id)) {
+			target_reset_list->target_reset_issued = 1;
+			hd->resetPending = 1;
+		}
+		return;
+	}
+
+	/*
+	 * enable work queue to remove device from upper layers
+	 */
+	list_del(&target_reset_list->list);
+
+	ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
+	if (!ev) {
+		dfailprintk((MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
+		    ioc->name,__FUNCTION__, __LINE__));
+		return;
+	}
+
+	INIT_WORK(&ev->work, mptsas_hotplug_work);
+	ev->ioc = ioc;
+	ev->handle = le16_to_cpu(sas_event_data->DevHandle);
+	ev->parent_handle =
+	    le16_to_cpu(sas_event_data->ParentDevHandle);
+	ev->channel = channel;
+	ev->id =id;
+	ev->phy_id = sas_event_data->PhyNum;
+	memcpy(&sas_address, &sas_event_data->SASAddress,
+	    sizeof(__le64));
+	ev->sas_address = le64_to_cpu(sas_address);
+	ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo);
+	ev->event_type = MPTSAS_DEL_DEVICE;
+	schedule_work(&ev->work);
+	kfree(target_reset_list);
+
+	/*
+	 * issue target reset to next device in the queue
+	 */
+
+	head = &hd->target_reset_list;
+	if (list_empty(head))
+		return;
+
+	target_reset_list = list_entry(head->next, struct mptsas_target_reset_event,
+	    list);
+
+	sas_event_data = &target_reset_list->sas_event_data;
+	id = sas_event_data->TargetID;
+	channel = sas_event_data->Bus;
+
+	if (mptsas_target_reset(ioc, channel, id)) {
+		target_reset_list->target_reset_issued = 1;
+		hd->resetPending = 1;
+	}
+}
+
+/**
+ * mptsas_taskmgmt_complete
+ *
+ * @ioc
+ * @mf
+ * @mr
+ *
+ **/
+static int
+mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
+{
+	mptsas_dev_reset_complete(ioc);
+	return mptscsih_taskmgmt_complete(ioc, mf, mr);
+}
+
+/**
+ * mptscsih_ioc_reset
+ *
+ * @ioc
+ * @reset_phase
+ *
+ **/
+static int
+mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
+{
+	MPT_SCSI_HOST	*hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+	struct mptsas_target_reset_event *target_reset_list, *n;
+	int rc;
+
+	rc = mptscsih_ioc_reset(ioc, reset_phase);
+
+	if (ioc->bus_type != SAS)
+		goto out;
+
+	if (reset_phase != MPT_IOC_POST_RESET)
+		goto out;
+
+	if (!hd || !hd->ioc)
+		goto out;
+
+	if (list_empty(&hd->target_reset_list))
+		goto out;
+
+	/* flush the target_reset_list */
+	list_for_each_entry_safe(target_reset_list, n,
+	    &hd->target_reset_list, list) {
+		list_del(&target_reset_list->list);
+		kfree(target_reset_list);
+	}
+
+ out:
+	return rc;
+}
+
 static int
 mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
 		u32 form, u32 form_specific)
@@ -661,8 +928,7 @@ mptsas_target_alloc(struct scsi_target *starget)
 	struct Scsi_Host *host = dev_to_shost(&starget->dev);
 	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)host->hostdata;
 	VirtTarget		*vtarget;
-	u32			target_id;
-	u32			channel;
+	u8			id, channel;
 	struct sas_rphy		*rphy;
 	struct mptsas_portinfo	*p;
 	int 			 i;
@@ -673,15 +939,19 @@ mptsas_target_alloc(struct scsi_target *starget)
 
 	vtarget->starget = starget;
 	vtarget->ioc_id = hd->ioc->id;
-	vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
-
-	target_id = starget->id;
+	vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
+	id = starget->id;
 	channel = 0;
 
-	hd->Targets[target_id] = vtarget;
-
-	if (starget->channel == MPTSAS_RAID_CHANNEL)
+	/*
+	 * RAID volumes placed beyond the last expected port.
+	 */
+	if (starget->channel == MPTSAS_RAID_CHANNEL) {
+		for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
+			if (id == hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
+				channel = hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
 		goto out;
+	}
 
 	rphy = dev_to_rphy(starget->dev.parent);
 	mutex_lock(&hd->ioc->sas_topology_mutex);
@@ -690,18 +960,19 @@ mptsas_target_alloc(struct scsi_target *starget)
 			if (p->phy_info[i].attached.sas_address !=
 					rphy->identify.sas_address)
 				continue;
-			target_id = p->phy_info[i].attached.id;
+			id = p->phy_info[i].attached.id;
 			channel = p->phy_info[i].attached.channel;
 			mptsas_set_starget(&p->phy_info[i], starget);
 
 			/*
 			 * Exposing hidden raid components
 			 */
-			if (mptscsih_is_phys_disk(hd->ioc, target_id)) {
-				target_id = mptscsih_raid_id_to_num(hd,
-						target_id);
+			if (mptscsih_is_phys_disk(hd->ioc, channel, id)) {
+				id = mptscsih_raid_id_to_num(hd->ioc,
+						channel, id);
 				vtarget->tflags |=
 				    MPT_TARGET_FLAGS_RAID_COMPONENT;
+				p->phy_info[i].attached.phys_disk_num = id;
 			}
 			mutex_unlock(&hd->ioc->sas_topology_mutex);
 			goto out;
@@ -713,8 +984,8 @@ mptsas_target_alloc(struct scsi_target *starget)
 	return -ENXIO;
 
  out:
-	vtarget->target_id = target_id;
-	vtarget->bus_id = channel;
+	vtarget->id = id;
+	vtarget->channel = channel;
 	starget->hostdata = vtarget;
 	return 0;
 }
@@ -786,7 +1057,8 @@ mptsas_slave_alloc(struct scsi_device *sdev)
 			 * Exposing hidden raid components
 			 */
 			if (mptscsih_is_phys_disk(hd->ioc,
-					p->phy_info[i].attached.id))
+			    p->phy_info[i].attached.channel,
+			    p->phy_info[i].attached.id))
 				sdev->no_uld_attach = 1;
 			mutex_unlock(&hd->ioc->sas_topology_mutex);
 			goto out;
@@ -808,13 +1080,14 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 {
 	VirtDevice	*vdev = SCpnt->device->hostdata;
 
-//	scsi_print_command(SCpnt);
-	if (vdev->vtarget->deleted) {
+	if (!vdev || !vdev->vtarget || vdev->vtarget->deleted) {
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
 		return 0;
 	}
 
+//	scsi_print_command(SCpnt);
+
 	return mptscsih_qcmd(SCpnt,done);
 }
 
@@ -1114,9 +1387,6 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
 		goto out_free_consistent;
 	}
 
-	if (port_info->num_phys)
-		port_info->handle =
-		    le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
 	for (i = 0; i < port_info->num_phys; i++) {
 		mptsas_print_phy_data(&buffer->PhyData[i]);
 		port_info->phy_info[i].phy_id = i;
@@ -1125,6 +1395,8 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
 		port_info->phy_info[i].negotiated_link_rate =
 		    buffer->PhyData[i].NegotiatedLinkRate;
 		port_info->phy_info[i].portinfo = port_info;
+		port_info->phy_info[i].handle =
+		    le16_to_cpu(buffer->PhyData[i].ControllerDevHandle);
 	}
 
  out_free_consistent:
@@ -1261,6 +1533,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
 	device_info->phy_id = buffer->PhyNum;
 	device_info->port_id = buffer->PhysicalPort;
 	device_info->id = buffer->TargetID;
+	device_info->phys_disk_num = ~0;
 	device_info->channel = buffer->Bus;
 	memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
 	device_info->sas_address = le64_to_cpu(sas_address);
@@ -1325,7 +1598,6 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
 
 	/* save config data */
 	port_info->num_phys = buffer->NumPhys;
-	port_info->handle = le16_to_cpu(buffer->DevHandle);
 	port_info->phy_info = kcalloc(port_info->num_phys,
 		sizeof(*port_info->phy_info),GFP_KERNEL);
 	if (!port_info->phy_info) {
@@ -1333,8 +1605,11 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
 		goto out_free_consistent;
 	}
 
-	for (i = 0; i < port_info->num_phys; i++)
+	for (i = 0; i < port_info->num_phys; i++) {
 		port_info->phy_info[i].portinfo = port_info;
+		port_info->phy_info[i].handle =
+		    le16_to_cpu(buffer->DevHandle);
+	}
 
  out_free_consistent:
 	pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
@@ -1702,7 +1977,6 @@ static int
 mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
 {
 	struct mptsas_portinfo *port_info, *hba;
-	u32 handle = 0xFFFF;
 	int error = -ENOMEM, i;
 
 	hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
@@ -1714,34 +1988,36 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
 		goto out_free_port_info;
 
 	mutex_lock(&ioc->sas_topology_mutex);
-	ioc->handle = hba->handle;
-	port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle);
+	ioc->handle = hba->phy_info[0].handle;
+	port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle);
 	if (!port_info) {
 		port_info = hba;
 		list_add_tail(&port_info->list, &ioc->sas_topology);
 	} else {
-		port_info->handle = hba->handle;
-		for (i = 0; i < hba->num_phys; i++)
+		for (i = 0; i < hba->num_phys; i++) {
 			port_info->phy_info[i].negotiated_link_rate =
 				hba->phy_info[i].negotiated_link_rate;
+			port_info->phy_info[i].handle =
+				hba->phy_info[i].handle;
+			port_info->phy_info[i].port_id =
+				hba->phy_info[i].port_id;
+		}
 		kfree(hba->phy_info);
 		kfree(hba);
 		hba = NULL;
 	}
 	mutex_unlock(&ioc->sas_topology_mutex);
-
 	for (i = 0; i < port_info->num_phys; i++) {
 		mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
 			(MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
 			 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
 
 		mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
-			(MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
-			 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
+			(MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+			 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+			 port_info->phy_info[i].handle);
 		port_info->phy_info[i].identify.phy_id =
-		    port_info->phy_info[i].phy_id;
-		handle = port_info->phy_info[i].identify.handle;
-
+		    port_info->phy_info[i].phy_id = i;
 		if (port_info->phy_info[i].attached.handle)
 			mptsas_sas_device_pg0(ioc,
 				&port_info->phy_info[i].attached,
@@ -1777,12 +2053,12 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
 		goto out;
 
 	error = mptsas_sas_expander_pg0(ioc, ex,
-		(MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
-		 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
+	    (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
+	     MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
 	if (error)
 		goto out_free_port_info;
 
-	*handle = ex->handle;
+	*handle = ex->phy_info[0].handle;
 
 	mutex_lock(&ioc->sas_topology_mutex);
 	port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
@@ -1790,7 +2066,12 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
 		port_info = ex;
 		list_add_tail(&port_info->list, &ioc->sas_topology);
 	} else {
-		port_info->handle = ex->handle;
+		for (i = 0; i < ex->num_phys; i++) {
+			port_info->phy_info[i].handle =
+				ex->phy_info[i].handle;
+			port_info->phy_info[i].port_id =
+				ex->phy_info[i].port_id;
+		}
 		kfree(ex->phy_info);
 		kfree(ex);
 		ex = NULL;
@@ -1868,8 +2149,6 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
 	struct mptsas_portinfo buffer;
 	struct mptsas_portinfo *port_info, *n, *parent;
 	struct mptsas_phyinfo *phy_info;
-	struct scsi_target * starget;
-	VirtTarget * vtarget;
 	struct sas_port * port;
 	int i;
 	u64	expander_sas_address;
@@ -1884,26 +2163,8 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
 
 		if (mptsas_sas_expander_pg0(ioc, &buffer,
 		     (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
-		     MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {
-
-			/*
-			 * Issue target reset to all child end devices
-			 * then mark them deleted to prevent further
-			 * IO going to them.
-			 */
-			phy_info = port_info->phy_info;
-			for (i = 0; i < port_info->num_phys; i++, phy_info++) {
-				starget = mptsas_get_starget(phy_info);
-				if (!starget)
-					continue;
-				vtarget = starget->hostdata;
-				if(vtarget->deleted)
-					continue;
-				vtarget->deleted = 1;
-				mptsas_target_reset(ioc, vtarget);
-				sas_port_delete(mptsas_get_port(phy_info));
-				mptsas_port_delete(phy_info->port_details);
-			}
+		     MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
+		     port_info->phy_info[0].handle)) {
 
 			/*
 			 * Obtain the port_info instance to the parent port
@@ -1972,11 +2233,13 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
 	/*
 	  Reporting RAID volumes.
 	*/
+	if (!ioc->ir_firmware)
+		goto out;
 	if (!ioc->raid_data.pIocPg2)
 		goto out;
 	if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
 		goto out;
-	for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
+	for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
 		scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
 		    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
 	}
@@ -2030,12 +2293,37 @@ mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
 	mutex_lock(&ioc->sas_topology_mutex);
 	list_for_each_entry(port_info, &ioc->sas_topology, list) {
 		for (i = 0; i < port_info->num_phys; i++) {
+			if (!mptsas_is_end_device(
+				&port_info->phy_info[i].attached))
+				continue;
 			if (port_info->phy_info[i].attached.sas_address
 			    != sas_address)
 				continue;
+			phy_info = &port_info->phy_info[i];
+			break;
+		}
+	}
+	mutex_unlock(&ioc->sas_topology_mutex);
+	return phy_info;
+}
+
+static struct mptsas_phyinfo *
+mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id)
+{
+	struct mptsas_portinfo *port_info;
+	struct mptsas_phyinfo *phy_info = NULL;
+	int i;
+
+	mutex_lock(&ioc->sas_topology_mutex);
+	list_for_each_entry(port_info, &ioc->sas_topology, list) {
+		for (i = 0; i < port_info->num_phys; i++) {
 			if (!mptsas_is_end_device(
 				&port_info->phy_info[i].attached))
 				continue;
+			if (port_info->phy_info[i].attached.id != id)
+				continue;
+			if (port_info->phy_info[i].attached.channel != channel)
+				continue;
 			phy_info = &port_info->phy_info[i];
 			break;
 		}
@@ -2045,7 +2333,7 @@ mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
 }
 
 static struct mptsas_phyinfo *
-mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
+mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
 {
 	struct mptsas_portinfo *port_info;
 	struct mptsas_phyinfo *phy_info = NULL;
@@ -2054,11 +2342,15 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
 	mutex_lock(&ioc->sas_topology_mutex);
 	list_for_each_entry(port_info, &ioc->sas_topology, list) {
 		for (i = 0; i < port_info->num_phys; i++) {
-			if (port_info->phy_info[i].attached.id != id)
-				continue;
 			if (!mptsas_is_end_device(
 				&port_info->phy_info[i].attached))
 				continue;
+			if (port_info->phy_info[i].attached.phys_disk_num == ~0)
+				continue;
+			if (port_info->phy_info[i].attached.phys_disk_num != id)
+				continue;
+			if (port_info->phy_info[i].attached.channel != channel)
+				continue;
 			phy_info = &port_info->phy_info[i];
 			break;
 		}
@@ -2094,6 +2386,76 @@ mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
 			mptsas_reprobe_lun);
 }
 
+static void
+mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
+{
+	CONFIGPARMS			cfg;
+	ConfigPageHeader_t		hdr;
+	dma_addr_t			dma_handle;
+	pRaidVolumePage0_t		buffer = NULL;
+	RaidPhysDiskPage0_t 		phys_disk;
+	int				i;
+	struct mptsas_hotplug_event 	*ev;
+
+	memset(&cfg, 0 , sizeof(CONFIGPARMS));
+	memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+	hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
+	cfg.pageAddr = (channel << 8) + id;
+	cfg.cfghdr.hdr = &hdr;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+
+	if (mpt_config(ioc, &cfg) != 0)
+		goto out;
+
+	if (!hdr.PageLength)
+		goto out;
+
+	buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
+	    &dma_handle);
+
+	if (!buffer)
+		goto out;
+
+	cfg.physAddr = dma_handle;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+	if (mpt_config(ioc, &cfg) != 0)
+		goto out;
+
+	if (!(buffer->VolumeStatus.Flags &
+	    MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
+		goto out;
+
+	if (!buffer->NumPhysDisks)
+		goto out;
+
+	for (i = 0; i < buffer->NumPhysDisks; i++) {
+
+		if (mpt_raid_phys_disk_pg0(ioc,
+		    buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
+			continue;
+
+		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
+		if (!ev) {
+			printk(KERN_WARNING "mptsas: lost hotplug event\n");
+			goto out;
+		}
+
+		INIT_WORK(&ev->work, mptsas_hotplug_work);
+		ev->ioc = ioc;
+		ev->id = phys_disk.PhysDiskID;
+		ev->channel = phys_disk.PhysDiskBus;
+		ev->phys_disk_num_valid = 1;
+		ev->phys_disk_num = phys_disk.PhysDiskNum;
+		ev->event_type = MPTSAS_ADD_DEVICE;
+		schedule_work(&ev->work);
+	}
+
+ out:
+	if (buffer)
+		pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
+		    dma_handle);
+}
 /*
  * Work queue thread to handle SAS hotplug events
  */
@@ -2102,6 +2464,7 @@ mptsas_hotplug_work(struct work_struct *work)
 {
 	struct mptsas_hotplug_event *ev =
 		container_of(work, struct mptsas_hotplug_event, work);
+
 	MPT_ADAPTER *ioc = ev->ioc;
 	struct mptsas_phyinfo *phy_info;
 	struct sas_rphy *rphy;
@@ -2114,17 +2477,43 @@ mptsas_hotplug_work(struct work_struct *work)
 	VirtTarget *vtarget;
 	VirtDevice *vdevice;
 
-
 	mutex_lock(&ioc->sas_discovery_mutex);
 	switch (ev->event_type) {
 	case MPTSAS_DEL_DEVICE:
 
-		phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
+		phy_info = NULL;
+		if (ev->phys_disk_num_valid) {
+			if (ev->hidden_raid_component){
+				if (mptsas_sas_device_pg0(ioc, &sas_device,
+				    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
+				     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+				    (ev->channel << 8) + ev->id)) {
+					dfailprintk((MYIOC_s_ERR_FMT
+					"%s: exit at line=%d\n", ioc->name,
+						__FUNCTION__, __LINE__));
+					break;
+				}
+				phy_info = mptsas_find_phyinfo_by_sas_address(
+				    ioc, sas_device.sas_address);
+			}else
+				phy_info = mptsas_find_phyinfo_by_phys_disk_num(
+				    ioc, ev->channel, ev->phys_disk_num);
+		}
+
+		if (!phy_info)
+			phy_info = mptsas_find_phyinfo_by_target(ioc,
+			    ev->channel, ev->id);
 
 		/*
 		 * Sanity checks, for non-existing phys and remote rphys.
 		 */
-		if (!phy_info || !phy_info->port_details) {
+		if (!phy_info){
+			dfailprintk((MYIOC_s_ERR_FMT
+				"%s: exit at line=%d\n", ioc->name,
+				__FUNCTION__, __LINE__));
+			break;
+		}
+		if (!phy_info->port_details) {
 			dfailprintk((MYIOC_s_ERR_FMT
 				"%s: exit at line=%d\n", ioc->name,
 			       	__FUNCTION__, __LINE__));
@@ -2137,6 +2526,7 @@ mptsas_hotplug_work(struct work_struct *work)
 			       	__FUNCTION__, __LINE__));
 			break;
 		}
+
 		port = mptsas_get_port(phy_info);
 		if (!port) {
 			dfailprintk((MYIOC_s_ERR_FMT
@@ -2159,28 +2549,35 @@ mptsas_hotplug_work(struct work_struct *work)
 			/*
 			 * Handling  RAID components
 			 */
-			if (ev->phys_disk_num_valid) {
-				vtarget->target_id = ev->phys_disk_num;
-				vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
+			if (ev->phys_disk_num_valid &&
+			    ev->hidden_raid_component) {
+				printk(MYIOC_s_INFO_FMT
+				    "RAID Hidding: channel=%d, id=%d, "
+				    "physdsk %d \n", ioc->name, ev->channel,
+				    ev->id, ev->phys_disk_num);
+				vtarget->id = ev->phys_disk_num;
+				vtarget->tflags |=
+				    MPT_TARGET_FLAGS_RAID_COMPONENT;
 				mptsas_reprobe_target(starget, 1);
-				break;
+				phy_info->attached.phys_disk_num =
+				    ev->phys_disk_num;
+			break;
 			}
-
-			vtarget->deleted = 1;
-			mptsas_target_reset(ioc, vtarget);
 		}
 
-		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+		if (phy_info->attached.device_info &
+		    MPI_SAS_DEVICE_INFO_SSP_TARGET)
 			ds = "ssp";
-		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
+		if (phy_info->attached.device_info &
+		    MPI_SAS_DEVICE_INFO_STP_TARGET)
 			ds = "stp";
-		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+		if (phy_info->attached.device_info &
+		    MPI_SAS_DEVICE_INFO_SATA_DEVICE)
 			ds = "sata";
 
 		printk(MYIOC_s_INFO_FMT
 		       "removing %s device, channel %d, id %d, phy %d\n",
 		       ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
-
 #ifdef MPT_DEBUG_SAS_WIDE
 		dev_printk(KERN_DEBUG, &port->dev,
 		    "delete port (%d)\n", port->port_identifier);
@@ -2198,14 +2595,14 @@ mptsas_hotplug_work(struct work_struct *work)
 		 */
 		if (mptsas_sas_device_pg0(ioc, &sas_device,
 		    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
-		     MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) {
+		     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+			(ev->channel << 8) + ev->id)) {
 				dfailprintk((MYIOC_s_ERR_FMT
 					"%s: exit at line=%d\n", ioc->name,
 					__FUNCTION__, __LINE__));
 			break;
 		}
 
-		ssleep(2);
 		__mptsas_discovery_work(ioc);
 
 		phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
@@ -2219,7 +2616,8 @@ mptsas_hotplug_work(struct work_struct *work)
 		}
 
 		starget = mptsas_get_starget(phy_info);
-		if (starget) {
+		if (starget && (!ev->hidden_raid_component)){
+
 			vtarget = starget->hostdata;
 
 			if (!vtarget) {
@@ -2232,9 +2630,15 @@ mptsas_hotplug_work(struct work_struct *work)
 			 * Handling  RAID components
 			 */
 			if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
-				vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
-				vtarget->target_id = ev->id;
+				printk(MYIOC_s_INFO_FMT
+				    "RAID Exposing: channel=%d, id=%d, "
+				    "physdsk %d \n", ioc->name, ev->channel,
+				    ev->id, ev->phys_disk_num);
+				vtarget->tflags &=
+				    ~MPT_TARGET_FLAGS_RAID_COMPONENT;
+				vtarget->id = ev->id;
 				mptsas_reprobe_target(starget, 0);
+				phy_info->attached.phys_disk_num = ~0;
 			}
 			break;
 		}
@@ -2243,8 +2647,10 @@ mptsas_hotplug_work(struct work_struct *work)
 			dfailprintk((MYIOC_s_ERR_FMT
 				"%s: exit at line=%d\n", ioc->name,
 			       	__FUNCTION__, __LINE__));
+			if (ev->channel) printk("%d\n", __LINE__);
 			break;
 		}
+
 		port = mptsas_get_port(phy_info);
 		if (!port) {
 			dfailprintk((MYIOC_s_ERR_FMT
@@ -2252,15 +2658,17 @@ mptsas_hotplug_work(struct work_struct *work)
 			       	__FUNCTION__, __LINE__));
 			break;
 		}
-
 		memcpy(&phy_info->attached, &sas_device,
 		    sizeof(struct mptsas_devinfo));
 
-		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+		if (phy_info->attached.device_info &
+		    MPI_SAS_DEVICE_INFO_SSP_TARGET)
 			ds = "ssp";
-		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
+		if (phy_info->attached.device_info &
+		    MPI_SAS_DEVICE_INFO_STP_TARGET)
 			ds = "stp";
-		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+		if (phy_info->attached.device_info &
+		    MPI_SAS_DEVICE_INFO_SATA_DEVICE)
 			ds = "sata";
 
 		printk(MYIOC_s_INFO_FMT
@@ -2301,19 +2709,21 @@ mptsas_hotplug_work(struct work_struct *work)
 		break;
 	case MPTSAS_DEL_RAID:
 		sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
-	    	    ev->id, 0);
+		    ev->id, 0);
 		if (!sdev)
 			break;
 		printk(MYIOC_s_INFO_FMT
 		       "removing raid volume, channel %d, id %d\n",
 		       ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
 		vdevice = sdev->hostdata;
-		vdevice->vtarget->deleted = 1;
-		mptsas_target_reset(ioc, vdevice->vtarget);
 		scsi_remove_device(sdev);
 		scsi_device_put(sdev);
 		mpt_findImVolumes(ioc);
 		break;
+	case MPTSAS_ADD_INACTIVE_VOLUME:
+		mptsas_adding_inactive_raid_components(ioc,
+		    ev->channel, ev->id);
+		break;
 	case MPTSAS_IGNORE_EVENT:
 	default:
 		break;
@@ -2321,7 +2731,6 @@ mptsas_hotplug_work(struct work_struct *work)
 
 	mutex_unlock(&ioc->sas_discovery_mutex);
 	kfree(ev);
-
 }
 
 static void
@@ -2339,8 +2748,12 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc,
 		return;
 
 	switch (sas_event_data->ReasonCode) {
-	case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
 	case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
+
+		mptsas_target_reset_queue(ioc, sas_event_data);
+		break;
+
+	case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
 		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
 		if (!ev) {
 			printk(KERN_WARNING "mptsas: lost hotplug event\n");
@@ -2375,15 +2788,20 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc,
 		    mptsas_persist_clear_table);
 		schedule_work(&ioc->sas_persist_task);
 		break;
+	/*
+	 * TODO, handle other events
+	 */
 	case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
-	/* TODO */
+	case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
 	case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
-	/* TODO */
+	case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
+	case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
+	case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
+	case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
 	default:
 		break;
 	}
 }
-
 static void
 mptsas_send_raid_event(MPT_ADAPTER *ioc,
 		EVENT_DATA_RAID *raid_event_data)
@@ -2404,31 +2822,36 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc,
 	INIT_WORK(&ev->work, mptsas_hotplug_work);
 	ev->ioc = ioc;
 	ev->id = raid_event_data->VolumeID;
+	ev->channel = raid_event_data->VolumeBus;
 	ev->event_type = MPTSAS_IGNORE_EVENT;
 
 	switch (raid_event_data->ReasonCode) {
 	case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
+		ev->phys_disk_num_valid = 1;
+		ev->phys_disk_num = raid_event_data->PhysDiskNum;
 		ev->event_type = MPTSAS_ADD_DEVICE;
 		break;
 	case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
-		ioc->raid_data.isRaid = 1;
 		ev->phys_disk_num_valid = 1;
 		ev->phys_disk_num = raid_event_data->PhysDiskNum;
+		ev->hidden_raid_component = 1;
 		ev->event_type = MPTSAS_DEL_DEVICE;
 		break;
 	case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
 		switch (state) {
 		case MPI_PD_STATE_ONLINE:
-			ioc->raid_data.isRaid = 1;
+		case MPI_PD_STATE_NOT_COMPATIBLE:
 			ev->phys_disk_num_valid = 1;
 			ev->phys_disk_num = raid_event_data->PhysDiskNum;
+			ev->hidden_raid_component = 1;
 			ev->event_type = MPTSAS_ADD_DEVICE;
 			break;
 		case MPI_PD_STATE_MISSING:
-		case MPI_PD_STATE_NOT_COMPATIBLE:
 		case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
 		case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
 		case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
+			ev->phys_disk_num_valid = 1;
+			ev->phys_disk_num = raid_event_data->PhysDiskNum;
 			ev->event_type = MPTSAS_DEL_DEVICE;
 			break;
 		default:
@@ -2485,6 +2908,35 @@ mptsas_send_discovery_event(MPT_ADAPTER *ioc,
 	schedule_work(&ev->work);
 };
 
+/*
+ * mptsas_send_ir2_event - handle exposing hidden disk when
+ * an inactive raid volume is added
+ *
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @ir2_data
+ *
+ */
+static void
+mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data)
+{
+	struct mptsas_hotplug_event *ev;
+
+	if (ir2_data->ReasonCode !=
+	    MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED)
+		return;
+
+	ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
+	if (!ev)
+		return;
+
+	INIT_WORK(&ev->work, mptsas_hotplug_work);
+	ev->ioc = ioc;
+	ev->id = ir2_data->TargetID;
+	ev->channel = ir2_data->Bus;
+	ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME;
+
+	schedule_work(&ev->work);
+};
 
 static int
 mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
@@ -2524,6 +2976,10 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
 		mptsas_send_discovery_event(ioc,
 			(EVENT_DATA_SAS_DISCOVERY *)reply->Data);
 		break;
+	case MPI_EVENT_IR2:
+		mptsas_send_ir2_event(ioc,
+		    (PTR_MPI_EVENT_DATA_IR2)reply->Data);
+		break;
 	default:
 		rc = mptscsih_event_process(ioc, reply);
 		break;
@@ -2611,12 +3067,11 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	/* set 16 byte cdb's */
 	sh->max_cmd_len = 16;
 
-	sh->max_id = ioc->pfacts->MaxDevices + 1;
+	sh->max_id = ioc->pfacts[0].PortSCSIID;
+	sh->max_lun = max_lun;
 
 	sh->transportt = mptsas_transport_template;
 
-	sh->max_lun = MPT_LAST_LUN + 1;
-	sh->max_channel = 0;
 	sh->this_id = ioc->pfacts[0].PortSCSIID;
 
 	/* Required entry.
@@ -2659,8 +3114,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		sh->sg_tablesize = numSGE;
 	}
 
-	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-
 	hd = (MPT_SCSI_HOST *) sh->hostdata;
 	hd->ioc = ioc;
 
@@ -2676,19 +3129,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
 		 ioc->name, hd->ScsiLookup));
 
-	/* Allocate memory for the device structures.
-	 * A non-Null pointer at an offset
-	 * indicates a device exists.
-	 * max_id = 1 + maximum id (hosts.h)
-	 */
-	hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
-	if (!hd->Targets) {
-		error = -ENOMEM;
-		goto out_mptsas_probe;
-	}
-
-	dprintk((KERN_INFO "  vtarget @ %p\n", hd->Targets));
-
 	/* Clear the TM flags
 	 */
 	hd->tmPending = 0;
@@ -2713,15 +3153,17 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	ioc->sas_data.ptClear = mpt_pt_clear;
 
+	init_waitqueue_head(&hd->scandv_waitq);
+	hd->scandv_wait_done = 0;
+	hd->last_queue_full = 0;
+	INIT_LIST_HEAD(&hd->target_reset_list);
+	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+
 	if (ioc->sas_data.ptClear==1) {
 		mptbase_sas_persist_operation(
 		    ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
 	}
 
-	init_waitqueue_head(&hd->scandv_waitq);
-	hd->scandv_wait_done = 0;
-	hd->last_queue_full = 0;
-
 	error = scsi_add_host(sh, &ioc->pcidev->dev);
 	if (error) {
 		dprintk((KERN_ERR MYNAM
@@ -2745,7 +3187,7 @@ static void __devexit mptsas_remove(struct pci_dev *pdev)
 	struct mptsas_portinfo *p, *n;
 	int i;
 
-	ioc->sas_discovery_ignore_events=1;
+	ioc->sas_discovery_ignore_events = 1;
 	sas_remove_host(ioc->sh);
 
 	mutex_lock(&ioc->sas_topology_mutex);
@@ -2800,7 +3242,7 @@ mptsas_init(void)
 		return -ENODEV;
 
 	mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
-	mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
+	mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
 	mptsasInternalCtx =
 		mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
 	mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
@@ -2810,7 +3252,7 @@ mptsas_init(void)
 		  ": Registered for IOC event notifications\n"));
 	}
 
-	if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
+	if (mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset) == 0) {
 		dprintk((KERN_INFO MYNAM
 		  ": Registered for IOC reset notifications\n"));
 	}
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index f0cca3ea93b2..c417ae0b5fe6 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -4,7 +4,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -79,43 +79,6 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION(my_VERSION);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-typedef struct _BIG_SENSE_BUF {
-	u8		data[MPT_SENSE_BUFFER_ALLOC];
-} BIG_SENSE_BUF;
-
-#define MPT_SCANDV_GOOD			(0x00000000) /* must be 0 */
-#define MPT_SCANDV_DID_RESET		(0x00000001)
-#define MPT_SCANDV_SENSE		(0x00000002)
-#define MPT_SCANDV_SOME_ERROR		(0x00000004)
-#define MPT_SCANDV_SELECTION_TIMEOUT	(0x00000008)
-#define MPT_SCANDV_ISSUE_SENSE		(0x00000010)
-#define MPT_SCANDV_FALLBACK		(0x00000020)
-
-#define MPT_SCANDV_MAX_RETRIES		(10)
-
-#define MPT_ICFLAG_BUF_CAP	0x01	/* ReadBuffer Read Capacity format */
-#define MPT_ICFLAG_ECHO		0x02	/* ReadBuffer Echo buffer format */
-#define MPT_ICFLAG_EBOS		0x04	/* ReadBuffer Echo buffer has EBOS */
-#define MPT_ICFLAG_PHYS_DISK	0x08	/* Any SCSI IO but do Phys Disk Format */
-#define MPT_ICFLAG_TAGGED_CMD	0x10	/* Do tagged IO */
-#define MPT_ICFLAG_DID_RESET	0x20	/* Bus Reset occurred with this command */
-#define MPT_ICFLAG_RESERVED	0x40	/* Reserved has been issued */
-
-typedef struct _internal_cmd {
-	char		*data;		/* data pointer */
-	dma_addr_t	data_dma;	/* data dma address */
-	int		size;		/* transfer size */
-	u8		cmd;		/* SCSI Op Code */
-	u8		bus;		/* bus number */
-	u8		id;		/* SCSI ID (virtual) */
-	u8		lun;
-	u8		flags;		/* Bit Field - See above */
-	u8		physDiskNum;	/* Phys disk number, -1 else */
-	u8		rsvd2;
-	u8		rsvd;
-} INTERNAL_CMD;
-
 /*
  *  Other private/forward protos...
  */
@@ -131,14 +94,11 @@ static int	mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
 static int	mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
 static int	SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
 
-static int	mptscsih_IssueTaskMgmt(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 id, int lun, int ctx2abort, ulong timeout);
 
 int		mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
 int		mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
 
-static void	mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev);
-static void	mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev);
-static int	mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
 int		mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 static int	mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
 static void	mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
@@ -517,16 +477,100 @@ mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
 
 	SEPMsg = (SEPRequest_t *)mf;
 	SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
-	SEPMsg->Bus = vtarget->bus_id;
-	SEPMsg->TargetID = vtarget->target_id;
+	SEPMsg->Bus = vtarget->channel;
+	SEPMsg->TargetID = vtarget->id;
 	SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
 	SEPMsg->SlotStatus = SlotStatus;
 	devtverboseprintk((MYIOC_s_WARN_FMT
-	    "Sending SEP cmd=%x id=%d bus=%d\n",
-	    ioc->name, SlotStatus, SEPMsg->TargetID, SEPMsg->Bus));
+	    "Sending SEP cmd=%x channel=%d id=%d\n",
+	    ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID));
 	mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
 }
 
+#ifdef MPT_DEBUG_REPLY
+/**
+ *	mptscsih_iocstatus_info_scsiio - IOCSTATUS information for SCSIIO
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@ioc_status: U32 IOCStatus word from IOC
+ *	@scsi_status: U8 sam status from target
+ *	@scsi_state: U8 scsi state
+ *	@sc: original scsi cmnd pointer
+ *	@mf: Pointer to MPT request frame
+ *
+ *	Refer to lsi/mpi.h.
+ **/
+static void
+mptscsih_iocstatus_info_scsiio(MPT_ADAPTER *ioc, u32 ioc_status,
+    u8 scsi_status, u8 scsi_state, struct scsi_cmnd *sc)
+{
+	char extend_desc[EVENT_DESCR_STR_SZ];
+	char *desc = NULL;
+
+	switch (ioc_status) {
+
+	case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
+		desc = "SCSI Invalid Bus";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
+		desc = "SCSI Invalid TargetID";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
+		/*
+		 * Inquiry is issued for device scanning
+		 */
+		if (sc->cmnd[0] != 0x12)
+			desc = "SCSI Device Not There";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
+		desc = "SCSI Data Overrun";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
+		desc = "SCSI I/O Data Error";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
+		desc = "SCSI Protocol Error";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
+		desc = "SCSI Task Terminated";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
+		desc = "SCSI Residual Mismatch";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
+		desc = "SCSI Task Management Failed";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
+		desc = "SCSI IOC Terminated";
+		break;
+
+	case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
+		desc = "SCSI Ext Terminated";
+		break;
+	}
+
+	if (!desc)
+		return;
+
+	snprintf(extend_desc, EVENT_DESCR_STR_SZ,
+	    "[%d:%d:%d:%d] cmd=%02Xh, sam_status=%02Xh state=%02Xh",
+		sc->device->host->host_no,
+		sc->device->channel, sc->device->id, sc->device->lun,
+		sc->cmnd[0], scsi_status, scsi_state);
+
+	printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n",
+	    ioc->name, ioc_status, desc, extend_desc);
+}
+#endif
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *	mptscsih_io_done - Main SCSI IO callback routine registered to
@@ -613,12 +657,14 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 		u32	 xfer_cnt;
 		u16	 status;
 		u8	 scsi_state, scsi_status;
+		u32	 log_info;
 
 		status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
 		scsi_state = pScsiReply->SCSIState;
 		scsi_status = pScsiReply->SCSIStatus;
 		xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
 		sc->resid = sc->request_bufflen - xfer_cnt;
+		log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
 
 		/*
 		 *  if we get a data underrun indication, yet no data was
@@ -633,13 +679,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 			status = MPI_IOCSTATUS_SUCCESS;
 		}
 
-		dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
-			"IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
-			"resid=%d bufflen=%d xfer_cnt=%d\n",
-			ioc->id, sc->device->id, sc->device->lun,
-			status, scsi_state, scsi_status, sc->resid,
-			sc->request_bufflen, xfer_cnt));
-
 		if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
 			mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
 
@@ -648,9 +687,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 		 */
 		if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
 		    pScsiReply->ResponseInfo) {
-			printk(KERN_NOTICE "ha=%d id=%d lun=%d: "
+			printk(KERN_NOTICE "[%d:%d:%d:%d] "
 			"FCP_ResponseInfo=%08xh\n",
-			ioc->id, sc->device->id, sc->device->lun,
+			sc->device->host->host_no, sc->device->channel,
+			sc->device->id, sc->device->lun,
 			le32_to_cpu(pScsiReply->ResponseInfo));
 		}
 
@@ -695,9 +735,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 			if ( ioc->bus_type == SAS ) {
 				u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
 				if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
-					u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
-					log_info &=SAS_LOGINFO_MASK;
-					if (log_info == SAS_LOGINFO_NEXUS_LOSS) {
+					if ((log_info & SAS_LOGINFO_MASK)
+					    == SAS_LOGINFO_NEXUS_LOSS) {
 						sc->result = (DID_BUS_BUSY << 16);
 						break;
 					}
@@ -735,7 +774,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 			else /* Sufficient data transfer occurred */
 				sc->result = (DID_OK << 16) | scsi_status;
 			dreplyprintk((KERN_NOTICE
-			    "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
+			    "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n",
+			    sc->result, sc->device->channel, sc->device->id));
 			break;
 
 		case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:		/* 0x0045 */
@@ -848,7 +888,28 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 
 		}	/* switch(status) */
 
-		dreplyprintk((KERN_NOTICE "  sc->result is %08xh\n", sc->result));
+#ifdef MPT_DEBUG_REPLY
+		if (sc->result) {
+
+			mptscsih_iocstatus_info_scsiio(ioc, status,
+			    scsi_status, scsi_state, sc);
+
+			dreplyprintk(("%s: [%d:%d:%d:%d] cmd=0x%02x "
+			    "result=0x%08x\n\tiocstatus=0x%04X "
+			    "scsi_state=0x%02X scsi_status=0x%02X "
+			    "loginfo=0x%08X\n", __FUNCTION__,
+			    sc->device->host->host_no, sc->device->channel, sc->device->id,
+			    sc->device->lun, sc->cmnd[0], sc->result, status,
+			    scsi_state, scsi_status, log_info));
+
+			dreplyprintk(("%s: [%d:%d:%d:%d] resid=%d "
+			    "bufflen=%d xfer_cnt=%d\n", __FUNCTION__,
+			    sc->device->host->host_no, sc->device->channel, sc->device->id,
+			    sc->device->lun, sc->resid, sc->request_bufflen,
+			    xfer_cnt));
+		}
+#endif
+
 	} /* end of address reply case */
 
 	/* Unmap the DMA buffers, if any. */
@@ -955,9 +1016,10 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
 	int		 ii;
 	int		 max = hd->ioc->req_depth;
 	struct scsi_cmnd *sc;
+	struct scsi_lun  lun;
 
-	dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
-			vdevice->vtarget->target_id, vdevice->lun, max));
+	dsprintk((KERN_INFO MYNAM ": search_running channel %d id %d lun %d max %d\n",
+	    vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, max));
 
 	for (ii=0; ii < max; ii++) {
 		if ((sc = hd->ScsiLookup[ii]) != NULL) {
@@ -965,10 +1027,14 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
 			mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
 			if (mf == NULL)
 				continue;
-			dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
-					hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
-			if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
+			int_to_scsilun(vdevice->lun, &lun);
+			if ((mf->Bus != vdevice->vtarget->channel) ||
+			    (mf->TargetID != vdevice->vtarget->id) ||
+			    memcmp(lun.scsi_lun, mf->LUN, 8))
 				continue;
+			dsprintk(( "search_running: found (sc=%p, mf = %p) "
+			    "channel %d id %d, lun %d \n", hd->ScsiLookup[ii],
+			    mf, mf->Bus, mf->TargetID, vdevice->lun));
 
 			/* Cleanup
 			 */
@@ -1065,12 +1131,6 @@ mptscsih_remove(struct pci_dev *pdev)
 		hd->ScsiLookup = NULL;
 	}
 
-	/*
-	 * Free pointer array.
-	 */
-	kfree(hd->Targets);
-	hd->Targets = NULL;
-
 	dprintk((MYIOC_s_INFO_FMT
 	    "Free'd ScsiLookup (%d) memory\n",
 	    hd->ioc->name, sz1));
@@ -1317,14 +1377,6 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
-	if ((hd->ioc->bus_type == SPI) &&
-	    vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT &&
-	    mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) {
-		SCpnt->result = DID_NO_CONNECT << 16;
-		done(SCpnt);
-		return 0;
-	}
-
 	/*
 	 *  Put together a MPT SCSI request...
 	 */
@@ -1368,8 +1420,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 
 	/* Use the above information to set up the message frame
 	 */
-	pScsiReq->TargetID = (u8) vdev->vtarget->target_id;
-	pScsiReq->Bus = vdev->vtarget->bus_id;
+	pScsiReq->TargetID = (u8) vdev->vtarget->id;
+	pScsiReq->Bus = vdev->vtarget->channel;
 	pScsiReq->ChainOffset = 0;
 	if (vdev->vtarget->tflags &  MPT_TARGET_FLAGS_RAID_COMPONENT)
 		pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
@@ -1379,14 +1431,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
 	pScsiReq->Reserved = 0;
 	pScsiReq->MsgFlags = mpt_msg_flags();
-	pScsiReq->LUN[0] = 0;
-	pScsiReq->LUN[1] = lun;
-	pScsiReq->LUN[2] = 0;
-	pScsiReq->LUN[3] = 0;
-	pScsiReq->LUN[4] = 0;
-	pScsiReq->LUN[5] = 0;
-	pScsiReq->LUN[6] = 0;
-	pScsiReq->LUN[7] = 0;
+	int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
 	pScsiReq->Control = cpu_to_le32(scsictl);
 
 	/*
@@ -1491,14 +1536,14 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
  */
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *	mptscsih_TMHandler - Generic handler for SCSI Task Management.
  *	Fall through to mpt_HardResetHandler if: not operational, too many
  *	failed TM requests or handshake failure.
  *
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@type: Task Management type
- *	@target: Logical Target ID for reset (if appropriate)
+ *	@id: Logical Target ID for reset (if appropriate)
  *	@lun: Logical Unit for reset (if appropriate)
  *	@ctx2abort: Context for the task to be aborted (if appropriate)
  *
@@ -1507,28 +1552,17 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
  *	Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
  *	will be active.
  *
- *	Returns 0 for SUCCESS or -1 if FAILED.
- */
+ *	Returns 0 for SUCCESS, or FAILED.
+ **/
 int
-mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
+mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
 {
 	MPT_ADAPTER	*ioc;
 	int		 rc = -1;
-	int		 doTask = 1;
 	u32		 ioc_raw_state;
 	unsigned long	 flags;
 
-	/* If FW is being reloaded currently, return success to
-	 * the calling function.
-	 */
-	if (hd == NULL)
-		return 0;
-
 	ioc = hd->ioc;
-	if (ioc == NULL) {
-		printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
-		return FAILED;
-	}
 	dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
 
 	// SJR - CHECKME - Can we avoid this here?
@@ -1541,8 +1575,10 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
 	spin_unlock_irqrestore(&ioc->diagLock, flags);
 
 	/*  Wait a fixed amount of time for the TM pending flag to be cleared.
-	 *  If we time out and not bus reset, then we return a FAILED status to the caller.
-	 *  The call to mptscsih_tm_pending_wait() will set the pending flag if we are
+	 *  If we time out and not bus reset, then we return a FAILED status
+	 *  to the caller.
+	 *  The call to mptscsih_tm_pending_wait() will set the pending flag
+	 *  if we are
 	 *  successful. Otherwise, reload the FW.
 	 */
 	if (mptscsih_tm_pending_wait(hd) == FAILED) {
@@ -1552,18 +1588,16 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
 			   hd->ioc->name, hd->tmPending));
 			return FAILED;
 		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
-			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "
-			   "Timed out waiting for last TM (%d) to complete! \n",
-			   hd->ioc->name, hd->tmPending));
+			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target "
+				"reset: Timed out waiting for last TM (%d) "
+				"to complete! \n", hd->ioc->name,
+				hd->tmPending));
 			return FAILED;
 		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
 			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
 			   "Timed out waiting for last TM (%d) to complete! \n",
 			   hd->ioc->name, hd->tmPending));
-			if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
-				return FAILED;
-
-			doTask = 0;
+			return FAILED;
 		}
 	} else {
 		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
@@ -1571,47 +1605,40 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
 		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
 	}
 
-	/* Is operational?
-	 */
 	ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
 
-#ifdef MPT_DEBUG_RESET
 	if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
 		printk(MYIOC_s_WARN_FMT
-			"TM Handler: IOC Not operational(0x%x)!\n",
-			hd->ioc->name, ioc_raw_state);
-	}
-#endif
-
-	if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
-				&& !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
-
-		/* Isse the Task Mgmt request.
-		 */
-		if (hd->hard_resets < -1)
-			hd->hard_resets++;
-		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 {
-			dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
-		}
+			"TM Handler for type=%x: IOC Not operational (0x%x)!\n",
+			ioc->name, type, ioc_raw_state);
+		printk(KERN_WARNING " Issuing HardReset!!\n");
+		if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
+			printk((KERN_WARNING "TMHandler: HardReset "
+				"FAILED!!\n"));
+		return FAILED;
 	}
 
-	/* Only fall through to the HRH if this is a bus reset
-	 */
-	if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
-		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, CAN_SLEEP);
+	if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
+		printk(MYIOC_s_WARN_FMT
+			"TM Handler for type=%x: ioc_state: "
+			"DOORBELL_ACTIVE (0x%x)!\n",
+			ioc->name, type, ioc_raw_state);
+		return FAILED;
 	}
 
-	/*
-	 * Check IOCStatus from TM reply message
+	/* Isse the Task Mgmt request.
 	 */
-	 if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS)
-		rc = FAILED;
+	if (hd->hard_resets < -1)
+		hd->hard_resets++;
+
+	rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun,
+	    ctx2abort, timeout);
+	if (rc)
+		printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n",
+		       hd->ioc->name);
+	else
+		dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n",
+			   hd->ioc->name));
 
 	dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
 
@@ -1620,11 +1647,11 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
 
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
  *	mptscsih_IssueTaskMgmt - Generic send Task Management function.
  *	@hd: Pointer to MPT_SCSI_HOST structure
  *	@type: Task Management type
- *	@target: Logical Target ID for reset (if appropriate)
+ *	@id: Logical Target ID for reset (if appropriate)
  *	@lun: Logical Unit for reset (if appropriate)
  *	@ctx2abort: Context for the task to be aborted (if appropriate)
  *
@@ -1633,11 +1660,11 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
  *
  *	Not all fields are meaningfull for all task types.
  *
- *	Returns 0 for SUCCESS, -999 for "no msg frames",
- *	else other non-zero value returned.
- */
+ *	Returns 0 for SUCCESS, or FAILED.
+ *
+ **/
 static int
-mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
+mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
 {
 	MPT_FRAME_HDR	*mf;
 	SCSITaskMgmt_t	*pScsiTm;
@@ -1657,7 +1684,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
 	/* Format the Request
 	 */
 	pScsiTm = (SCSITaskMgmt_t *) mf;
-	pScsiTm->TargetID = target;
+	pScsiTm->TargetID = id;
 	pScsiTm->Bus = channel;
 	pScsiTm->ChainOffset = 0;
 	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
@@ -1668,42 +1695,59 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
 	pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
                     ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
 
-	for (ii= 0; ii < 8; ii++) {
-		pScsiTm->LUN[ii] = 0;
-	}
-	pScsiTm->LUN[1] = lun;
+	int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
 
 	for (ii=0; ii < 7; ii++)
 		pScsiTm->Reserved2[ii] = 0;
 
 	pScsiTm->TaskMsgContext = ctx2abort;
 
-	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(hd->ioc->TaskCtx, hd->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));
-		mpt_free_msg_frame(hd->ioc, mf);
-		return retval;
+		sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) {
+		dfailprintk((MYIOC_s_ERR_FMT "send_handshake FAILED!"
+			" (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd,
+			hd->ioc, mf, retval));
+		goto fail_out;
 	}
 
 	if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
-		dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
+		dfailprintk((MYIOC_s_ERR_FMT "task management request TIMED OUT!"
 			" (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);
+		dtmprintk((MYIOC_s_INFO_FMT "rc=%d \n",
+			 hd->ioc->name, retval));
+		goto fail_out;
 	}
 
+	/*
+	 * Handle success case, see if theres a non-zero ioc_status.
+	 */
+	if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS ||
+	   hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
+	   hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
+		retval = 0;
+	else
+		retval = FAILED;
+
 	return retval;
+
+ fail_out:
+
+	/*
+	 * Free task managment mf, and corresponding tm flags
+	 */
+	mpt_free_msg_frame(hd->ioc, mf);
+	hd->tmPending = 0;
+	hd->tmState = TM_STATE_NONE;
+	return FAILED;
 }
 
 static int
@@ -1728,7 +1772,7 @@ mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
  *	(linux scsi_host_template.eh_abort_handler routine)
  *
  *	Returns SUCCESS or FAILED.
- */
+ **/
 int
 mptscsih_abort(struct scsi_cmnd * SCpnt)
 {
@@ -1764,9 +1808,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 		return SUCCESS;
 	}
 
-	if (hd->resetPending) {
+	if (hd->resetPending)
 		return FAILED;
-	}
 
 	if (hd->timeouts < -1)
 		hd->timeouts++;
@@ -1789,13 +1832,12 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 
 	vdev = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
-		vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
+		vdev->vtarget->channel, vdev->vtarget->id, vdev->lun,
 		ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
 
 	if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
-	    SCpnt->serial_number == sn) {
+	    SCpnt->serial_number == sn)
 		retval = FAILED;
-	}
 
 	printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
 		hd->ioc->name,
@@ -1803,12 +1845,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 
 	if (retval == 0)
 		return SUCCESS;
-
-	if(retval != FAILED ) {
-		hd->tmPending = 0;
-		hd->tmState = TM_STATE_NONE;
-	}
-	return FAILED;
+	else
+		return FAILED;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1819,7 +1857,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
  *	(linux scsi_host_template.eh_dev_reset_handler routine)
  *
  *	Returns SUCCESS or FAILED.
- */
+ **/
 int
 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
 {
@@ -1845,7 +1883,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
 
 	vdev = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
-		vdev->vtarget->bus_id, vdev->vtarget->target_id,
+		vdev->vtarget->channel, vdev->vtarget->id,
 		0, 0, mptscsih_get_tm_timeout(hd->ioc));
 
 	printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
@@ -1854,14 +1892,11 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
 
 	if (retval == 0)
 		return SUCCESS;
-
-	if(retval != FAILED ) {
-		hd->tmPending = 0;
-		hd->tmState = TM_STATE_NONE;
-	}
-	return FAILED;
+	else
+		return FAILED;
 }
 
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *	mptscsih_bus_reset - Perform a SCSI BUS_RESET!	new_eh variant
@@ -1870,7 +1905,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
  *	(linux scsi_host_template.eh_bus_reset_handler routine)
  *
  *	Returns SUCCESS or FAILED.
- */
+ **/
 int
 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 {
@@ -1896,7 +1931,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 
 	vdev = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
-		vdev->vtarget->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
+		vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
 
 	printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
 		hd->ioc->name,
@@ -1904,12 +1939,8 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 
 	if (retval == 0)
 		return SUCCESS;
-
-	if(retval != FAILED ) {
-		hd->tmPending = 0;
-		hd->tmState = TM_STATE_NONE;
-	}
-	return FAILED;
+	else
+		return FAILED;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1992,7 +2023,6 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
 /**
  *	mptscsih_tm_wait_for_completion - wait for completion of TM task
  *	@hd: Pointer to MPT host structure.
- *	@timeout: timeout in seconds
  *
  *	Returns {SUCCESS,FAILED}.
  */
@@ -2066,7 +2096,7 @@ mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
  *	load/init time via the mpt_register() API call.
  *
  *	Returns 1 indicating alloc'd request frame ptr should be freed.
- */
+ **/
 int
 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 {
@@ -2076,78 +2106,85 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
 	unsigned long		 flags;
 	u16			 iocstatus;
 	u8			 tmType;
+	u32			 termination_count;
 
 	dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
-			ioc->name, mf, mr));
-	if (ioc->sh) {
-		/* Depending on the thread, a timer is activated for
-		 * the TM request.  Delete this timer on completion of TM.
-		 * Decrement count of outstanding TM requests.
-		 */
-		hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
-	} else {
-		dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
-			ioc->name));
+	    ioc->name, mf, mr));
+	if (!ioc->sh) {
+		dtmprintk((MYIOC_s_WARN_FMT
+		    "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name));
 		return 1;
 	}
 
 	if (mr == NULL) {
-		dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
-			ioc->name, mf));
+		dtmprintk((MYIOC_s_WARN_FMT
+		    "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf));
 		return 1;
-	} else {
-		pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
-		pScsiTmReq = (SCSITaskMgmt_t*)mf;
-
-		/* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
-		tmType = pScsiTmReq->TaskType;
+	}
 
-		if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
-		    pScsiTmReply->ResponseCode)
-			mptscsih_taskmgmt_response_code(ioc,
-			    pScsiTmReply->ResponseCode);
+	hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+	pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
+	pScsiTmReq = (SCSITaskMgmt_t*)mf;
+	tmType = pScsiTmReq->TaskType;
+	iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+	termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
+
+	if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
+	    pScsiTmReply->ResponseCode)
+		mptscsih_taskmgmt_response_code(ioc,
+		    pScsiTmReply->ResponseCode);
+	DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
+
+#if defined(MPT_DEBUG_REPLY) || defined(MPT_DEBUG_TM)
+	printk("%s: ha=%d [%d:%d:0] task_type=0x%02X "
+	    "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X "
+	    "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus,
+	    pScsiTmReply->TargetID, pScsiTmReq->TaskType,
+	    le16_to_cpu(pScsiTmReply->IOCStatus),
+	    le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode,
+	    le32_to_cpu(pScsiTmReply->TerminationCount));
+#endif
+	if (!iocstatus) {
+		dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
+			hd->abortSCpnt = NULL;
+		goto out;
+	}
 
-		dtmprintk((MYIOC_s_WARN_FMT "  TaskType = %d, TerminationCount=%d\n",
-				ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
-		DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
+	/* Error?  (anything non-zero?) */
 
-		iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
-		hd->tm_iocstatus = iocstatus;
-		dtmprintk((MYIOC_s_WARN_FMT "  SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
-			ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
-		/* Error?  (anything non-zero?) */
-		if (iocstatus) {
+	/* clear flags and continue.
+	 */
+	switch (tmType) {
 
-			/* clear flags and continue.
-			 */
-			if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
-				hd->abortSCpnt = NULL;
+	case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
+		if (termination_count == 1)
+			iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED;
+		hd->abortSCpnt = NULL;
+		break;
 
-			/* If an internal command is present
-			 * or the TM failed - reload the FW.
-			 * FC FW may respond FAILED to an ABORT
-			 */
-			if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
-				if ((hd->cmdPtr) ||
-				    (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
-					if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
-						printk((KERN_WARNING
-							" Firmware Reload FAILED!!\n"));
-					}
-				}
-			}
-		} else {
-			dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
+	case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:
 
-			hd->abortSCpnt = NULL;
+		/* If an internal command is present
+		 * or the TM failed - reload the FW.
+		 * FC FW may respond FAILED to an ABORT
+		 */
+		if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED ||
+		    hd->cmdPtr)
+			if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
+				printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
+		break;
 
-		}
+	case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
+	default:
+		break;
 	}
 
+ out:
 	spin_lock_irqsave(&ioc->FreeQlock, flags);
 	hd->tmPending = 0;
-	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 	hd->tmState = TM_STATE_NONE;
+	hd->tm_iocstatus = iocstatus;
+	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
 	return 1;
 }
@@ -2191,7 +2228,7 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
 
 	dprintk((KERN_NOTICE
 		": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
-		sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors));
+		sdev->id, sdev->lun, sdev->channel, (int)cylinders, heads, sectors));
 
 	return 0;
 }
@@ -2200,115 +2237,78 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
  *
  */
 int
-mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
+mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
 {
+	struct inactive_raid_component_info *component_info;
 	int i;
+	int rc = 0;
 
-	if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
-		return 0;
+	if (!ioc->raid_data.pIocPg3)
+		goto out;
 	for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
-                if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
-                        return 1;
-        }
-        return 0;
-}
-EXPORT_SYMBOL(mptscsih_is_phys_disk);
-
-int
-mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid)
-{
-	int i;
-
-	if (!hd->ioc->raid_data.isRaid || !hd->ioc->raid_data.pIocPg3)
-		return -ENXIO;
-
-	for (i = 0; i < hd->ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
-		if (physdiskid ==
-		    hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
-			return hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
+		if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
+		    (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
+			rc = 1;
+			goto out;
+		}
 	}
 
-	return -ENXIO;
-}
-EXPORT_SYMBOL(mptscsih_raid_id_to_num);
+	/*
+	 * Check inactive list for matching phys disks
+	 */
+	if (list_empty(&ioc->raid_data.inactive_list))
+		goto out;
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *	OS entry point to allow host driver to alloc memory
- *	for each scsi target. Called once per device the bus scan.
- *	Return non-zero if allocation fails.
- */
-int
-mptscsih_target_alloc(struct scsi_target *starget)
-{
-	VirtTarget		*vtarget;
+	down(&ioc->raid_data.inactive_list_mutex);
+	list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
+	    list) {
+		if ((component_info->d.PhysDiskID == id) &&
+		    (component_info->d.PhysDiskBus == channel))
+			rc = 1;
+	}
+	up(&ioc->raid_data.inactive_list_mutex);
 
-	vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
-	if (!vtarget)
-		return -ENOMEM;
-	starget->hostdata = vtarget;
-	vtarget->starget = starget;
-	return 0;
+ out:
+	return rc;
 }
+EXPORT_SYMBOL(mptscsih_is_phys_disk);
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *	OS entry point to allow host driver to alloc memory
- *	for each scsi device. Called once per device the bus scan.
- *	Return non-zero if allocation fails.
- */
-int
-mptscsih_slave_alloc(struct scsi_device *sdev)
+u8
+mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
 {
-	struct Scsi_Host	*host = sdev->host;
-	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)host->hostdata;
-	VirtTarget		*vtarget;
-	VirtDevice		*vdev;
-	struct scsi_target 	*starget;
+	struct inactive_raid_component_info *component_info;
+	int i;
+	int rc = -ENXIO;
 
-	vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
-	if (!vdev) {
-		printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
-				hd->ioc->name, sizeof(VirtDevice));
-		return -ENOMEM;
+	if (!ioc->raid_data.pIocPg3)
+		goto out;
+	for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+		if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
+		    (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
+			rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
+			goto out;
+		}
 	}
 
-	vdev->lun = sdev->lun;
-	sdev->hostdata = vdev;
-
-	starget = scsi_target(sdev);
-	vtarget = starget->hostdata;
+	/*
+	 * Check inactive list for matching phys disks
+	 */
+	if (list_empty(&ioc->raid_data.inactive_list))
+		goto out;
 
-	vdev->vtarget = vtarget;
-
-	if (vtarget->num_luns == 0) {
-		hd->Targets[sdev->id] = vtarget;
-		vtarget->ioc_id = hd->ioc->id;
-		vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
-		vtarget->target_id = sdev->id;
-		vtarget->bus_id = sdev->channel;
-		if (hd->ioc->bus_type == SPI && sdev->channel == 0 &&
-		    hd->ioc->raid_data.isRaid & (1 << sdev->id)) {
-			vtarget->raidVolume = 1;
-			ddvtprintk((KERN_INFO
-				    "RAID Volume @ id %d\n", sdev->id));
-		}
+	down(&ioc->raid_data.inactive_list_mutex);
+	list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
+	    list) {
+		if ((component_info->d.PhysDiskID == id) &&
+		    (component_info->d.PhysDiskBus == channel))
+			rc = component_info->d.PhysDiskNum;
 	}
-	vtarget->num_luns++;
-	return 0;
-}
+	up(&ioc->raid_data.inactive_list_mutex);
 
-/*
- *	OS entry point to allow for host driver to free allocated memory
- *	Called if no device present or device being unloaded
- */
-void
-mptscsih_target_destroy(struct scsi_target *starget)
-{
-	if (starget->hostdata)
-		kfree(starget->hostdata);
-	starget->hostdata = NULL;
+ out:
+	return rc;
 }
+EXPORT_SYMBOL(mptscsih_raid_id_to_num);
 
 /*
  *	OS entry point to allow for host driver to free allocated memory
@@ -2328,11 +2328,7 @@ mptscsih_slave_destroy(struct scsi_device *sdev)
 	vdevice = sdev->hostdata;
 
 	mptscsih_search_running_cmds(hd, vdevice);
-	vtarget->luns[0] &= ~(1 << vdevice->lun);
 	vtarget->num_luns--;
-	if (vtarget->num_luns == 0) {
-		hd->Targets[sdev->id] = NULL;
-	}
 	mptscsih_synchronize_cache(hd, vdevice);
 	kfree(vdevice);
 	sdev->hostdata = NULL;
@@ -2394,15 +2390,14 @@ mptscsih_slave_configure(struct scsi_device *sdev)
 	VirtDevice		*vdevice;
 	struct scsi_target 	*starget;
 	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)sh->hostdata;
-	int			indexed_lun, lun_index;
 
 	starget = scsi_target(sdev);
 	vtarget = starget->hostdata;
 	vdevice = sdev->hostdata;
 
 	dsprintk((MYIOC_s_INFO_FMT
-		"device @ %p, id=%d, LUN=%d, channel=%d\n",
-		hd->ioc->name, sdev, sdev->id, sdev->lun, sdev->channel));
+		"device @ %p, channel=%d, id=%d, lun=%d\n",
+		hd->ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
 	if (hd->ioc->bus_type == SPI)
 		dsprintk((MYIOC_s_INFO_FMT
 		    "sdtr %d wdtr %d ppr %d inq length=%d\n",
@@ -2415,11 +2410,7 @@ mptscsih_slave_configure(struct scsi_device *sdev)
 		goto slave_configure_exit;
 	}
 
-	vdevice->configured_lun=1;
-	lun_index = (vdevice->lun >> 5);  /* 32 luns per lun_index */
-	indexed_lun = (vdevice->lun % 32);
-	vtarget->luns[lun_index] |= (1 << indexed_lun);
-	mptscsih_initTarget(hd, vtarget, sdev);
+	vdevice->configured_lun = 1;
 	mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
 
 	dsprintk((MYIOC_s_INFO_FMT
@@ -2683,285 +2674,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	mptscsih_initTarget - Target, LUN alloc/free functionality.
- *	@hd: Pointer to MPT_SCSI_HOST structure
- *	@vtarget: per target private data
- *	@sdev: SCSI device
- *
- *	NOTE: It's only SAFE to call this routine if data points to
- *	sane & valid STANDARD INQUIRY data!
- *
- *	Allocate and initialize memory for this target.
- *	Save inquiry data.
- *
- */
-static void
-mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget,
-		    struct scsi_device *sdev)
-{
-	dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
-		hd->ioc->name, vtarget->bus_id, vtarget->target_id,
-		sdev->lun, hd));
-
-	/* Is LUN supported? If so, upper 2 bits will be 0
-	* in first byte of inquiry data.
-	*/
-	if (sdev->inq_periph_qual != 0)
-		return;
-
-	if (vtarget == NULL)
-		return;
-
-	vtarget->type = sdev->type;
-
-	if (hd->ioc->bus_type != SPI)
-		return;
-
-	if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
-		/* Treat all Processors as SAF-TE if
-		 * command line option is set */
-		vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
-		mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
-	}else if ((sdev->type == TYPE_PROCESSOR) &&
-		!(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
-		if (sdev->inquiry_len > 49 ) {
-			if (sdev->inquiry[44] == 'S' &&
-			    sdev->inquiry[45] == 'A' &&
-			    sdev->inquiry[46] == 'F' &&
-			    sdev->inquiry[47] == '-' &&
-			    sdev->inquiry[48] == 'T' &&
-			    sdev->inquiry[49] == 'E' ) {
-				vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
-				mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
-			}
-		}
-	}
-	mptscsih_setTargetNegoParms(hd, vtarget, sdev);
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *  Update the target negotiation parameters based on the
- *  the Inquiry data, adapter capabilities, and NVRAM settings.
- *
- */
-static void
-mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
-			    struct scsi_device *sdev)
-{
-	SpiCfgData *pspi_data = &hd->ioc->spi_data;
-	int  id = (int) target->target_id;
-	int  nvram;
-	u8 width = MPT_NARROW;
-	u8 factor = MPT_ASYNC;
-	u8 offset = 0;
-	u8 nfactor;
-	u8 noQas = 1;
-
-	target->negoFlags = pspi_data->noQas;
-
-	/* noQas == 0 => device supports QAS. */
-
-	if (sdev->scsi_level < SCSI_2) {
-		width = 0;
-		factor = MPT_ULTRA2;
-		offset = pspi_data->maxSyncOffset;
-		target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
-	} else {
-		if (scsi_device_wide(sdev)) {
-			width = 1;
-		}
-
-		if (scsi_device_sync(sdev)) {
-			factor = pspi_data->minSyncFactor;
-			if (!scsi_device_dt(sdev))
-					factor = MPT_ULTRA2;
-			else {
-				if (!scsi_device_ius(sdev) &&
-				    !scsi_device_qas(sdev))
-					factor = MPT_ULTRA160;
-				else {
-					factor = MPT_ULTRA320;
-					if (scsi_device_qas(sdev)) {
-						ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id));
-						noQas = 0;
-					}
-					if (sdev->type == TYPE_TAPE &&
-					    scsi_device_ius(sdev))
-						target->negoFlags |= MPT_TAPE_NEGO_IDP;
-				}
-			}
-			offset = pspi_data->maxSyncOffset;
-
-			/* If RAID, never disable QAS
-			 * else if non RAID, do not disable
-			 *   QAS if bit 1 is set
-			 * bit 1 QAS support, non-raid only
-			 * bit 0 IU support
-			 */
-			if (target->raidVolume == 1) {
-				noQas = 0;
-			}
-		} else {
-			factor = MPT_ASYNC;
-			offset = 0;
-		}
-	}
-
-	if (!sdev->tagged_supported) {
-		target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
-	}
-
-	/* Update tflags based on NVRAM settings. (SCSI only)
-	 */
-	if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
-		nvram = pspi_data->nvram[id];
-		nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
-
-		if (width)
-			width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
-
-		if (offset > 0) {
-			/* Ensure factor is set to the
-			 * maximum of: adapter, nvram, inquiry
-			 */
-			if (nfactor) {
-				if (nfactor < pspi_data->minSyncFactor )
-					nfactor = pspi_data->minSyncFactor;
-
-				factor = max(factor, nfactor);
-				if (factor == MPT_ASYNC)
-					offset = 0;
-			} else {
-				offset = 0;
-				factor = MPT_ASYNC;
-		}
-		} else {
-			factor = MPT_ASYNC;
-		}
-	}
-
-	/* Make sure data is consistent
-	 */
-	if ((!width) && (factor < MPT_ULTRA2)) {
-		factor = MPT_ULTRA2;
-	}
-
-	/* Save the data to the target structure.
-	 */
-	target->minSyncFactor = factor;
-	target->maxOffset = offset;
-	target->maxWidth = width;
-
-	target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
-
-	/* Disable unused features.
-	 */
-	if (!width)
-		target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
-
-	if (!offset)
-		target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
-
-	if ( factor > MPT_ULTRA320 )
-		noQas = 0;
-
-	if (noQas && (pspi_data->noQas == 0)) {
-		pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
-		target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
-
-		/* Disable QAS in a mixed configuration case
-		 */
-
-		ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
-	}
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *  SCSI Config Page functionality ...
- */
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*	mptscsih_writeIOCPage4  - write IOC Page 4
- *	@hd: Pointer to a SCSI Host Structure
- *	@target_id: write IOC Page4 for this ID & Bus
- *
- *	Return: -EAGAIN if unable to obtain a Message Frame
- *		or 0 if success.
- *
- *	Remark: We do not wait for a return, write pages sequentially.
- */
-static int
-mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
-{
-	MPT_ADAPTER		*ioc = hd->ioc;
-	Config_t		*pReq;
-	IOCPage4_t		*IOCPage4Ptr;
-	MPT_FRAME_HDR		*mf;
-	dma_addr_t		 dataDma;
-	u16			 req_idx;
-	u32			 frameOffset;
-	u32			 flagsLength;
-	int			 ii;
-
-	/* Get a MF for this command.
-	 */
-	if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
-		dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
-					ioc->name));
-		return -EAGAIN;
-	}
-
-	/* Set the request and the data pointers.
-	 * Place data at end of MF.
-	 */
-	pReq = (Config_t *)mf;
-
-	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
-	frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
-
-	/* Complete the request frame (same for all requests).
-	 */
-	pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-	pReq->Reserved = 0;
-	pReq->ChainOffset = 0;
-	pReq->Function = MPI_FUNCTION_CONFIG;
-	pReq->ExtPageLength = 0;
-	pReq->ExtPageType = 0;
-	pReq->MsgFlags = 0;
-	for (ii=0; ii < 8; ii++) {
-		pReq->Reserved2[ii] = 0;
-	}
-
-       	IOCPage4Ptr = ioc->spi_data.pIocPg4;
-       	dataDma = ioc->spi_data.IocPg4_dma;
-       	ii = IOCPage4Ptr->ActiveSEP++;
-       	IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
-       	IOCPage4Ptr->SEP[ii].SEPBus = bus;
-       	pReq->Header = IOCPage4Ptr->Header;
-	pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
-
-	/* Add a SGE to the config request.
-	 */
-	flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
-		(IOCPage4Ptr->Header.PageLength + ii) * 4;
-
-	mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
-
-	dinitprintk((MYIOC_s_INFO_FMT
-		"writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
-			ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
-
-	mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
-
-	return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
  *  Bus Scan and Domain Validation functionality ...
  */
 
@@ -3343,7 +3055,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 		pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
 	} else {
 		pScsiReq->TargetID = io->id;
-		pScsiReq->Bus = io->bus;
+		pScsiReq->Bus = io->channel;
 		pScsiReq->ChainOffset = 0;
 		pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
 	}
@@ -3356,9 +3068,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 	pScsiReq->MsgFlags = mpt_msg_flags();
 	/* MsgContext set in mpt_get_msg_fram call  */
 
-	for (ii=0; ii < 8; ii++)
-		pScsiReq->LUN[ii] = 0;
-	pScsiReq->LUN[1] = io->lun;
+	int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
 
 	if (io->flags & MPT_ICFLAG_TAGGED_CMD)
 		pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
@@ -3379,7 +3089,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 					   + (my_idx * MPT_SENSE_BUFFER_ALLOC));
 
 	ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
-			hd->ioc->name, cmd, io->bus, io->id, io->lun));
+			hd->ioc->name, cmd, io->channel, io->id, io->lun));
 
 	if (dir == MPI_SCSIIO_CONTROL_READ) {
 		mpt_add_sge((char *) &pScsiReq->SGL,
@@ -3462,9 +3172,9 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
 	iocmd.data_dma = -1;
 	iocmd.size = 0;
 	iocmd.rsvd = iocmd.rsvd2 = 0;
-	iocmd.bus = vdevice->vtarget->bus_id;
-	iocmd.id = vdevice->vtarget->target_id;
-	iocmd.lun = (u8)vdevice->lun;
+	iocmd.channel = vdevice->vtarget->channel;
+	iocmd.id = vdevice->vtarget->id;
+	iocmd.lun = vdevice->lun;
 
 	if ((vdevice->vtarget->type == TYPE_DISK) &&
 	    (vdevice->configured_lun))
@@ -3480,9 +3190,6 @@ EXPORT_SYMBOL(mptscsih_resume);
 EXPORT_SYMBOL(mptscsih_proc_info);
 EXPORT_SYMBOL(mptscsih_info);
 EXPORT_SYMBOL(mptscsih_qcmd);
-EXPORT_SYMBOL(mptscsih_target_alloc);
-EXPORT_SYMBOL(mptscsih_slave_alloc);
-EXPORT_SYMBOL(mptscsih_target_destroy);
 EXPORT_SYMBOL(mptscsih_slave_destroy);
 EXPORT_SYMBOL(mptscsih_slave_configure);
 EXPORT_SYMBOL(mptscsih_abort);
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 187c8af0890b..843c01a6aa0e 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -6,7 +6,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -53,6 +53,24 @@
  *	SCSI Public stuff...
  */
 
+#define MPT_SCANDV_GOOD			(0x00000000) /* must be 0 */
+#define MPT_SCANDV_DID_RESET		(0x00000001)
+#define MPT_SCANDV_SENSE		(0x00000002)
+#define MPT_SCANDV_SOME_ERROR		(0x00000004)
+#define MPT_SCANDV_SELECTION_TIMEOUT	(0x00000008)
+#define MPT_SCANDV_ISSUE_SENSE		(0x00000010)
+#define MPT_SCANDV_FALLBACK		(0x00000020)
+
+#define MPT_SCANDV_MAX_RETRIES		(10)
+
+#define MPT_ICFLAG_BUF_CAP	0x01	/* ReadBuffer Read Capacity format */
+#define MPT_ICFLAG_ECHO		0x02	/* ReadBuffer Echo buffer format */
+#define MPT_ICFLAG_EBOS		0x04	/* ReadBuffer Echo buffer has EBOS */
+#define MPT_ICFLAG_PHYS_DISK	0x08	/* Any SCSI IO but do Phys Disk Format */
+#define MPT_ICFLAG_TAGGED_CMD	0x10	/* Do tagged IO */
+#define MPT_ICFLAG_DID_RESET	0x20	/* Bus Reset occurred with this command */
+#define MPT_ICFLAG_RESERVED	0x40	/* Reserved has been issued */
+
 #define MPT_SCSI_CMD_PER_DEV_HIGH	64
 #define MPT_SCSI_CMD_PER_DEV_LOW	32
 
@@ -69,9 +87,22 @@
 #define MPTSCSIH_SAF_TE                 0
 #define MPTSCSIH_PT_CLEAR               0
 
-
 #endif
 
+typedef struct _internal_cmd {
+	char		*data;		/* data pointer */
+	dma_addr_t	data_dma;	/* data dma address */
+	int		size;		/* transfer size */
+	u8		cmd;		/* SCSI Op Code */
+	u8		channel;	/* bus number */
+	u8		id;		/* SCSI ID (virtual) */
+	int		lun;
+	u8		flags;		/* Bit Field - See above */
+	u8		physDiskNum;	/* Phys disk number, -1 else */
+	u8		rsvd2;
+	u8		rsvd;
+} INTERNAL_CMD;
+
 extern void mptscsih_remove(struct pci_dev *);
 extern void mptscsih_shutdown(struct pci_dev *);
 #ifdef CONFIG_PM
@@ -81,9 +112,6 @@ extern int mptscsih_resume(struct pci_dev *pdev);
 extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func);
 extern const char * mptscsih_info(struct Scsi_Host *SChost);
 extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *));
-extern int mptscsih_target_alloc(struct scsi_target *starget);
-extern int mptscsih_slave_alloc(struct scsi_device *device);
-extern void mptscsih_target_destroy(struct scsi_target *starget);
 extern void mptscsih_slave_destroy(struct scsi_device *device);
 extern int mptscsih_slave_configure(struct scsi_device *device);
 extern int mptscsih_abort(struct scsi_cmnd * SCpnt);
@@ -98,6 +126,6 @@ extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pE
 extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
 extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
 extern void mptscsih_timer_expired(unsigned long data);
-extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
-extern int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid);
-extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
+extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
+extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id);
+extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 203c661d2c79..c31a9e3c8a26 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -4,7 +4,7 @@
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
  *  Copyright (c) 1999-2007 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -65,6 +65,7 @@
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_transport_spi.h>
+#include <scsi/scsi_dbg.h>
 
 #include "mptbase.h"
 #include "mptscsih.h"
@@ -95,25 +96,339 @@ static int	mptspiDoneCtx = -1;
 static int	mptspiTaskCtx = -1;
 static int	mptspiInternalCtx = -1; /* Used only for internal commands */
 
+/**
+ * 	mptspi_setTargetNegoParms  - Update the target negotiation
+ *	parameters based on the the Inquiry data, adapter capabilities,
+ *	and NVRAM settings
+ *
+ *	@hd: Pointer to a SCSI Host Structure
+ *	@vtarget: per target private data
+ *	@sdev: SCSI device
+ *
+ **/
+static void
+mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
+			    struct scsi_device *sdev)
+{
+	SpiCfgData *pspi_data = &hd->ioc->spi_data;
+	int  id = (int) target->id;
+	int  nvram;
+	u8 width = MPT_NARROW;
+	u8 factor = MPT_ASYNC;
+	u8 offset = 0;
+	u8 nfactor;
+	u8 noQas = 1;
+
+	target->negoFlags = pspi_data->noQas;
+
+	if (sdev->scsi_level < SCSI_2) {
+		width = 0;
+		factor = MPT_ULTRA2;
+		offset = pspi_data->maxSyncOffset;
+		target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
+	} else {
+		if (scsi_device_wide(sdev))
+			width = 1;
+
+		if (scsi_device_sync(sdev)) {
+			factor = pspi_data->minSyncFactor;
+			if (!scsi_device_dt(sdev))
+					factor = MPT_ULTRA2;
+			else {
+				if (!scsi_device_ius(sdev) &&
+				    !scsi_device_qas(sdev))
+					factor = MPT_ULTRA160;
+				else {
+					factor = MPT_ULTRA320;
+					if (scsi_device_qas(sdev)) {
+						ddvprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id));
+						noQas = 0;
+					}
+					if (sdev->type == TYPE_TAPE &&
+					    scsi_device_ius(sdev))
+						target->negoFlags |= MPT_TAPE_NEGO_IDP;
+				}
+			}
+			offset = pspi_data->maxSyncOffset;
+
+			/* If RAID, never disable QAS
+			 * else if non RAID, do not disable
+			 *   QAS if bit 1 is set
+			 * bit 1 QAS support, non-raid only
+			 * bit 0 IU support
+			 */
+			if (target->raidVolume == 1)
+				noQas = 0;
+		} else {
+			factor = MPT_ASYNC;
+			offset = 0;
+		}
+	}
+
+	if (!sdev->tagged_supported)
+		target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
+
+	/* Update tflags based on NVRAM settings. (SCSI only)
+	 */
+	if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
+		nvram = pspi_data->nvram[id];
+		nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
+
+		if (width)
+			width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
+
+		if (offset > 0) {
+			/* Ensure factor is set to the
+			 * maximum of: adapter, nvram, inquiry
+			 */
+			if (nfactor) {
+				if (nfactor < pspi_data->minSyncFactor )
+					nfactor = pspi_data->minSyncFactor;
+
+				factor = max(factor, nfactor);
+				if (factor == MPT_ASYNC)
+					offset = 0;
+			} else {
+				offset = 0;
+				factor = MPT_ASYNC;
+		}
+		} else {
+			factor = MPT_ASYNC;
+		}
+	}
+
+	/* Make sure data is consistent
+	 */
+	if ((!width) && (factor < MPT_ULTRA2))
+		factor = MPT_ULTRA2;
+
+	/* Save the data to the target structure.
+	 */
+	target->minSyncFactor = factor;
+	target->maxOffset = offset;
+	target->maxWidth = width;
+
+	target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
+
+	/* Disable unused features.
+	 */
+	if (!width)
+		target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
+
+	if (!offset)
+		target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
+
+	if ( factor > MPT_ULTRA320 )
+		noQas = 0;
+
+	if (noQas && (pspi_data->noQas == 0)) {
+		pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
+		target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+
+		/* Disable QAS in a mixed configuration case
+		 */
+
+		ddvprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
+	}
+}
+
+/**
+ * 	mptspi_writeIOCPage4  - write IOC Page 4
+ *	@hd: Pointer to a SCSI Host Structure
+ *	@channel:
+ *	@id: write IOC Page4 for this ID & Bus
+ *
+ *	Return: -EAGAIN if unable to obtain a Message Frame
+ *		or 0 if success.
+ *
+ *	Remark: We do not wait for a return, write pages sequentially.
+ **/
+static int
+mptspi_writeIOCPage4(MPT_SCSI_HOST *hd, u8 channel , u8 id)
+{
+	MPT_ADAPTER		*ioc = hd->ioc;
+	Config_t		*pReq;
+	IOCPage4_t		*IOCPage4Ptr;
+	MPT_FRAME_HDR		*mf;
+	dma_addr_t		 dataDma;
+	u16			 req_idx;
+	u32			 frameOffset;
+	u32			 flagsLength;
+	int			 ii;
+
+	/* Get a MF for this command.
+	 */
+	if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
+		dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
+					ioc->name));
+		return -EAGAIN;
+	}
+
+	/* Set the request and the data pointers.
+	 * Place data at end of MF.
+	 */
+	pReq = (Config_t *)mf;
+
+	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+	frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
+
+	/* Complete the request frame (same for all requests).
+	 */
+	pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+	pReq->Reserved = 0;
+	pReq->ChainOffset = 0;
+	pReq->Function = MPI_FUNCTION_CONFIG;
+	pReq->ExtPageLength = 0;
+	pReq->ExtPageType = 0;
+	pReq->MsgFlags = 0;
+	for (ii=0; ii < 8; ii++) {
+		pReq->Reserved2[ii] = 0;
+	}
+
+	IOCPage4Ptr = ioc->spi_data.pIocPg4;
+	dataDma = ioc->spi_data.IocPg4_dma;
+	ii = IOCPage4Ptr->ActiveSEP++;
+	IOCPage4Ptr->SEP[ii].SEPTargetID = id;
+	IOCPage4Ptr->SEP[ii].SEPBus = channel;
+	pReq->Header = IOCPage4Ptr->Header;
+	pReq->PageAddress = cpu_to_le32(id | (channel << 8 ));
+
+	/* Add a SGE to the config request.
+	 */
+	flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
+		(IOCPage4Ptr->Header.PageLength + ii) * 4;
+
+	mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
+
+	ddvprintk((MYIOC_s_INFO_FMT
+		"writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
+			ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, channel));
+
+	mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
+
+	return 0;
+}
+
+/**
+ *	mptspi_initTarget - Target, LUN alloc/free functionality.
+ *	@hd: Pointer to MPT_SCSI_HOST structure
+ *	@vtarget: per target private data
+ *	@sdev: SCSI device
+ *
+ *	NOTE: It's only SAFE to call this routine if data points to
+ *	sane & valid STANDARD INQUIRY data!
+ *
+ *	Allocate and initialize memory for this target.
+ *	Save inquiry data.
+ *
+ **/
+static void
+mptspi_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget,
+		    struct scsi_device *sdev)
+{
+
+	/* Is LUN supported? If so, upper 2 bits will be 0
+	* in first byte of inquiry data.
+	*/
+	if (sdev->inq_periph_qual != 0)
+		return;
+
+	if (vtarget == NULL)
+		return;
+
+	vtarget->type = sdev->type;
+
+	if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
+		/* Treat all Processors as SAF-TE if
+		 * command line option is set */
+		vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+		mptspi_writeIOCPage4(hd, vtarget->channel, vtarget->id);
+	}else if ((sdev->type == TYPE_PROCESSOR) &&
+		!(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
+		if (sdev->inquiry_len > 49 ) {
+			if (sdev->inquiry[44] == 'S' &&
+			    sdev->inquiry[45] == 'A' &&
+			    sdev->inquiry[46] == 'F' &&
+			    sdev->inquiry[47] == '-' &&
+			    sdev->inquiry[48] == 'T' &&
+			    sdev->inquiry[49] == 'E' ) {
+				vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+				mptspi_writeIOCPage4(hd, vtarget->channel, vtarget->id);
+			}
+		}
+	}
+	mptspi_setTargetNegoParms(hd, vtarget, sdev);
+}
+
+/**
+ *	mptspi_is_raid - Determines whether target is belonging to volume
+ *	@hd: Pointer to a SCSI HOST structure
+ *	@id: target device id
+ *
+ *	Return:
+ *		non-zero = true
+ *		zero = false
+ *
+ */
+static int
+mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id)
+{
+	int i, rc = 0;
+
+	if (!hd->ioc->raid_data.pIocPg2)
+		goto out;
+
+	if (!hd->ioc->raid_data.pIocPg2->NumActiveVolumes)
+		goto out;
+	for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
+		if (hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) {
+			rc = 1;
+			goto out;
+		}
+	}
+
+ out:
+	return rc;
+}
+
 static int mptspi_target_alloc(struct scsi_target *starget)
 {
 	struct Scsi_Host *shost = dev_to_shost(&starget->dev);
 	struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
-	int ret;
+	VirtTarget		*vtarget;
 
 	if (hd == NULL)
 		return -ENODEV;
 
-	ret = mptscsih_target_alloc(starget);
-	if (ret)
-		return ret;
+	vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
+	if (!vtarget)
+		return -ENOMEM;
+
+	vtarget->ioc_id = hd->ioc->id;
+	vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
+	vtarget->id = (u8)starget->id;
+	vtarget->channel = (u8)starget->channel;
+	vtarget->starget = starget;
+	starget->hostdata = vtarget;
+
+	if (starget->channel == 1) {
+		if (mptscsih_is_phys_disk(hd->ioc, 0, starget->id) == 0)
+			return 0;
+		vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
+		/* The real channel for this device is zero */
+		vtarget->channel = 0;
+		/* The actual physdisknum (for RAID passthrough) */
+		vtarget->id = mptscsih_raid_id_to_num(hd->ioc, 0,
+		    starget->id);
+	}
 
-	/* if we're a device on virtual channel 1 and we're not part
-	 * of an array, just return here (otherwise the setup below
-	 * may actually affect a real physical device on channel 0 */
-	if (starget->channel == 1 &&
-	    mptscsih_raid_id_to_num(hd, starget->id) < 0)
-		return 0;
+	if (starget->channel == 0 &&
+	    mptspi_is_raid(hd, starget->id)) {
+		vtarget->raidVolume = 1;
+		ddvprintk((KERN_INFO
+		    "RAID Volume @ channel=%d id=%d\n", starget->channel,
+		    starget->id));
+	}
 
 	if (hd->ioc->spi_data.nvram &&
 	    hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) {
@@ -132,6 +447,64 @@ static int mptspi_target_alloc(struct scsi_target *starget)
 	return 0;
 }
 
+void
+mptspi_target_destroy(struct scsi_target *starget)
+{
+	if (starget->hostdata)
+		kfree(starget->hostdata);
+	starget->hostdata = NULL;
+}
+
+/**
+ *	mptspi_print_write_nego - negotiation parameters debug info that is being sent
+ *	@hd: Pointer to a SCSI HOST structure
+ *	@starget: SCSI target
+ *	@ii: negotiation parameters
+ *
+ */
+static void
+mptspi_print_write_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii)
+{
+	ddvprintk((MYIOC_s_INFO_FMT "id=%d Requested = 0x%08x"
+	    " ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n",
+	    hd->ioc->name, starget->id, ii,
+	    ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "",
+	    ((ii >> 8) & 0xFF), ((ii >> 16) & 0xFF),
+	    ii & MPI_SCSIDEVPAGE0_NP_IU ? "IU ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_DT ? "DT ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_QAS ? "QAS ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_HOLD_MCS ? "HOLDMCS ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_WR_FLOW ? "WRFLOW ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_RD_STRM ? "RDSTRM ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_RTI ? "RTI ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": ""));
+}
+
+/**
+ *	mptspi_print_read_nego - negotiation parameters debug info that is being read
+ *	@hd: Pointer to a SCSI HOST structure
+ *	@starget: SCSI target
+ *	@ii: negotiation parameters
+ *
+ */
+static void
+mptspi_print_read_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii)
+{
+	ddvprintk((MYIOC_s_INFO_FMT "id=%d Read = 0x%08x"
+	    " ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n",
+	    hd->ioc->name, starget->id, ii,
+	    ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "",
+	    ((ii >> 8) & 0xFF), ((ii >> 16) & 0xFF),
+	    ii & MPI_SCSIDEVPAGE0_NP_IU ? "IU ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_DT ? "DT ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_QAS ? "QAS ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_HOLD_MCS ? "HOLDMCS ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_WR_FLOW ? "WRFLOW ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_RD_STRM ? "RDSTRM ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_RTI ? "RTI ": "",
+	    ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": ""));
+}
+
 static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
 			     struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0)
 {
@@ -147,7 +520,7 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
 
 	/* No SPI parameters for RAID devices */
 	if (starget->channel == 0 &&
-	    (hd->ioc->raid_data.isRaid & (1 << starget->id)))
+	    mptspi_is_raid(hd, starget->id))
 		return -1;
 
 	size = ioc->spi_data.sdp0length * 4;
@@ -185,6 +558,8 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
 	err = 0;
 	memcpy(pass_pg0, pg0, size);
 
+	mptspi_print_read_nego(hd, starget, le32_to_cpu(pg0->NegotiatedParameters));
+
  out_free:
 	dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma);
 	return err;
@@ -233,7 +608,7 @@ static void mptspi_read_parameters(struct scsi_target *starget)
 }
 
 static int
-mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk)
+mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
 {
 	MpiRaidActionRequest_t	*pReq;
 	MPT_FRAME_HDR		*mf;
@@ -253,8 +628,8 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk)
 	pReq->Reserved1 = 0;
 	pReq->ChainOffset = 0;
 	pReq->Function = MPI_FUNCTION_RAID_ACTION;
-	pReq->VolumeID = disk;
-	pReq->VolumeBus = 0;
+	pReq->VolumeID = id;
+	pReq->VolumeBus = channel;
 	pReq->PhysDiskNum = 0;
 	pReq->MsgFlags = 0;
 	pReq->Reserved2 = 0;
@@ -263,8 +638,8 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk)
 	mpt_add_sge((char *)&pReq->ActionDataSGE,
 		MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
 
-	ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
-			hd->ioc->name, action, io->id));
+	ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action=%x channel=%d id=%d\n",
+			hd->ioc->name, pReq->Action, channel, id));
 
 	hd->pLocal = NULL;
 	hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
@@ -292,12 +667,12 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
 
 	/* no DV on RAID devices */
 	if (sdev->channel == 0 &&
-	    (hd->ioc->raid_data.isRaid & (1 << sdev->id)))
+	    mptspi_is_raid(hd, sdev->id))
 		return;
 
 	/* If this is a piece of a RAID, then quiesce first */
 	if (sdev->channel == 1 &&
-	    mptscsih_quiesce_raid(hd, 1, vtarget->target_id) < 0) {
+	    mptscsih_quiesce_raid(hd, 1, vtarget->channel, vtarget->id) < 0) {
 		starget_printk(KERN_ERR, scsi_target(sdev),
 			       "Integrated RAID quiesce failed\n");
 		return;
@@ -306,7 +681,7 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
 	spi_dv_device(sdev);
 
 	if (sdev->channel == 1 &&
-	    mptscsih_quiesce_raid(hd, 0, vtarget->target_id) < 0)
+	    mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0)
 		starget_printk(KERN_ERR, scsi_target(sdev),
 			       "Integrated RAID resume failed\n");
 
@@ -317,54 +692,89 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
 
 static int mptspi_slave_alloc(struct scsi_device *sdev)
 {
-	int ret;
 	MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
-	/* gcc doesn't see that all uses of this variable occur within
-	 * the if() statements, so stop it from whining */
-	int physdisknum = 0;
-
-	if (sdev->channel == 1) {
-		physdisknum = mptscsih_raid_id_to_num(hd, sdev->id);
+	VirtTarget		*vtarget;
+	VirtDevice		*vdev;
+	struct scsi_target 	*starget;
 
-		if (physdisknum < 0)
-			return physdisknum;
+	if (sdev->channel == 1 &&
+		mptscsih_is_phys_disk(hd->ioc, 0, sdev->id) == 0)
+			return -ENXIO;
+
+	vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
+	if (!vdev) {
+		printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
+				hd->ioc->name, sizeof(VirtDevice));
+		return -ENOMEM;
 	}
 
-	ret = mptscsih_slave_alloc(sdev);
+	vdev->lun = sdev->lun;
+	sdev->hostdata = vdev;
 
-	if (ret)
-		return ret;
+	starget = scsi_target(sdev);
+	vtarget = starget->hostdata;
+	vdev->vtarget = vtarget;
+	vtarget->num_luns++;
 
-	if (sdev->channel == 1) {
-		VirtDevice *vdev = sdev->hostdata;
+	if (sdev->channel == 1)
 		sdev->no_uld_attach = 1;
-		vdev->vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
-		/* The real channel for this device is zero */
-		vdev->vtarget->bus_id = 0;
-		/* The actual physdisknum (for RAID passthrough) */
-		vdev->vtarget->target_id = physdisknum;
-	}
 
 	return 0;
 }
 
 static int mptspi_slave_configure(struct scsi_device *sdev)
 {
-	int ret = mptscsih_slave_configure(sdev);
 	struct _MPT_SCSI_HOST *hd =
 		(struct _MPT_SCSI_HOST *)sdev->host->hostdata;
+	VirtTarget *vtarget = scsi_target(sdev)->hostdata;
+	int ret = mptscsih_slave_configure(sdev);
 
 	if (ret)
 		return ret;
 
+	mptspi_initTarget(hd, vtarget, sdev);
+
+	ddvprintk((MYIOC_s_INFO_FMT "id=%d min_period=0x%02x"
+		" max_offset=0x%02x max_width=%d\n", hd->ioc->name,
+		sdev->id, spi_min_period(scsi_target(sdev)),
+		spi_max_offset(scsi_target(sdev)),
+		spi_max_width(scsi_target(sdev))));
+
 	if ((sdev->channel == 1 ||
-	     !(hd->ioc->raid_data.isRaid & (1 << sdev->id))) &&
+	     !(mptspi_is_raid(hd, sdev->id))) &&
 	    !spi_initial_dv(sdev->sdev_target))
 		mptspi_dv_device(hd, sdev);
 
 	return 0;
 }
 
+static int
+mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
+{
+	struct _MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
+	VirtDevice	*vdev = SCpnt->device->hostdata;
+
+	if (!vdev || !vdev->vtarget) {
+		SCpnt->result = DID_NO_CONNECT << 16;
+		done(SCpnt);
+		return 0;
+	}
+
+	if (SCpnt->device->channel == 1 &&
+		mptscsih_is_phys_disk(hd->ioc, 0, SCpnt->device->id) == 0) {
+		SCpnt->result = DID_NO_CONNECT << 16;
+		done(SCpnt);
+		return 0;
+	}
+
+#ifdef MPT_DEBUG_DV
+	if (spi_dv_pending(scsi_target(SCpnt->device)))
+		scsi_print_command(SCpnt);
+#endif
+
+	return mptscsih_qcmd(SCpnt,done);
+}
+
 static void mptspi_slave_destroy(struct scsi_device *sdev)
 {
 	struct scsi_target *starget = scsi_target(sdev);
@@ -392,11 +802,11 @@ static struct scsi_host_template mptspi_driver_template = {
 	.proc_info			= mptscsih_proc_info,
 	.name				= "MPT SPI Host",
 	.info				= mptscsih_info,
-	.queuecommand			= mptscsih_qcmd,
+	.queuecommand			= mptspi_qcmd,
 	.target_alloc			= mptspi_target_alloc,
 	.slave_alloc			= mptspi_slave_alloc,
 	.slave_configure		= mptspi_slave_configure,
-	.target_destroy			= mptscsih_target_destroy,
+	.target_destroy			= mptspi_target_destroy,
 	.slave_destroy			= mptspi_slave_destroy,
 	.change_queue_depth 		= mptscsih_change_queue_depth,
 	.eh_abort_handler		= mptscsih_abort,
@@ -427,7 +837,7 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
 
 	/* don't allow updating nego parameters on RAID devices */
 	if (starget->channel == 0 &&
-	    (hd->ioc->raid_data.isRaid & (1 << starget->id)))
+	    mptspi_is_raid(hd, starget->id))
 		return -1;
 
 	size = ioc->spi_data.sdp1length * 4;
@@ -460,6 +870,8 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
 	pg1->Header.PageNumber = hdr.PageNumber;
 	pg1->Header.PageType = hdr.PageType;
 
+	mptspi_print_write_nego(hd, starget, le32_to_cpu(pg1->RequestedParameters));
+
 	if (mpt_config(ioc, &cfg)) {
 		starget_printk(KERN_ERR, starget, "mpt_config failed\n");
 		goto out_free;
@@ -672,9 +1084,9 @@ static void mpt_work_wrapper(struct work_struct *work)
 		if (sdev->channel != 1)
 			continue;
 
-		/* The target_id is the raid PhysDiskNum, even if
+		/* The id is the raid PhysDiskNum, even if
 		 * starget->id is the actual target address */
-		if(vtarget->target_id != disk)
+		if(vtarget->id != disk)
 			continue;
 
 		starget_printk(KERN_INFO, vtarget->starget,
@@ -727,7 +1139,7 @@ mptspi_deny_binding(struct scsi_target *starget)
 {
 	struct _MPT_SCSI_HOST *hd =
 		(struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata;
-	return ((hd->ioc->raid_data.isRaid & (1 << starget->id)) &&
+	return ((mptspi_is_raid(hd, starget->id)) &&
 		starget->channel == 0) ? 1 : 0;
 }
 
@@ -945,14 +1357,13 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	 * max_lun = 1 + actual last lun,
 	 *	see hosts.h :o(
 	 */
-	sh->max_id = MPT_MAX_SCSI_DEVICES;
+	sh->max_id = ioc->devices_per_bus;
 
 	sh->max_lun = MPT_LAST_LUN + 1;
 	/*
 	 * If RAID Firmware Detected, setup virtual channel
 	 */
-	if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
-	    > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
+	if (ioc->ir_firmware)
 		sh->max_channel = 1;
 	else
 		sh->max_channel = 0;
@@ -1009,20 +1420,6 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
 		 ioc->name, hd->ScsiLookup));
 
-	/* Allocate memory for the device structures.
-	 * A non-Null pointer at an offset
-	 * indicates a device exists.
-	 * max_id = 1 + maximum id (hosts.h)
-	 */
-	hd->Targets = kcalloc(sh->max_id * (sh->max_channel + 1),
-			      sizeof(void *), GFP_ATOMIC);
-	if (!hd->Targets) {
-		error = -ENOMEM;
-		goto out_mptspi_probe;
-	}
-
-	dprintk((KERN_INFO "  vdev @ %p\n", hd->Targets));
-
 	/* Clear the TM flags
 	 */
 	hd->tmPending = 0;
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 88642dec080c..421da1e7c0ea 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -838,32 +838,28 @@ zfcp_erp_action_exists(struct zfcp_erp_action *erp_action)
  *		and does appropriate preparations (dismiss fsf request, ...)
  *
  * locks:	called under erp_lock (disabled interrupts)
- *
- * returns:	0
  */
-static int
+static void
 zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
 {
-	int retval = 0;
-	struct zfcp_fsf_req *fsf_req = NULL;
 	struct zfcp_adapter *adapter = erp_action->adapter;
 
 	if (erp_action->fsf_req) {
 		/* take lock to ensure that request is not deleted meanwhile */
 		spin_lock(&adapter->req_list_lock);
-		if ((!zfcp_reqlist_ismember(adapter,
-					    erp_action->fsf_req->req_id)) &&
-		    (fsf_req->erp_action == erp_action)) {
+		if (zfcp_reqlist_ismember(adapter,
+					    erp_action->fsf_req->req_id)) {
 			/* fsf_req still exists */
 			debug_text_event(adapter->erp_dbf, 3, "a_ca_req");
-			debug_event(adapter->erp_dbf, 3, &fsf_req,
+			debug_event(adapter->erp_dbf, 3, &erp_action->fsf_req,
 				    sizeof (unsigned long));
 			/* dismiss fsf_req of timed out/dismissed erp_action */
 			if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED |
 						  ZFCP_STATUS_ERP_TIMEDOUT)) {
 				debug_text_event(adapter->erp_dbf, 3,
 						 "a_ca_disreq");
-				fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
+				erp_action->fsf_req->status |=
+					ZFCP_STATUS_FSFREQ_DISMISSED;
 			}
 			if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
 				ZFCP_LOG_NORMAL("error: erp step timed out "
@@ -876,11 +872,11 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
 			 * then keep it running asynchronously and don't mess
 			 * with the association of erp_action and fsf_req.
 			 */
-			if (fsf_req->status & (ZFCP_STATUS_FSFREQ_COMPLETED |
+			if (erp_action->fsf_req->status &
+					(ZFCP_STATUS_FSFREQ_COMPLETED |
 					       ZFCP_STATUS_FSFREQ_DISMISSED)) {
 				/* forget about association between fsf_req
 				   and erp_action */
-				fsf_req->erp_action = NULL;
 				erp_action->fsf_req = NULL;
 			}
 		} else {
@@ -894,8 +890,6 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
 		spin_unlock(&adapter->req_list_lock);
 	} else
 		debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq");
-
-	return retval;
 }
 
 /**
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index cda0cc095ad1..01386ac688a2 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -89,7 +89,7 @@ extern int  zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **,
 				  u32, u32, struct zfcp_sg_list *);
 extern void zfcp_fsf_start_timer(struct zfcp_fsf_req *, unsigned long);
 extern void zfcp_erp_start_timer(struct zfcp_fsf_req *);
-extern int  zfcp_fsf_req_dismiss_all(struct zfcp_adapter *);
+extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *);
 extern int  zfcp_fsf_status_read(struct zfcp_adapter *, int);
 extern int zfcp_fsf_req_create(struct zfcp_adapter *, u32, int, mempool_t *,
 			       unsigned long *, struct zfcp_fsf_req **);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 4b3ae3f22e78..ef16f7ca4bb1 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -176,28 +176,25 @@ static void zfcp_fsf_req_dismiss(struct zfcp_adapter *adapter,
 /**
  * zfcp_fsf_req_dismiss_all - dismiss all remaining fsf requests
  */
-int zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
+void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
 {
 	struct zfcp_fsf_req *request, *tmp;
 	unsigned long flags;
+	LIST_HEAD(remove_queue);
 	unsigned int i, counter;
 
 	spin_lock_irqsave(&adapter->req_list_lock, flags);
 	atomic_set(&adapter->reqs_active, 0);
-	for (i=0; i<REQUEST_LIST_SIZE; i++) {
-		if (list_empty(&adapter->req_list[i]))
-			continue;
-
-		counter = 0;
-		list_for_each_entry_safe(request, tmp,
-					 &adapter->req_list[i], list) {
-			zfcp_fsf_req_dismiss(adapter, request, counter);
-			counter++;
-		}
-	}
+	for (i=0; i<REQUEST_LIST_SIZE; i++)
+		list_splice_init(&adapter->req_list[i], &remove_queue);
+
 	spin_unlock_irqrestore(&adapter->req_list_lock, flags);
 
-	return 0;
+	counter = 0;
+	list_for_each_entry_safe(request, tmp, &remove_queue, list) {
+		zfcp_fsf_req_dismiss(adapter, request, counter);
+		counter++;
+	}
 }
 
 /*
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 68103e508db7..88e061d13d0b 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -667,12 +667,30 @@ NCR_700_chip_setup(struct Scsi_Host *host)
 	__u8 min_xferp = (hostdata->chip710 ? NCR_710_MIN_XFERP : NCR_700_MIN_XFERP);
 
 	if(hostdata->chip710) {
-		__u8 burst_disable = hostdata->burst_disable
-			? BURST_DISABLE : 0;
+		__u8 burst_disable = 0;
+		__u8 burst_length = 0;
+
+		switch (hostdata->burst_length) {
+			case 1:
+			        burst_length = BURST_LENGTH_1;
+			        break;
+			case 2:
+			        burst_length = BURST_LENGTH_2;
+			        break;
+			case 4:
+			        burst_length = BURST_LENGTH_4;
+			        break;
+			case 8:
+			        burst_length = BURST_LENGTH_8;
+			        break;
+			default:
+			        burst_disable = BURST_DISABLE;
+			        break;
+		}
 		dcntl_extra = COMPAT_700_MODE;
 
 		NCR_700_writeb(dcntl_extra, host, DCNTL_REG);
-		NCR_700_writeb(BURST_LENGTH_8  | hostdata->dmode_extra,
+		NCR_700_writeb(burst_length | hostdata->dmode_extra,
 			       host, DMODE_710_REG);
 		NCR_700_writeb(burst_disable | (hostdata->differential ? 
 						DIFF : 0), host, CTEST7_REG);
diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h
index f38822db4210..841e1bb27d57 100644
--- a/drivers/scsi/53c700.h
+++ b/drivers/scsi/53c700.h
@@ -203,7 +203,7 @@ struct NCR_700_Host_Parameters {
 	__u32	force_le_on_be:1;
 #endif
 	__u32	chip710:1;	/* set if really a 710 not 700 */
-	__u32	burst_disable:1;	/* set to 1 to disable 710 bursting */
+	__u32	burst_length:4;	/* set to 0 to disable 710 bursting */
 
 	/* NOTHING BELOW HERE NEEDS ALTERING */
 	__u32	fast:1;		/* if we can alter the SCSI bus clock
diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c
index 9c3794310879..93b41f45638a 100644
--- a/drivers/scsi/53c7xx.c
+++ b/drivers/scsi/53c7xx.c
@@ -4399,7 +4399,7 @@ abort_connected (struct Scsi_Host *host) {
  * account the current synchronous offset) 
  */
 
-    sstat = (NCR53c8x0_read8 (SSTAT2_REG);
+    sstat = NCR53c8x0_read8 (SSTAT2_REG);
     offset = OFFSET (sstat & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT;
     phase = sstat & SSTAT2_PHASE_MASK;
 
@@ -5422,7 +5422,7 @@ insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) {
     	    	     --buffers, offset += segment->length, ++segment)
 #if 0
 		    printk("scsi%d: comparing 0x%p to 0x%p\n", 
-			cmd->device->host->host_no, saved, page_address(segment->page+segment->offset);
+			cmd->device->host->host_no, saved, page_address(segment->page+segment->offset));
 #else
 		    ;
 #endif
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 3075204915c8..e874b8944875 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -192,7 +192,7 @@ static void BusLogic_InitializeCCBs(struct BusLogic_HostAdapter *HostAdapter, vo
   BusLogic_CreateInitialCCBs allocates the initial CCBs for Host Adapter.
 */
 
-static boolean __init BusLogic_CreateInitialCCBs(struct BusLogic_HostAdapter *HostAdapter)
+static bool __init BusLogic_CreateInitialCCBs(struct BusLogic_HostAdapter *HostAdapter)
 {
 	int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB);
 	void *BlockPointer;
@@ -238,7 +238,7 @@ static void BusLogic_DestroyCCBs(struct BusLogic_HostAdapter *HostAdapter)
   multiple host adapters share the same IRQ Channel.
 */
 
-static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapter, int AdditionalCCBs, boolean SuccessMessageP)
+static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapter, int AdditionalCCBs, bool SuccessMessageP)
 {
 	int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB);
 	int PreviouslyAllocated = HostAdapter->AllocatedCCBs;
@@ -362,10 +362,8 @@ static int BusLogic_Command(struct BusLogic_HostAdapter *HostAdapter, enum BusLo
 	   interrupt could occur if the IRQ Channel was previously enabled by another
 	   BusLogic Host Adapter or another driver sharing the same IRQ Channel.
 	 */
-	if (!HostAdapter->IRQ_ChannelAcquired) {
+	if (!HostAdapter->IRQ_ChannelAcquired)
 		local_irq_save(ProcessorFlags);
-		local_irq_disable();
-	}
 	/*
 	   Wait for the Host Adapter Ready bit to be set and the Command/Parameter
 	   Register Busy bit to be reset in the Status Register.
@@ -639,9 +637,9 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd
 	struct BusLogic_ProbeInfo *PrimaryProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount];
 	int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount + 1;
 	int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0;
-	boolean ForceBusDeviceScanningOrder = false;
-	boolean ForceBusDeviceScanningOrderChecked = false;
-	boolean StandardAddressSeen[6];
+	bool ForceBusDeviceScanningOrder = false;
+	bool ForceBusDeviceScanningOrderChecked = false;
+	bool StandardAddressSeen[6];
 	struct pci_dev *PCI_Device = NULL;
 	int i;
 	if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters)
@@ -1011,7 +1009,7 @@ static void __init BusLogic_InitializeProbeInfoList(struct BusLogic_HostAdapter
   BusLogic_Failure prints a standardized error message, and then returns false.
 */
 
-static boolean BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter, char *ErrorMessage)
+static bool BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter, char *ErrorMessage)
 {
 	BusLogic_AnnounceDriver(HostAdapter);
 	if (HostAdapter->HostAdapterBusType == BusLogic_PCI_Bus) {
@@ -1030,7 +1028,7 @@ static boolean BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter, char *
   BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter.
 */
 
-static boolean __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
+static bool __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
 {
 	union BusLogic_StatusRegister StatusRegister;
 	union BusLogic_InterruptRegister InterruptRegister;
@@ -1101,8 +1099,8 @@ static boolean __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *Hos
   SCSI Bus Reset.
 */
 
-static boolean BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter
-						 *HostAdapter, boolean HardReset)
+static bool BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter
+						 *HostAdapter, bool HardReset)
 {
 	union BusLogic_StatusRegister StatusRegister;
 	int TimeoutCounter;
@@ -1205,11 +1203,11 @@ static boolean BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter
   Host Adapter.
 */
 
-static boolean __init BusLogic_CheckHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
+static bool __init BusLogic_CheckHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
 {
 	struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation;
 	unsigned char RequestedReplyLength;
-	boolean Result = true;
+	bool Result = true;
 	/*
 	   FlashPoint Host Adapters do not require this protection.
 	 */
@@ -1239,7 +1237,7 @@ static boolean __init BusLogic_CheckHostAdapter(struct BusLogic_HostAdapter *Hos
   from Host Adapter and initializes the Host Adapter structure.
 */
 
-static boolean __init BusLogic_ReadHostAdapterConfiguration(struct BusLogic_HostAdapter
+static bool __init BusLogic_ReadHostAdapterConfiguration(struct BusLogic_HostAdapter
 							    *HostAdapter)
 {
 	struct BusLogic_BoardID BoardID;
@@ -1686,14 +1684,14 @@ static boolean __init BusLogic_ReadHostAdapterConfiguration(struct BusLogic_Host
   Host Adapter.
 */
 
-static boolean __init BusLogic_ReportHostAdapterConfiguration(struct BusLogic_HostAdapter
+static bool __init BusLogic_ReportHostAdapterConfiguration(struct BusLogic_HostAdapter
 							      *HostAdapter)
 {
 	unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1;
 	unsigned short SynchronousPermitted, FastPermitted;
 	unsigned short UltraPermitted, WidePermitted;
 	unsigned short DisconnectPermitted, TaggedQueuingPermitted;
-	boolean CommonSynchronousNegotiation, CommonTaggedQueueDepth;
+	bool CommonSynchronousNegotiation, CommonTaggedQueueDepth;
 	char SynchronousString[BusLogic_MaxTargetDevices + 1];
 	char WideString[BusLogic_MaxTargetDevices + 1];
 	char DisconnectString[BusLogic_MaxTargetDevices + 1];
@@ -1835,7 +1833,7 @@ static boolean __init BusLogic_ReportHostAdapterConfiguration(struct BusLogic_Ho
   Host Adapter.
 */
 
-static boolean __init BusLogic_AcquireResources(struct BusLogic_HostAdapter *HostAdapter)
+static bool __init BusLogic_AcquireResources(struct BusLogic_HostAdapter *HostAdapter)
 {
 	if (HostAdapter->IRQ_Channel == 0) {
 		BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n", HostAdapter);
@@ -1903,7 +1901,7 @@ static void BusLogic_ReleaseResources(struct BusLogic_HostAdapter *HostAdapter)
   of the Host Adapter from its initial power on or hard reset state.
 */
 
-static boolean BusLogic_InitializeHostAdapter(struct BusLogic_HostAdapter
+static bool BusLogic_InitializeHostAdapter(struct BusLogic_HostAdapter
 					      *HostAdapter)
 {
 	struct BusLogic_ExtendedMailboxRequest ExtendedMailboxRequest;
@@ -2002,7 +2000,7 @@ static boolean BusLogic_InitializeHostAdapter(struct BusLogic_HostAdapter
   through Host Adapter.
 */
 
-static boolean __init BusLogic_TargetDeviceInquiry(struct BusLogic_HostAdapter
+static bool __init BusLogic_TargetDeviceInquiry(struct BusLogic_HostAdapter
 						   *HostAdapter)
 {
 	u16 InstalledDevices;
@@ -2739,7 +2737,7 @@ static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel, void *DeviceIdenti
   already have been acquired by the caller.
 */
 
-static boolean BusLogic_WriteOutgoingMailbox(struct BusLogic_HostAdapter
+static bool BusLogic_WriteOutgoingMailbox(struct BusLogic_HostAdapter
 					     *HostAdapter, enum BusLogic_ActionCode ActionCode, struct BusLogic_CCB *CCB)
 {
 	struct BusLogic_OutgoingMailbox *NextOutgoingMailbox;
@@ -3058,7 +3056,7 @@ static int BusLogic_AbortCommand(struct scsi_cmnd *Command)
   currently executing SCSI Commands as having been Reset.
 */
 
-static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, boolean HardReset)
+static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, bool HardReset)
 {
 	struct BusLogic_CCB *CCB;
 	int TargetID;
@@ -3309,7 +3307,7 @@ Target	Requested Completed  Requested Completed  Requested Completed\n\
 static void BusLogic_Message(enum BusLogic_MessageLevel MessageLevel, char *Format, struct BusLogic_HostAdapter *HostAdapter, ...)
 {
 	static char Buffer[BusLogic_LineBufferSize];
-	static boolean BeginningOfLine = true;
+	static bool BeginningOfLine = true;
 	va_list Arguments;
 	int Length = 0;
 	va_start(Arguments, HostAdapter);
@@ -3347,7 +3345,7 @@ static void BusLogic_Message(enum BusLogic_MessageLevel MessageLevel, char *Form
   and updates the pointer if the keyword is recognized and false otherwise.
 */
 
-static boolean __init BusLogic_ParseKeyword(char **StringPointer, char *Keyword)
+static bool __init BusLogic_ParseKeyword(char **StringPointer, char *Keyword)
 {
 	char *Pointer = *StringPointer;
 	while (*Keyword != '\0') {
diff --git a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h
index cca6d45eee4d..bfbfb5c3a8f6 100644
--- a/drivers/scsi/BusLogic.h
+++ b/drivers/scsi/BusLogic.h
@@ -234,12 +234,6 @@ enum BusLogic_BIOS_DiskGeometryTranslation {
 
 
 /*
-  Define a Boolean data type.
-*/
-
-typedef bool boolean;
-
-/*
   Define a 10^18 Statistics Byte Counter data type.
 */
 
@@ -269,19 +263,19 @@ struct BusLogic_ProbeInfo {
 */
 
 struct BusLogic_ProbeOptions {
-	boolean NoProbe:1;	/* Bit 0 */
-	boolean NoProbeISA:1;	/* Bit 1 */
-	boolean NoProbePCI:1;	/* Bit 2 */
-	boolean NoSortPCI:1;	/* Bit 3 */
-	boolean MultiMasterFirst:1;	/* Bit 4 */
-	boolean FlashPointFirst:1;	/* Bit 5 */
-	boolean LimitedProbeISA:1;	/* Bit 6 */
-	boolean Probe330:1;	/* Bit 7 */
-	boolean Probe334:1;	/* Bit 8 */
-	boolean Probe230:1;	/* Bit 9 */
-	boolean Probe234:1;	/* Bit 10 */
-	boolean Probe130:1;	/* Bit 11 */
-	boolean Probe134:1;	/* Bit 12 */
+	bool NoProbe:1;		/* Bit 0 */
+	bool NoProbeISA:1;	/* Bit 1 */
+	bool NoProbePCI:1;	/* Bit 2 */
+	bool NoSortPCI:1;	/* Bit 3 */
+	bool MultiMasterFirst:1;/* Bit 4 */
+	bool FlashPointFirst:1;	/* Bit 5 */
+	bool LimitedProbeISA:1;	/* Bit 6 */
+	bool Probe330:1;	/* Bit 7 */
+	bool Probe334:1;	/* Bit 8 */
+	bool Probe230:1;	/* Bit 9 */
+	bool Probe234:1;	/* Bit 10 */
+	bool Probe130:1;	/* Bit 11 */
+	bool Probe134:1;	/* Bit 12 */
 };
 
 /*
@@ -289,10 +283,10 @@ struct BusLogic_ProbeOptions {
 */
 
 struct BusLogic_GlobalOptions {
-	boolean TraceProbe:1;	/* Bit 0 */
-	boolean TraceHardwareReset:1;	/* Bit 1 */
-	boolean TraceConfiguration:1;	/* Bit 2 */
-	boolean TraceErrors:1;	/* Bit 3 */
+	bool TraceProbe:1;	/* Bit 0 */
+	bool TraceHardwareReset:1;	/* Bit 1 */
+	bool TraceConfiguration:1;	/* Bit 2 */
+	bool TraceErrors:1;	/* Bit 3 */
 };
 
 /*
@@ -300,7 +294,7 @@ struct BusLogic_GlobalOptions {
 */
 
 struct BusLogic_LocalOptions {
-	boolean InhibitTargetInquiry:1;	/* Bit 0 */
+	bool InhibitTargetInquiry:1;	/* Bit 0 */
 };
 
 /*
@@ -322,10 +316,10 @@ union BusLogic_ControlRegister {
 	unsigned char All;
 	struct {
 		unsigned char:4;	/* Bits 0-3 */
-		boolean SCSIBusReset:1;	/* Bit 4 */
-		boolean InterruptReset:1;	/* Bit 5 */
-		boolean SoftReset:1;	/* Bit 6 */
-		boolean HardReset:1;	/* Bit 7 */
+		bool SCSIBusReset:1;	/* Bit 4 */
+		bool InterruptReset:1;	/* Bit 5 */
+		bool SoftReset:1;	/* Bit 6 */
+		bool HardReset:1;	/* Bit 7 */
 	} cr;
 };
 
@@ -336,14 +330,14 @@ union BusLogic_ControlRegister {
 union BusLogic_StatusRegister {
 	unsigned char All;
 	struct {
-		boolean CommandInvalid:1;	/* Bit 0 */
-		boolean Reserved:1;	/* Bit 1 */
-		boolean DataInRegisterReady:1;	/* Bit 2 */
-		boolean CommandParameterRegisterBusy:1;	/* Bit 3 */
-		boolean HostAdapterReady:1;	/* Bit 4 */
-		boolean InitializationRequired:1;	/* Bit 5 */
-		boolean DiagnosticFailure:1;	/* Bit 6 */
-		boolean DiagnosticActive:1;	/* Bit 7 */
+		bool CommandInvalid:1;		/* Bit 0 */
+		bool Reserved:1;		/* Bit 1 */
+		bool DataInRegisterReady:1;	/* Bit 2 */
+		bool CommandParameterRegisterBusy:1;	/* Bit 3 */
+		bool HostAdapterReady:1;	/* Bit 4 */
+		bool InitializationRequired:1;	/* Bit 5 */
+		bool DiagnosticFailure:1;	/* Bit 6 */
+		bool DiagnosticActive:1;	/* Bit 7 */
 	} sr;
 };
 
@@ -354,12 +348,12 @@ union BusLogic_StatusRegister {
 union BusLogic_InterruptRegister {
 	unsigned char All;
 	struct {
-		boolean IncomingMailboxLoaded:1;	/* Bit 0 */
-		boolean OutgoingMailboxAvailable:1;	/* Bit 1 */
-		boolean CommandComplete:1;	/* Bit 2 */
-		boolean ExternalBusReset:1;	/* Bit 3 */
+		bool IncomingMailboxLoaded:1;	/* Bit 0 */
+		bool OutgoingMailboxAvailable:1;/* Bit 1 */
+		bool CommandComplete:1;		/* Bit 2 */
+		bool ExternalBusReset:1;	/* Bit 3 */
 		unsigned char Reserved:3;	/* Bits 4-6 */
-		boolean InterruptValid:1;	/* Bit 7 */
+		bool InterruptValid:1;		/* Bit 7 */
 	} ir;
 };
 
@@ -373,7 +367,7 @@ union BusLogic_GeometryRegister {
 		enum BusLogic_BIOS_DiskGeometryTranslation Drive0Geometry:2;	/* Bits 0-1 */
 		enum BusLogic_BIOS_DiskGeometryTranslation Drive1Geometry:2;	/* Bits 2-3 */
 		unsigned char:3;	/* Bits 4-6 */
-		boolean ExtendedTranslationEnabled:1;	/* Bit 7 */
+		bool ExtendedTranslationEnabled:1;	/* Bit 7 */
 	} gr;
 };
 
@@ -445,16 +439,16 @@ struct BusLogic_BoardID {
 
 struct BusLogic_Configuration {
 	unsigned char:5;	/* Byte 0 Bits 0-4 */
-	boolean DMA_Channel5:1;	/* Byte 0 Bit 5 */
-	boolean DMA_Channel6:1;	/* Byte 0 Bit 6 */
-	boolean DMA_Channel7:1;	/* Byte 0 Bit 7 */
-	boolean IRQ_Channel9:1;	/* Byte 1 Bit 0 */
-	boolean IRQ_Channel10:1;	/* Byte 1 Bit 1 */
-	boolean IRQ_Channel11:1;	/* Byte 1 Bit 2 */
-	boolean IRQ_Channel12:1;	/* Byte 1 Bit 3 */
+	bool DMA_Channel5:1;	/* Byte 0 Bit 5 */
+	bool DMA_Channel6:1;	/* Byte 0 Bit 6 */
+	bool DMA_Channel7:1;	/* Byte 0 Bit 7 */
+	bool IRQ_Channel9:1;	/* Byte 1 Bit 0 */
+	bool IRQ_Channel10:1;	/* Byte 1 Bit 1 */
+	bool IRQ_Channel11:1;	/* Byte 1 Bit 2 */
+	bool IRQ_Channel12:1;	/* Byte 1 Bit 3 */
 	unsigned char:1;	/* Byte 1 Bit 4 */
-	boolean IRQ_Channel14:1;	/* Byte 1 Bit 5 */
-	boolean IRQ_Channel15:1;	/* Byte 1 Bit 6 */
+	bool IRQ_Channel14:1;	/* Byte 1 Bit 5 */
+	bool IRQ_Channel15:1;	/* Byte 1 Bit 6 */
 	unsigned char:1;	/* Byte 1 Bit 7 */
 	unsigned char HostAdapterID:4;	/* Byte 2 Bits 0-3 */
 	unsigned char:4;	/* Byte 2 Bits 4-7 */
@@ -467,12 +461,12 @@ struct BusLogic_Configuration {
 struct BusLogic_SynchronousValue {
 	unsigned char Offset:4;	/* Bits 0-3 */
 	unsigned char TransferPeriod:3;	/* Bits 4-6 */
-	boolean Synchronous:1;	/* Bit 7 */
+	bool Synchronous:1;	/* Bit 7 */
 };
 
 struct BusLogic_SetupInformation {
-	boolean SynchronousInitiationEnabled:1;	/* Byte 0 Bit 0 */
-	boolean ParityCheckingEnabled:1;	/* Byte 0 Bit 1 */
+	bool SynchronousInitiationEnabled:1;	/* Byte 0 Bit 0 */
+	bool ParityCheckingEnabled:1;		/* Byte 0 Bit 1 */
 	unsigned char:6;	/* Byte 0 Bits 2-7 */
 	unsigned char BusTransferRate;	/* Byte 1 */
 	unsigned char PreemptTimeOnBus;	/* Byte 2 */
@@ -523,13 +517,13 @@ enum BusLogic_ISACompatibleIOPort {
 struct BusLogic_PCIHostAdapterInformation {
 	enum BusLogic_ISACompatibleIOPort ISACompatibleIOPort;	/* Byte 0 */
 	unsigned char PCIAssignedIRQChannel;	/* Byte 1 */
-	boolean LowByteTerminated:1;	/* Byte 2 Bit 0 */
-	boolean HighByteTerminated:1;	/* Byte 2 Bit 1 */
+	bool LowByteTerminated:1;	/* Byte 2 Bit 0 */
+	bool HighByteTerminated:1;	/* Byte 2 Bit 1 */
 	unsigned char:2;	/* Byte 2 Bits 2-3 */
-	boolean JP1:1;		/* Byte 2 Bit 4 */
-	boolean JP2:1;		/* Byte 2 Bit 5 */
-	boolean JP3:1;		/* Byte 2 Bit 6 */
-	boolean GenericInfoValid:1;	/* Byte 2 Bit 7 */
+	bool JP1:1;		/* Byte 2 Bit 4 */
+	bool JP2:1;		/* Byte 2 Bit 5 */
+	bool JP3:1;		/* Byte 2 Bit 6 */
+	bool GenericInfoValid:1;/* Byte 2 Bit 7 */
 	unsigned char:8;	/* Byte 3 */
 };
 
@@ -545,17 +539,17 @@ struct BusLogic_ExtendedSetupInformation {
 	u32 BaseMailboxAddress;	/* Bytes 5-8 */
 	struct {
 		unsigned char:2;	/* Byte 9 Bits 0-1 */
-		boolean FastOnEISA:1;	/* Byte 9 Bit 2 */
+		bool FastOnEISA:1;	/* Byte 9 Bit 2 */
 		unsigned char:3;	/* Byte 9 Bits 3-5 */
-		boolean LevelSensitiveInterrupt:1;	/* Byte 9 Bit 6 */
+		bool LevelSensitiveInterrupt:1;	/* Byte 9 Bit 6 */
 		unsigned char:1;	/* Byte 9 Bit 7 */
 	} Misc;
 	unsigned char FirmwareRevision[3];	/* Bytes 10-12 */
-	boolean HostWideSCSI:1;	/* Byte 13 Bit 0 */
-	boolean HostDifferentialSCSI:1;	/* Byte 13 Bit 1 */
-	boolean HostSupportsSCAM:1;	/* Byte 13 Bit 2 */
-	boolean HostUltraSCSI:1;	/* Byte 13 Bit 3 */
-	boolean HostSmartTermination:1;	/* Byte 13 Bit 4 */
+	bool HostWideSCSI:1;		/* Byte 13 Bit 0 */
+	bool HostDifferentialSCSI:1;	/* Byte 13 Bit 1 */
+	bool HostSupportsSCAM:1;	/* Byte 13 Bit 2 */
+	bool HostUltraSCSI:1;		/* Byte 13 Bit 3 */
+	bool HostSmartTermination:1;	/* Byte 13 Bit 4 */
 	unsigned char:3;	/* Byte 13 Bits 5-7 */
 } PACKED;
 
@@ -590,35 +584,35 @@ struct BusLogic_AutoSCSIData {
 	unsigned char InformationByteCount;	/* Byte 2 */
 	unsigned char HostAdapterType[6];	/* Bytes 3-8 */
 	unsigned char:8;	/* Byte 9 */
-	boolean FloppyEnabled:1;	/* Byte 10 Bit 0 */
-	boolean FloppySecondary:1;	/* Byte 10 Bit 1 */
-	boolean LevelSensitiveInterrupt:1;	/* Byte 10 Bit 2 */
+	bool FloppyEnabled:1;		/* Byte 10 Bit 0 */
+	bool FloppySecondary:1;		/* Byte 10 Bit 1 */
+	bool LevelSensitiveInterrupt:1;	/* Byte 10 Bit 2 */
 	unsigned char:2;	/* Byte 10 Bits 3-4 */
 	unsigned char SystemRAMAreaForBIOS:3;	/* Byte 10 Bits 5-7 */
 	unsigned char DMA_Channel:7;	/* Byte 11 Bits 0-6 */
-	boolean DMA_AutoConfiguration:1;	/* Byte 11 Bit 7 */
+	bool DMA_AutoConfiguration:1;	/* Byte 11 Bit 7 */
 	unsigned char IRQ_Channel:7;	/* Byte 12 Bits 0-6 */
-	boolean IRQ_AutoConfiguration:1;	/* Byte 12 Bit 7 */
+	bool IRQ_AutoConfiguration:1;	/* Byte 12 Bit 7 */
 	unsigned char DMA_TransferRate;	/* Byte 13 */
 	unsigned char SCSI_ID;	/* Byte 14 */
-	boolean LowByteTerminated:1;	/* Byte 15 Bit 0 */
-	boolean ParityCheckingEnabled:1;	/* Byte 15 Bit 1 */
-	boolean HighByteTerminated:1;	/* Byte 15 Bit 2 */
-	boolean NoisyCablingEnvironment:1;	/* Byte 15 Bit 3 */
-	boolean FastSynchronousNegotiation:1;	/* Byte 15 Bit 4 */
-	boolean BusResetEnabled:1;	/* Byte 15 Bit 5 */
-	 boolean:1;		/* Byte 15 Bit 6 */
-	boolean ActiveNegationEnabled:1;	/* Byte 15 Bit 7 */
+	bool LowByteTerminated:1;	/* Byte 15 Bit 0 */
+	bool ParityCheckingEnabled:1;	/* Byte 15 Bit 1 */
+	bool HighByteTerminated:1;	/* Byte 15 Bit 2 */
+	bool NoisyCablingEnvironment:1;	/* Byte 15 Bit 3 */
+	bool FastSynchronousNegotiation:1;	/* Byte 15 Bit 4 */
+	bool BusResetEnabled:1;		/* Byte 15 Bit 5 */
+	 bool:1;		/* Byte 15 Bit 6 */
+	bool ActiveNegationEnabled:1;	/* Byte 15 Bit 7 */
 	unsigned char BusOnDelay;	/* Byte 16 */
 	unsigned char BusOffDelay;	/* Byte 17 */
-	boolean HostAdapterBIOSEnabled:1;	/* Byte 18 Bit 0 */
-	boolean BIOSRedirectionOfINT19Enabled:1;	/* Byte 18 Bit 1 */
-	boolean ExtendedTranslationEnabled:1;	/* Byte 18 Bit 2 */
-	boolean MapRemovableAsFixedEnabled:1;	/* Byte 18 Bit 3 */
-	 boolean:1;		/* Byte 18 Bit 4 */
-	boolean BIOSSupportsMoreThan2DrivesEnabled:1;	/* Byte 18 Bit 5 */
-	boolean BIOSInterruptModeEnabled:1;	/* Byte 18 Bit 6 */
-	boolean FlopticalSupportEnabled:1;	/* Byte 19 Bit 7 */
+	bool HostAdapterBIOSEnabled:1;		/* Byte 18 Bit 0 */
+	bool BIOSRedirectionOfINT19Enabled:1;	/* Byte 18 Bit 1 */
+	bool ExtendedTranslationEnabled:1;	/* Byte 18 Bit 2 */
+	bool MapRemovableAsFixedEnabled:1;	/* Byte 18 Bit 3 */
+	 bool:1;		/* Byte 18 Bit 4 */
+	bool BIOSSupportsMoreThan2DrivesEnabled:1;	/* Byte 18 Bit 5 */
+	bool BIOSInterruptModeEnabled:1;	/* Byte 18 Bit 6 */
+	bool FlopticalSupportEnabled:1;		/* Byte 19 Bit 7 */
 	unsigned short DeviceEnabled;	/* Bytes 19-20 */
 	unsigned short WidePermitted;	/* Bytes 21-22 */
 	unsigned short FastPermitted;	/* Bytes 23-24 */
@@ -628,22 +622,22 @@ struct BusLogic_AutoSCSIData {
 	unsigned short IgnoreInBIOSScan;	/* Bytes 31-32 */
 	unsigned char PCIInterruptPin:2;	/* Byte 33 Bits 0-1 */
 	unsigned char HostAdapterIOPortAddress:2;	/* Byte 33 Bits 2-3 */
-	boolean StrictRoundRobinModeEnabled:1;	/* Byte 33 Bit 4 */
-	boolean VESABusSpeedGreaterThan33MHz:1;	/* Byte 33 Bit 5 */
-	boolean VESABurstWriteEnabled:1;	/* Byte 33 Bit 6 */
-	boolean VESABurstReadEnabled:1;	/* Byte 33 Bit 7 */
+	bool StrictRoundRobinModeEnabled:1;	/* Byte 33 Bit 4 */
+	bool VESABusSpeedGreaterThan33MHz:1;	/* Byte 33 Bit 5 */
+	bool VESABurstWriteEnabled:1;	/* Byte 33 Bit 6 */
+	bool VESABurstReadEnabled:1;	/* Byte 33 Bit 7 */
 	unsigned short UltraPermitted;	/* Bytes 34-35 */
 	unsigned int:32;	/* Bytes 36-39 */
 	unsigned char:8;	/* Byte 40 */
 	unsigned char AutoSCSIMaximumLUN;	/* Byte 41 */
-	 boolean:1;		/* Byte 42 Bit 0 */
-	boolean SCAM_Dominant:1;	/* Byte 42 Bit 1 */
-	boolean SCAM_Enabled:1;	/* Byte 42 Bit 2 */
-	boolean SCAM_Level2:1;	/* Byte 42 Bit 3 */
+	 bool:1;		/* Byte 42 Bit 0 */
+	bool SCAM_Dominant:1;	/* Byte 42 Bit 1 */
+	bool SCAM_Enabled:1;	/* Byte 42 Bit 2 */
+	bool SCAM_Level2:1;	/* Byte 42 Bit 3 */
 	unsigned char:4;	/* Byte 42 Bits 4-7 */
-	boolean INT13ExtensionEnabled:1;	/* Byte 43 Bit 0 */
-	 boolean:1;		/* Byte 43 Bit 1 */
-	boolean CDROMBootEnabled:1;	/* Byte 43 Bit 2 */
+	bool INT13ExtensionEnabled:1;	/* Byte 43 Bit 0 */
+	 bool:1;		/* Byte 43 Bit 1 */
+	bool CDROMBootEnabled:1;	/* Byte 43 Bit 2 */
 	unsigned char:5;	/* Byte 43 Bits 3-7 */
 	unsigned char BootTargetID:4;	/* Byte 44 Bits 0-3 */
 	unsigned char BootChannel:4;	/* Byte 44 Bits 4-7 */
@@ -852,7 +846,7 @@ struct BusLogic_CCB {
 	enum BusLogic_CCB_Opcode Opcode;	/* Byte 0 */
 	unsigned char:3;	/* Byte 1 Bits 0-2 */
 	enum BusLogic_DataDirection DataDirection:2;	/* Byte 1 Bits 3-4 */
-	boolean TagEnable:1;	/* Byte 1 Bit 5 */
+	bool TagEnable:1;	/* Byte 1 Bit 5 */
 	enum BusLogic_QueueTag QueueTag:2;	/* Byte 1 Bits 6-7 */
 	unsigned char CDB_Length;	/* Byte 2 */
 	unsigned char SenseDataLength;	/* Byte 3 */
@@ -864,7 +858,7 @@ struct BusLogic_CCB {
 	enum BusLogic_TargetDeviceStatus TargetDeviceStatus;	/* Byte 15 */
 	unsigned char TargetID;	/* Byte 16 */
 	unsigned char LogicalUnit:5;	/* Byte 17 Bits 0-4 */
-	boolean LegacyTagEnable:1;	/* Byte 17 Bit 5 */
+	bool LegacyTagEnable:1;	/* Byte 17 Bit 5 */
 	enum BusLogic_QueueTag LegacyQueueTag:2;	/* Byte 17 Bits 6-7 */
 	SCSI_CDB_T CDB;		/* Bytes 18-29 */
 	unsigned char:8;	/* Byte 30 */
@@ -939,13 +933,13 @@ struct BusLogic_DriverOptions {
 */
 
 struct BusLogic_TargetFlags {
-	boolean TargetExists:1;
-	boolean TaggedQueuingSupported:1;
-	boolean WideTransfersSupported:1;
-	boolean TaggedQueuingActive:1;
-	boolean WideTransfersActive:1;
-	boolean CommandSuccessfulFlag:1;
-	boolean TargetInfoReported:1;
+	bool TargetExists:1;
+	bool TaggedQueuingSupported:1;
+	bool WideTransfersSupported:1;
+	bool TaggedQueuingActive:1;
+	bool WideTransfersActive:1;
+	bool CommandSuccessfulFlag:1;
+	bool TargetInfoReported:1;
 };
 
 /*
@@ -992,7 +986,7 @@ typedef unsigned int FlashPoint_CardHandle_T;
 
 struct FlashPoint_Info {
 	u32 BaseAddress;	/* Bytes 0-3 */
-	boolean Present;	/* Byte 4 */
+	bool Present;		/* Byte 4 */
 	unsigned char IRQ_Channel;	/* Byte 5 */
 	unsigned char SCSI_ID;	/* Byte 6 */
 	unsigned char SCSI_LUN;	/* Byte 7 */
@@ -1002,15 +996,15 @@ struct FlashPoint_Info {
 	unsigned short UltraPermitted;	/* Bytes 14-15 */
 	unsigned short DisconnectPermitted;	/* Bytes 16-17 */
 	unsigned short WidePermitted;	/* Bytes 18-19 */
-	boolean ParityCheckingEnabled:1;	/* Byte 20 Bit 0 */
-	boolean HostWideSCSI:1;	/* Byte 20 Bit 1 */
-	boolean HostSoftReset:1;	/* Byte 20 Bit 2 */
-	boolean ExtendedTranslationEnabled:1;	/* Byte 20 Bit 3 */
-	boolean LowByteTerminated:1;	/* Byte 20 Bit 4 */
-	boolean HighByteTerminated:1;	/* Byte 20 Bit 5 */
-	boolean ReportDataUnderrun:1;	/* Byte 20 Bit 6 */
-	boolean SCAM_Enabled:1;	/* Byte 20 Bit 7 */
-	boolean SCAM_Level2:1;	/* Byte 21 Bit 0 */
+	bool ParityCheckingEnabled:1;	/* Byte 20 Bit 0 */
+	bool HostWideSCSI:1;		/* Byte 20 Bit 1 */
+	bool HostSoftReset:1;		/* Byte 20 Bit 2 */
+	bool ExtendedTranslationEnabled:1;	/* Byte 20 Bit 3 */
+	bool LowByteTerminated:1;	/* Byte 20 Bit 4 */
+	bool HighByteTerminated:1;	/* Byte 20 Bit 5 */
+	bool ReportDataUnderrun:1;	/* Byte 20 Bit 6 */
+	bool SCAM_Enabled:1;	/* Byte 20 Bit 7 */
+	bool SCAM_Level2:1;	/* Byte 21 Bit 0 */
 	unsigned char:7;	/* Byte 21 Bits 1-7 */
 	unsigned char Family;	/* Byte 22 */
 	unsigned char BusType;	/* Byte 23 */
@@ -1044,29 +1038,29 @@ struct BusLogic_HostAdapter {
 	unsigned char IRQ_Channel;
 	unsigned char DMA_Channel;
 	unsigned char SCSI_ID;
-	boolean IRQ_ChannelAcquired:1;
-	boolean DMA_ChannelAcquired:1;
-	boolean ExtendedTranslationEnabled:1;
-	boolean ParityCheckingEnabled:1;
-	boolean BusResetEnabled:1;
-	boolean LevelSensitiveInterrupt:1;
-	boolean HostWideSCSI:1;
-	boolean HostDifferentialSCSI:1;
-	boolean HostSupportsSCAM:1;
-	boolean HostUltraSCSI:1;
-	boolean ExtendedLUNSupport:1;
-	boolean TerminationInfoValid:1;
-	boolean LowByteTerminated:1;
-	boolean HighByteTerminated:1;
-	boolean BounceBuffersRequired:1;
-	boolean StrictRoundRobinModeSupport:1;
-	boolean SCAM_Enabled:1;
-	boolean SCAM_Level2:1;
-	boolean HostAdapterInitialized:1;
-	boolean HostAdapterExternalReset:1;
-	boolean HostAdapterInternalError:1;
-	boolean ProcessCompletedCCBsActive;
-	volatile boolean HostAdapterCommandCompleted;
+	bool IRQ_ChannelAcquired:1;
+	bool DMA_ChannelAcquired:1;
+	bool ExtendedTranslationEnabled:1;
+	bool ParityCheckingEnabled:1;
+	bool BusResetEnabled:1;
+	bool LevelSensitiveInterrupt:1;
+	bool HostWideSCSI:1;
+	bool HostDifferentialSCSI:1;
+	bool HostSupportsSCAM:1;
+	bool HostUltraSCSI:1;
+	bool ExtendedLUNSupport:1;
+	bool TerminationInfoValid:1;
+	bool LowByteTerminated:1;
+	bool HighByteTerminated:1;
+	bool BounceBuffersRequired:1;
+	bool StrictRoundRobinModeSupport:1;
+	bool SCAM_Enabled:1;
+	bool SCAM_Level2:1;
+	bool HostAdapterInitialized:1;
+	bool HostAdapterExternalReset:1;
+	bool HostAdapterInternalError:1;
+	bool ProcessCompletedCCBsActive;
+	volatile bool HostAdapterCommandCompleted;
 	unsigned short HostAdapterScatterGatherLimit;
 	unsigned short DriverScatterGatherLimit;
 	unsigned short MaxTargetDevices;
@@ -1141,25 +1135,25 @@ struct SCSI_Inquiry {
 	unsigned char PeripheralDeviceType:5;	/* Byte 0 Bits 0-4 */
 	unsigned char PeripheralQualifier:3;	/* Byte 0 Bits 5-7 */
 	unsigned char DeviceTypeModifier:7;	/* Byte 1 Bits 0-6 */
-	boolean RMB:1;		/* Byte 1 Bit 7 */
+	bool RMB:1;		/* Byte 1 Bit 7 */
 	unsigned char ANSI_ApprovedVersion:3;	/* Byte 2 Bits 0-2 */
 	unsigned char ECMA_Version:3;	/* Byte 2 Bits 3-5 */
 	unsigned char ISO_Version:2;	/* Byte 2 Bits 6-7 */
 	unsigned char ResponseDataFormat:4;	/* Byte 3 Bits 0-3 */
 	unsigned char:2;	/* Byte 3 Bits 4-5 */
-	boolean TrmIOP:1;	/* Byte 3 Bit 6 */
-	boolean AENC:1;		/* Byte 3 Bit 7 */
+	bool TrmIOP:1;		/* Byte 3 Bit 6 */
+	bool AENC:1;		/* Byte 3 Bit 7 */
 	unsigned char AdditionalLength;	/* Byte 4 */
 	unsigned char:8;	/* Byte 5 */
 	unsigned char:8;	/* Byte 6 */
-	boolean SftRe:1;	/* Byte 7 Bit 0 */
-	boolean CmdQue:1;	/* Byte 7 Bit 1 */
-	 boolean:1;		/* Byte 7 Bit 2 */
-	boolean Linked:1;	/* Byte 7 Bit 3 */
-	boolean Sync:1;		/* Byte 7 Bit 4 */
-	boolean WBus16:1;	/* Byte 7 Bit 5 */
-	boolean WBus32:1;	/* Byte 7 Bit 6 */
-	boolean RelAdr:1;	/* Byte 7 Bit 7 */
+	bool SftRe:1;		/* Byte 7 Bit 0 */
+	bool CmdQue:1;		/* Byte 7 Bit 1 */
+	 bool:1;		/* Byte 7 Bit 2 */
+	bool Linked:1;		/* Byte 7 Bit 3 */
+	bool Sync:1;		/* Byte 7 Bit 4 */
+	bool WBus16:1;		/* Byte 7 Bit 5 */
+	bool WBus32:1;		/* Byte 7 Bit 6 */
+	bool RelAdr:1;		/* Byte 7 Bit 7 */
 	unsigned char VendorIdentification[8];	/* Bytes 8-15 */
 	unsigned char ProductIdentification[16];	/* Bytes 16-31 */
 	unsigned char ProductRevisionLevel[4];	/* Bytes 32-35 */
@@ -1348,7 +1342,7 @@ static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *, char *, char **, off_t
 static int BusLogic_SlaveConfigure(struct scsi_device *);
 static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *);
 static irqreturn_t BusLogic_InterruptHandler(int, void *);
-static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *, boolean HardReset);
+static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *, bool HardReset);
 static void BusLogic_Message(enum BusLogic_MessageLevel, char *, struct BusLogic_HostAdapter *, ...);
 static int __init BusLogic_Setup(char *);
 
diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c
index 7c0068049586..a7f916c0c9cd 100644
--- a/drivers/scsi/FlashPoint.c
+++ b/drivers/scsi/FlashPoint.c
@@ -7609,7 +7609,7 @@ FlashPoint__AbortCCB(FlashPoint_CardHandle_T CardHandle,
 	FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB);
 }
 
-static inline boolean
+static inline bool
 FlashPoint__InterruptPending(FlashPoint_CardHandle_T CardHandle)
 {
 	return FlashPoint_InterruptPending(CardHandle);
@@ -7640,7 +7640,7 @@ extern FlashPoint_CardHandle_T
 FlashPoint_HardwareResetHostAdapter(struct FlashPoint_Info *);
 extern void FlashPoint_StartCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
 extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
-extern boolean FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
+extern bool FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
 extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T);
 extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T);
 
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 7869c34a4a3e..5bf3f07870ba 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -973,6 +973,15 @@ config SCSI_LASI700
 	  many PA-RISC workstations & servers.  If you do not know whether you
 	  have a Lasi chip, it is safe to say "Y" here.
 
+config SCSI_SNI_53C710
+	tristate "SNI RM SCSI support for 53c710"
+	depends on SNI_RM && SCSI
+	select SCSI_SPI_ATTRS
+	select 53C700_LE_ON_BE
+	help
+	  This is a driver for the onboard SCSI controller found in older
+	  SNI RM workstations & servers.
+
 config 53C700_LE_ON_BE
 	bool
 	depends on SCSI_LASI700
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index bd7c9888f7f4..79ecf4ebe6eb 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -124,6 +124,7 @@ obj-$(CONFIG_JAZZ_ESP)		+= NCR53C9x.o	jazz_esp.o
 obj-$(CONFIG_SUN3X_ESP)		+= NCR53C9x.o	sun3x_esp.o
 obj-$(CONFIG_SCSI_FCAL)		+= fcal.o
 obj-$(CONFIG_SCSI_LASI700)	+= 53c700.o lasi700.o
+obj-$(CONFIG_SCSI_SNI_53C710)	+= 53c700.o sni_53c710.o
 obj-$(CONFIG_SCSI_NSP32)	+= nsp32.o
 obj-$(CONFIG_SCSI_IPR)		+= ipr.o
 obj-$(CONFIG_SCSI_SRP)		+= libsrp.o
diff --git a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c
index 9859cd17fc57..f12864abed2f 100644
--- a/drivers/scsi/NCR_D700.c
+++ b/drivers/scsi/NCR_D700.c
@@ -200,6 +200,7 @@ NCR_D700_probe_one(struct NCR_D700_private *p, int siop, int irq,
 	hostdata->base = ioport_map(region, 64);
 	hostdata->differential = (((1<<siop) & differential) != 0);
 	hostdata->clock = NCR_D700_CLOCK_MHZ;
+	hostdata->burst_length = 8;
 
 	/* and register the siop */
 	host = NCR_700_detect(&NCR_D700_driver_template, hostdata, p->dev);
diff --git a/drivers/scsi/aacraid/Makefile b/drivers/scsi/aacraid/Makefile
index 28d133a3094f..f1cca4ee5410 100644
--- a/drivers/scsi/aacraid/Makefile
+++ b/drivers/scsi/aacraid/Makefile
@@ -3,6 +3,6 @@
 obj-$(CONFIG_SCSI_AACRAID) := aacraid.o
 
 aacraid-objs	:= linit.o aachba.o commctrl.o comminit.o commsup.o \
-		   dpcsup.o rx.o sa.o rkt.o
+		   dpcsup.o rx.o sa.o rkt.o nark.o
 
 EXTRA_CFLAGS	:= -Idrivers/scsi
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 426cd6f49f5d..ddb33b06e0ef 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -170,9 +170,9 @@ int acbsize = -1;
 module_param(acbsize, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512, 2048, 4096 and 8192. Default is to use suggestion from Firmware.");
 
-int expose_physicals = 0;
+int expose_physicals = -1;
 module_param(expose_physicals, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. 0=off, 1=on");
+MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on");
 /**
  *	aac_get_config_status	-	check the adapter configuration
  *	@common: adapter to query
@@ -706,6 +706,309 @@ static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
 	}
 }
 
+static int aac_bounds_32(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba)
+{
+	if (lba & 0xffffffff00000000LL) {
+		int cid = scmd_id(cmd);
+		dprintk((KERN_DEBUG "aacraid: Illegal lba\n"));
+		cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
+			SAM_STAT_CHECK_CONDITION;
+		set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
+			    HARDWARE_ERROR,
+			    SENCODE_INTERNAL_TARGET_FAILURE,
+			    ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
+			    0, 0);
+		memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
+		  (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(cmd->sense_buffer))
+		    ? sizeof(cmd->sense_buffer)
+		    : sizeof(dev->fsa_dev[cid].sense_data));
+		cmd->scsi_done(cmd);
+		return 1;
+	}
+	return 0;
+}
+
+static int aac_bounds_64(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba)
+{
+	return 0;
+}
+
+static void io_callback(void *context, struct fib * fibptr);
+
+static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+{
+	u16 fibsize;
+	struct aac_raw_io *readcmd;
+	aac_fib_init(fib);
+	readcmd = (struct aac_raw_io *) fib_data(fib);
+	readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
+	readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
+	readcmd->count = cpu_to_le32(count<<9);
+	readcmd->cid = cpu_to_le16(scmd_id(cmd));
+	readcmd->flags = cpu_to_le16(1);
+	readcmd->bpTotal = 0;
+	readcmd->bpComplete = 0;
+
+	aac_build_sgraw(cmd, &readcmd->sg);
+	fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw));
+	BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr)));
+	/*
+	 *	Now send the Fib to the adapter
+	 */
+	return aac_fib_send(ContainerRawIo,
+			  fib,
+			  fibsize,
+			  FsaNormal,
+			  0, 1,
+			  (fib_callback) io_callback,
+			  (void *) cmd);
+}
+
+static int aac_read_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+{
+	u16 fibsize;
+	struct aac_read64 *readcmd;
+	aac_fib_init(fib);
+	readcmd = (struct aac_read64 *) fib_data(fib);
+	readcmd->command = cpu_to_le32(VM_CtHostRead64);
+	readcmd->cid = cpu_to_le16(scmd_id(cmd));
+	readcmd->sector_count = cpu_to_le16(count);
+	readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
+	readcmd->pad   = 0;
+	readcmd->flags = 0;
+
+	aac_build_sg64(cmd, &readcmd->sg);
+	fibsize = sizeof(struct aac_read64) +
+		((le32_to_cpu(readcmd->sg.count) - 1) *
+		 sizeof (struct sgentry64));
+	BUG_ON (fibsize > (fib->dev->max_fib_size -
+				sizeof(struct aac_fibhdr)));
+	/*
+	 *	Now send the Fib to the adapter
+	 */
+	return aac_fib_send(ContainerCommand64,
+			  fib,
+			  fibsize,
+			  FsaNormal,
+			  0, 1,
+			  (fib_callback) io_callback,
+			  (void *) cmd);
+}
+
+static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+{
+	u16 fibsize;
+	struct aac_read *readcmd;
+	aac_fib_init(fib);
+	readcmd = (struct aac_read *) fib_data(fib);
+	readcmd->command = cpu_to_le32(VM_CtBlockRead);
+	readcmd->cid = cpu_to_le16(scmd_id(cmd));
+	readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
+	readcmd->count = cpu_to_le32(count * 512);
+
+	aac_build_sg(cmd, &readcmd->sg);
+	fibsize = sizeof(struct aac_read) +
+			((le32_to_cpu(readcmd->sg.count) - 1) *
+			 sizeof (struct sgentry));
+	BUG_ON (fibsize > (fib->dev->max_fib_size -
+				sizeof(struct aac_fibhdr)));
+	/*
+	 *	Now send the Fib to the adapter
+	 */
+	return aac_fib_send(ContainerCommand,
+			  fib,
+			  fibsize,
+			  FsaNormal,
+			  0, 1,
+			  (fib_callback) io_callback,
+			  (void *) cmd);
+}
+
+static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+{
+	u16 fibsize;
+	struct aac_raw_io *writecmd;
+	aac_fib_init(fib);
+	writecmd = (struct aac_raw_io *) fib_data(fib);
+	writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
+	writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
+	writecmd->count = cpu_to_le32(count<<9);
+	writecmd->cid = cpu_to_le16(scmd_id(cmd));
+	writecmd->flags = 0;
+	writecmd->bpTotal = 0;
+	writecmd->bpComplete = 0;
+
+	aac_build_sgraw(cmd, &writecmd->sg);
+	fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw));
+	BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr)));
+	/*
+	 *	Now send the Fib to the adapter
+	 */
+	return aac_fib_send(ContainerRawIo,
+			  fib,
+			  fibsize,
+			  FsaNormal,
+			  0, 1,
+			  (fib_callback) io_callback,
+			  (void *) cmd);
+}
+
+static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+{
+	u16 fibsize;
+	struct aac_write64 *writecmd;
+	aac_fib_init(fib);
+	writecmd = (struct aac_write64 *) fib_data(fib);
+	writecmd->command = cpu_to_le32(VM_CtHostWrite64);
+	writecmd->cid = cpu_to_le16(scmd_id(cmd));
+	writecmd->sector_count = cpu_to_le16(count);
+	writecmd->block = cpu_to_le32((u32)(lba&0xffffffff));
+	writecmd->pad	= 0;
+	writecmd->flags	= 0;
+
+	aac_build_sg64(cmd, &writecmd->sg);
+	fibsize = sizeof(struct aac_write64) +
+		((le32_to_cpu(writecmd->sg.count) - 1) *
+		 sizeof (struct sgentry64));
+	BUG_ON (fibsize > (fib->dev->max_fib_size -
+				sizeof(struct aac_fibhdr)));
+	/*
+	 *	Now send the Fib to the adapter
+	 */
+	return aac_fib_send(ContainerCommand64,
+			  fib,
+			  fibsize,
+			  FsaNormal,
+			  0, 1,
+			  (fib_callback) io_callback,
+			  (void *) cmd);
+}
+
+static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
+{
+	u16 fibsize;
+	struct aac_write *writecmd;
+	aac_fib_init(fib);
+	writecmd = (struct aac_write *) fib_data(fib);
+	writecmd->command = cpu_to_le32(VM_CtBlockWrite);
+	writecmd->cid = cpu_to_le16(scmd_id(cmd));
+	writecmd->block = cpu_to_le32((u32)(lba&0xffffffff));
+	writecmd->count = cpu_to_le32(count * 512);
+	writecmd->sg.count = cpu_to_le32(1);
+	/* ->stable is not used - it did mean which type of write */
+
+	aac_build_sg(cmd, &writecmd->sg);
+	fibsize = sizeof(struct aac_write) +
+		((le32_to_cpu(writecmd->sg.count) - 1) *
+		 sizeof (struct sgentry));
+	BUG_ON (fibsize > (fib->dev->max_fib_size -
+				sizeof(struct aac_fibhdr)));
+	/*
+	 *	Now send the Fib to the adapter
+	 */
+	return aac_fib_send(ContainerCommand,
+			  fib,
+			  fibsize,
+			  FsaNormal,
+			  0, 1,
+			  (fib_callback) io_callback,
+			  (void *) cmd);
+}
+
+static struct aac_srb * aac_scsi_common(struct fib * fib, struct scsi_cmnd * cmd)
+{
+	struct aac_srb * srbcmd;
+	u32 flag;
+	u32 timeout;
+
+	aac_fib_init(fib);
+	switch(cmd->sc_data_direction){
+	case DMA_TO_DEVICE:
+		flag = SRB_DataOut;
+		break;
+	case DMA_BIDIRECTIONAL:
+		flag = SRB_DataIn | SRB_DataOut;
+		break;
+	case DMA_FROM_DEVICE:
+		flag = SRB_DataIn;
+		break;
+	case DMA_NONE:
+	default:	/* shuts up some versions of gcc */
+		flag = SRB_NoDataXfer;
+		break;
+	}
+
+	srbcmd = (struct aac_srb*) fib_data(fib);
+	srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
+	srbcmd->channel  = cpu_to_le32(aac_logical_to_phys(scmd_channel(cmd)));
+	srbcmd->id       = cpu_to_le32(scmd_id(cmd));
+	srbcmd->lun      = cpu_to_le32(cmd->device->lun);
+	srbcmd->flags    = cpu_to_le32(flag);
+	timeout = cmd->timeout_per_command/HZ;
+	if (timeout == 0)
+		timeout = 1;
+	srbcmd->timeout  = cpu_to_le32(timeout);  // timeout in seconds
+	srbcmd->retry_limit = 0; /* Obsolete parameter */
+	srbcmd->cdb_size = cpu_to_le32(cmd->cmd_len);
+	return srbcmd;
+}
+
+static void aac_srb_callback(void *context, struct fib * fibptr);
+
+static int aac_scsi_64(struct fib * fib, struct scsi_cmnd * cmd)
+{
+	u16 fibsize;
+	struct aac_srb * srbcmd = aac_scsi_common(fib, cmd);
+
+	aac_build_sg64(cmd, (struct sgmap64*) &srbcmd->sg);
+	srbcmd->count = cpu_to_le32(cmd->request_bufflen);
+
+	memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
+	memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len);
+	/*
+	 *	Build Scatter/Gather list
+	 */
+	fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) +
+		((le32_to_cpu(srbcmd->sg.count) & 0xff) *
+		 sizeof (struct sgentry64));
+	BUG_ON (fibsize > (fib->dev->max_fib_size -
+				sizeof(struct aac_fibhdr)));
+
+	/*
+	 *	Now send the Fib to the adapter
+	 */
+	return aac_fib_send(ScsiPortCommand64, fib,
+				fibsize, FsaNormal, 0, 1,
+				  (fib_callback) aac_srb_callback,
+				  (void *) cmd);
+}
+
+static int aac_scsi_32(struct fib * fib, struct scsi_cmnd * cmd)
+{
+	u16 fibsize;
+	struct aac_srb * srbcmd = aac_scsi_common(fib, cmd);
+
+	aac_build_sg(cmd, (struct sgmap*)&srbcmd->sg);
+	srbcmd->count = cpu_to_le32(cmd->request_bufflen);
+
+	memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
+	memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len);
+	/*
+	 *	Build Scatter/Gather list
+	 */
+	fibsize = sizeof (struct aac_srb) +
+		(((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) *
+		 sizeof (struct sgentry));
+	BUG_ON (fibsize > (fib->dev->max_fib_size -
+				sizeof(struct aac_fibhdr)));
+
+	/*
+	 *	Now send the Fib to the adapter
+	 */
+	return aac_fib_send(ScsiPortCommand, fib, fibsize, FsaNormal, 0, 1,
+				  (fib_callback) aac_srb_callback, (void *) cmd);
+}
+
 int aac_get_adapter_info(struct aac_dev* dev)
 {
 	struct fib* fibptr;
@@ -874,14 +1177,27 @@ int aac_get_adapter_info(struct aac_dev* dev)
 		}
 	}
 	/* 
-	 * 57 scatter gather elements 
+	 * Deal with configuring for the individualized limits of each packet
+	 * interface.
 	 */
-	if (!(dev->raw_io_interface)) {
+	dev->a_ops.adapter_scsi = (dev->dac_support)
+				? aac_scsi_64
+				: aac_scsi_32;
+	if (dev->raw_io_interface) {
+		dev->a_ops.adapter_bounds = (dev->raw_io_64)
+					? aac_bounds_64
+					: aac_bounds_32;
+		dev->a_ops.adapter_read = aac_read_raw_io;
+		dev->a_ops.adapter_write = aac_write_raw_io;
+	} else {
+		dev->a_ops.adapter_bounds = aac_bounds_32;
 		dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size -
 			sizeof(struct aac_fibhdr) -
 			sizeof(struct aac_write) + sizeof(struct sgentry)) /
 				sizeof(struct sgentry);
 		if (dev->dac_support) {
+			dev->a_ops.adapter_read = aac_read_block64;
+			dev->a_ops.adapter_write = aac_write_block64;
 			/* 
 			 * 38 scatter gather elements 
 			 */
@@ -891,6 +1207,9 @@ int aac_get_adapter_info(struct aac_dev* dev)
 				sizeof(struct aac_write64) +
 				sizeof(struct sgentry64)) /
 					sizeof(struct sgentry64);
+		} else {
+			dev->a_ops.adapter_read = aac_read_block;
+			dev->a_ops.adapter_write = aac_write_block;
 		}
 		dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
 		if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
@@ -1004,8 +1323,6 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
 	u64 lba;
 	u32 count;
 	int status;
-
-	u16 fibsize;
 	struct aac_dev *dev;
 	struct fib * cmd_fibcontext;
 
@@ -1059,23 +1376,8 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
 	}
 	dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %llu, t = %ld.\n",
 	  smp_processor_id(), (unsigned long long)lba, jiffies));
-	if ((!(dev->raw_io_interface) || !(dev->raw_io_64)) &&
-		(lba & 0xffffffff00000000LL)) {
-		dprintk((KERN_DEBUG "aac_read: Illegal lba\n"));
-		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | 
-			SAM_STAT_CHECK_CONDITION;
-		set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
-			    HARDWARE_ERROR,
-			    SENCODE_INTERNAL_TARGET_FAILURE,
-			    ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
-			    0, 0);
-		memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
-		  (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer))
-		    ? sizeof(scsicmd->sense_buffer)
-		    : sizeof(dev->fsa_dev[cid].sense_data));
-		scsicmd->scsi_done(scsicmd);
+	if (aac_adapter_bounds(dev,scsicmd,lba))
 		return 0;
-	}
 	/*
 	 *	Alocate and initialize a Fib
 	 */
@@ -1083,85 +1385,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
 		return -1;
 	}
 
-	aac_fib_init(cmd_fibcontext);
-
-	if (dev->raw_io_interface) {
-		struct aac_raw_io *readcmd;
-		readcmd = (struct aac_raw_io *) fib_data(cmd_fibcontext);
-		readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
-		readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
-		readcmd->count = cpu_to_le32(count<<9);
-		readcmd->cid = cpu_to_le16(cid);
-		readcmd->flags = cpu_to_le16(1);
-		readcmd->bpTotal = 0;
-		readcmd->bpComplete = 0;
-		
-		aac_build_sgraw(scsicmd, &readcmd->sg);
-		fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw));
-		BUG_ON(fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)));
-		/*
-		 *	Now send the Fib to the adapter
-		 */
-		status = aac_fib_send(ContainerRawIo,
-			  cmd_fibcontext, 
-			  fibsize, 
-			  FsaNormal, 
-			  0, 1, 
-			  (fib_callback) io_callback, 
-			  (void *) scsicmd);
-	} else if (dev->dac_support == 1) {
-		struct aac_read64 *readcmd;
-		readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext);
-		readcmd->command = cpu_to_le32(VM_CtHostRead64);
-		readcmd->cid = cpu_to_le16(cid);
-		readcmd->sector_count = cpu_to_le16(count);
-		readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
-		readcmd->pad   = 0;
-		readcmd->flags = 0; 
-
-		aac_build_sg64(scsicmd, &readcmd->sg);
-		fibsize = sizeof(struct aac_read64) + 
-			((le32_to_cpu(readcmd->sg.count) - 1) * 
-			 sizeof (struct sgentry64));
-		BUG_ON (fibsize > (dev->max_fib_size - 
-					sizeof(struct aac_fibhdr)));
-		/*
-		 *	Now send the Fib to the adapter
-		 */
-		status = aac_fib_send(ContainerCommand64,
-			  cmd_fibcontext, 
-			  fibsize, 
-			  FsaNormal, 
-			  0, 1, 
-			  (fib_callback) io_callback, 
-			  (void *) scsicmd);
-	} else {
-		struct aac_read *readcmd;
-		readcmd = (struct aac_read *) fib_data(cmd_fibcontext);
-		readcmd->command = cpu_to_le32(VM_CtBlockRead);
-		readcmd->cid = cpu_to_le32(cid);
-		readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
-		readcmd->count = cpu_to_le32(count * 512);
-
-		aac_build_sg(scsicmd, &readcmd->sg);
-		fibsize = sizeof(struct aac_read) + 
-			((le32_to_cpu(readcmd->sg.count) - 1) * 
-			 sizeof (struct sgentry));
-		BUG_ON (fibsize > (dev->max_fib_size -
-					sizeof(struct aac_fibhdr)));
-		/*
-		 *	Now send the Fib to the adapter
-		 */
-		status = aac_fib_send(ContainerCommand,
-			  cmd_fibcontext, 
-			  fibsize, 
-			  FsaNormal, 
-			  0, 1, 
-			  (fib_callback) io_callback, 
-			  (void *) scsicmd);
-	}
-
-	
+	status = aac_adapter_read(cmd_fibcontext, scsicmd, lba, count);
 
 	/*
 	 *	Check that the command queued to the controller
@@ -1187,7 +1411,6 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
 	u64 lba;
 	u32 count;
 	int status;
-	u16 fibsize;
 	struct aac_dev *dev;
 	struct fib * cmd_fibcontext;
 
@@ -1227,22 +1450,8 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
 	}
 	dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n",
 	  smp_processor_id(), (unsigned long long)lba, jiffies));
-	if ((!(dev->raw_io_interface) || !(dev->raw_io_64))
-	 && (lba & 0xffffffff00000000LL)) {
-		dprintk((KERN_DEBUG "aac_write: Illegal lba\n"));
-		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
-		set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
-			    HARDWARE_ERROR,
-			    SENCODE_INTERNAL_TARGET_FAILURE,
-			    ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
-			    0, 0);
-		memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
-		  (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer))
-		    ? sizeof(scsicmd->sense_buffer)
-		    : sizeof(dev->fsa_dev[cid].sense_data));
-		scsicmd->scsi_done(scsicmd);
+	if (aac_adapter_bounds(dev,scsicmd,lba))
 		return 0;
-	}
 	/*
 	 *	Allocate and initialize a Fib then setup a BlockWrite command
 	 */
@@ -1251,85 +1460,8 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
 		scsicmd->scsi_done(scsicmd);
 		return 0;
 	}
-	aac_fib_init(cmd_fibcontext);
 
-	if (dev->raw_io_interface) {
-		struct aac_raw_io *writecmd;
-		writecmd = (struct aac_raw_io *) fib_data(cmd_fibcontext);
-		writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
-		writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
-		writecmd->count = cpu_to_le32(count<<9);
-		writecmd->cid = cpu_to_le16(cid);
-		writecmd->flags = 0; 
-		writecmd->bpTotal = 0;
-		writecmd->bpComplete = 0;
-		
-		aac_build_sgraw(scsicmd, &writecmd->sg);
-		fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw));
-		BUG_ON(fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)));
-		/*
-		 *	Now send the Fib to the adapter
-		 */
-		status = aac_fib_send(ContainerRawIo,
-			  cmd_fibcontext, 
-			  fibsize, 
-			  FsaNormal, 
-			  0, 1, 
-			  (fib_callback) io_callback, 
-			  (void *) scsicmd);
-	} else if (dev->dac_support == 1) {
-		struct aac_write64 *writecmd;
-		writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext);
-		writecmd->command = cpu_to_le32(VM_CtHostWrite64);
-		writecmd->cid = cpu_to_le16(cid);
-		writecmd->sector_count = cpu_to_le16(count); 
-		writecmd->block = cpu_to_le32((u32)(lba&0xffffffff));
-		writecmd->pad	= 0;
-		writecmd->flags	= 0;
-
-		aac_build_sg64(scsicmd, &writecmd->sg);
-		fibsize = sizeof(struct aac_write64) + 
-			((le32_to_cpu(writecmd->sg.count) - 1) * 
-			 sizeof (struct sgentry64));
-		BUG_ON (fibsize > (dev->max_fib_size -
-					sizeof(struct aac_fibhdr)));
-		/*
-		 *	Now send the Fib to the adapter
-		 */
-		status = aac_fib_send(ContainerCommand64,
-			  cmd_fibcontext, 
-			  fibsize, 
-			  FsaNormal, 
-			  0, 1, 
-			  (fib_callback) io_callback, 
-			  (void *) scsicmd);
-	} else {
-		struct aac_write *writecmd;
-		writecmd = (struct aac_write *) fib_data(cmd_fibcontext);
-		writecmd->command = cpu_to_le32(VM_CtBlockWrite);
-		writecmd->cid = cpu_to_le32(cid);
-		writecmd->block = cpu_to_le32((u32)(lba&0xffffffff));
-		writecmd->count = cpu_to_le32(count * 512);
-		writecmd->sg.count = cpu_to_le32(1);
-		/* ->stable is not used - it did mean which type of write */
-
-		aac_build_sg(scsicmd, &writecmd->sg);
-		fibsize = sizeof(struct aac_write) + 
-			((le32_to_cpu(writecmd->sg.count) - 1) * 
-			 sizeof (struct sgentry));
-		BUG_ON (fibsize > (dev->max_fib_size -
-					sizeof(struct aac_fibhdr)));
-		/*
-		 *	Now send the Fib to the adapter
-		 */
-		status = aac_fib_send(ContainerCommand,
-			  cmd_fibcontext, 
-			  fibsize, 
-			  FsaNormal, 
-			  0, 1, 
-			  (fib_callback) io_callback, 
-			  (void *) scsicmd);
-	}
+	status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count);
 
 	/*
 	 *	Check that the command queued to the controller
@@ -2099,10 +2231,6 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
 	struct fib* cmd_fibcontext;
 	struct aac_dev* dev;
 	int status;
-	struct aac_srb *srbcmd;
-	u16 fibsize;
-	u32 flag;
-	u32 timeout;
 
 	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
 	if (scmd_id(scsicmd) >= dev->maximum_num_physicals ||
@@ -2112,88 +2240,14 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
 		return 0;
 	}
 
-	switch(scsicmd->sc_data_direction){
-	case DMA_TO_DEVICE:
-		flag = SRB_DataOut;
-		break;
-	case DMA_BIDIRECTIONAL:
-		flag = SRB_DataIn | SRB_DataOut;
-		break;
-	case DMA_FROM_DEVICE:
-		flag = SRB_DataIn;
-		break;
-	case DMA_NONE:
-	default:	/* shuts up some versions of gcc */
-		flag = SRB_NoDataXfer;
-		break;
-	}
-
-
 	/*
 	 *	Allocate and initialize a Fib then setup a BlockWrite command
 	 */
 	if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
 		return -1;
 	}
-	aac_fib_init(cmd_fibcontext);
-
-	srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext);
-	srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
-	srbcmd->channel  = cpu_to_le32(aac_logical_to_phys(scmd_channel(scsicmd)));
-	srbcmd->id   = cpu_to_le32(scmd_id(scsicmd));
-	srbcmd->lun      = cpu_to_le32(scsicmd->device->lun);
-	srbcmd->flags    = cpu_to_le32(flag);
-	timeout = scsicmd->timeout_per_command/HZ;
-	if(timeout == 0){
-		timeout = 1;
-	}
-	srbcmd->timeout  = cpu_to_le32(timeout);  // timeout in seconds
-	srbcmd->retry_limit = 0; /* Obsolete parameter */
-	srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len);
-	
-	if( dev->dac_support == 1 ) {
-		aac_build_sg64(scsicmd, (struct sgmap64*) &srbcmd->sg);
-		srbcmd->count = cpu_to_le32(scsicmd->request_bufflen);
-
-		memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
-		memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len);
-		/*
-		 *	Build Scatter/Gather list
-		 */
-		fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) +
-			((le32_to_cpu(srbcmd->sg.count) & 0xff) * 
-			 sizeof (struct sgentry64));
-		BUG_ON (fibsize > (dev->max_fib_size -
-					sizeof(struct aac_fibhdr)));
+	status = aac_adapter_scsi(cmd_fibcontext, scsicmd);
 
-		/*
-		 *	Now send the Fib to the adapter
-		 */
-		status = aac_fib_send(ScsiPortCommand64, cmd_fibcontext,
-				fibsize, FsaNormal, 0, 1,
-				  (fib_callback) aac_srb_callback, 
-				  (void *) scsicmd);
-	} else {
-		aac_build_sg(scsicmd, (struct sgmap*)&srbcmd->sg);
-		srbcmd->count = cpu_to_le32(scsicmd->request_bufflen);
-
-		memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
-		memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len);
-		/*
-		 *	Build Scatter/Gather list
-		 */
-		fibsize = sizeof (struct aac_srb) + 
-			(((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) * 
-			 sizeof (struct sgentry));
-		BUG_ON (fibsize > (dev->max_fib_size -
-					sizeof(struct aac_fibhdr)));
-
-		/*
-		 *	Now send the Fib to the adapter
-		 */
-		status = aac_fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1,
-				  (fib_callback) aac_srb_callback, (void *) scsicmd);
-	}
 	/*
 	 *	Check that the command queued to the controller
 	 */
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 4f8b4c53d435..39ecd0d22eb0 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -5,6 +5,7 @@
 #define _nblank(x) #x
 #define nblank(x) _nblank(x)[0]
 
+#include <linux/interrupt.h>
 
 /*------------------------------------------------------------------------------
  *              D E F I N E S
@@ -485,16 +486,28 @@ enum aac_log_level {
 
 struct aac_dev;
 struct fib;
+struct scsi_cmnd;
 
 struct adapter_ops
 {
+	/* Low level operations */
 	void (*adapter_interrupt)(struct aac_dev *dev);
 	void (*adapter_notify)(struct aac_dev *dev, u32 event);
 	void (*adapter_disable_int)(struct aac_dev *dev);
+	void (*adapter_enable_int)(struct aac_dev *dev);
 	int  (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
 	int  (*adapter_check_health)(struct aac_dev *dev);
-	int  (*adapter_send)(struct fib * fib);
+	/* Transport operations */
 	int  (*adapter_ioremap)(struct aac_dev * dev, u32 size);
+	irqreturn_t (*adapter_intr)(int irq, void *dev_id);
+	/* Packet operations */
+	int  (*adapter_deliver)(struct fib * fib);
+	int  (*adapter_bounds)(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba);
+	int  (*adapter_read)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count);
+	int  (*adapter_write)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count);
+	int  (*adapter_scsi)(struct fib * fib, struct scsi_cmnd * cmd);
+	/* Administrative operations */
+	int  (*adapter_comm)(struct aac_dev * dev, int comm);
 };
 
 /*
@@ -1018,7 +1031,9 @@ struct aac_dev
 	u8			nondasd_support; 
 	u8			dac_support;
 	u8			raid_scsi_mode;
-	u8			new_comm_interface;
+	u8			comm_interface;
+#	define AAC_COMM_PRODUCER 0
+#	define AAC_COMM_MESSAGE  1
 	/* macro side-effects BEWARE */
 #	define			raw_io_interface \
 	  init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4)
@@ -1036,18 +1051,36 @@ struct aac_dev
 #define aac_adapter_disable_int(dev) \
 	(dev)->a_ops.adapter_disable_int(dev)
 
+#define aac_adapter_enable_int(dev) \
+	(dev)->a_ops.adapter_enable_int(dev)
+
 #define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \
 	(dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4)
 
 #define aac_adapter_check_health(dev) \
 	(dev)->a_ops.adapter_check_health(dev)
 
-#define aac_adapter_send(fib) \
-	((fib)->dev)->a_ops.adapter_send(fib)
-
 #define aac_adapter_ioremap(dev, size) \
 	(dev)->a_ops.adapter_ioremap(dev, size)
 
+#define aac_adapter_deliver(fib) \
+	((fib)->dev)->a_ops.adapter_deliver(fib)
+
+#define aac_adapter_bounds(dev,cmd,lba) \
+	dev->a_ops.adapter_bounds(dev,cmd,lba)
+
+#define aac_adapter_read(fib,cmd,lba,count) \
+	((fib)->dev)->a_ops.adapter_read(fib,cmd,lba,count)
+
+#define aac_adapter_write(fib,cmd,lba,count) \
+	((fib)->dev)->a_ops.adapter_write(fib,cmd,lba,count)
+
+#define aac_adapter_scsi(fib,cmd) \
+	((fib)->dev)->a_ops.adapter_scsi(fib,cmd)
+
+#define aac_adapter_comm(dev,comm) \
+	(dev)->a_ops.adapter_comm(dev, comm)
+
 #define FIB_CONTEXT_FLAG_TIMED_OUT		(0x00000001)
 
 /*
@@ -1767,7 +1800,6 @@ static inline u32 cap_to_cyls(sector_t capacity, u32 divisor)
 	return (u32)capacity;
 }
 
-struct scsi_cmnd;
 /* SCp.phase values */
 #define AAC_OWNER_MIDLEVEL	0x101
 #define AAC_OWNER_LOWLEVEL	0x102
@@ -1794,7 +1826,9 @@ int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg);
 int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg);
 int aac_rx_init(struct aac_dev *dev);
 int aac_rkt_init(struct aac_dev *dev);
+int aac_nark_init(struct aac_dev *dev);
 int aac_sa_init(struct aac_dev *dev);
+int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify);
 unsigned int aac_response_normal(struct aac_queue * q);
 unsigned int aac_command_normal(struct aac_queue * q);
 unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index);
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 6d305b2f854e..df67ba686023 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -95,7 +95,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
 	init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES);
 
 	init->InitFlags = 0;
-	if (dev->new_comm_interface) {
+	if (dev->comm_interface == AAC_COMM_MESSAGE) {
 		init->InitFlags = cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED);
 		dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n"));
 	}
@@ -297,21 +297,23 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
 		- sizeof(struct aac_fibhdr)
 		- sizeof(struct aac_write) + sizeof(struct sgentry))
 			/ sizeof(struct sgentry);
-	dev->new_comm_interface = 0;
+	dev->comm_interface = AAC_COMM_PRODUCER;
 	dev->raw_io_64 = 0;
 	if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES,
 		0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) &&
 	 		(status[0] == 0x00000001)) {
 		if (status[1] & AAC_OPT_NEW_COMM_64)
 			dev->raw_io_64 = 1;
-		if (status[1] & AAC_OPT_NEW_COMM)
-			dev->new_comm_interface = dev->a_ops.adapter_send != 0;
-		if (dev->new_comm_interface && (status[2] > dev->base_size)) {
+		if (dev->a_ops.adapter_comm &&
+		    (status[1] & AAC_OPT_NEW_COMM))
+			dev->comm_interface = AAC_COMM_MESSAGE;
+		if ((dev->comm_interface == AAC_COMM_MESSAGE) &&
+		    (status[2] > dev->base_size)) {
 			aac_adapter_ioremap(dev, 0);
 			dev->base_size = status[2];
 			if (aac_adapter_ioremap(dev, status[2])) {
 				/* remap failed, go back ... */
-				dev->new_comm_interface = 0;
+				dev->comm_interface = AAC_COMM_PRODUCER;
 				if (aac_adapter_ioremap(dev, AAC_MIN_FOOTPRINT_SIZE)) {
 					printk(KERN_WARNING
 					  "aacraid: unable to map adapter.\n");
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 4893a6d06a33..1b97f60652ba 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -317,7 +317,7 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr
  *	success.
  */
 
-static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify)
+int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify)
 {
 	struct aac_entry * entry = NULL;
 	int map = 0;
@@ -387,7 +387,6 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
 {
 	struct aac_dev * dev = fibptr->dev;
 	struct hw_fib * hw_fib = fibptr->hw_fib;
-	struct aac_queue * q;
 	unsigned long flags = 0;
 	unsigned long qflags;
 
@@ -469,38 +468,10 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
 
 	if (!dev->queues)
 		return -EBUSY;
-	q = &dev->queues->queue[AdapNormCmdQueue];
 
 	if(wait)
 		spin_lock_irqsave(&fibptr->event_lock, flags);
-	spin_lock_irqsave(q->lock, qflags);
-	if (dev->new_comm_interface) {
-		unsigned long count = 10000000L; /* 50 seconds */
-		q->numpending++;
-		spin_unlock_irqrestore(q->lock, qflags);
-		while (aac_adapter_send(fibptr) != 0) {
-			if (--count == 0) {
-				if (wait)
-					spin_unlock_irqrestore(&fibptr->event_lock, flags);
-				spin_lock_irqsave(q->lock, qflags);
-				q->numpending--;
-				spin_unlock_irqrestore(q->lock, qflags);
-				return -ETIMEDOUT;
-			}
-			udelay(5);
-		}
-	} else {
-		u32 index;
-		unsigned long nointr = 0;
-		aac_queue_get( dev, &index, AdapNormCmdQueue, hw_fib, 1, fibptr, &nointr);
-
-		q->numpending++;
-		*(q->headers.producer) = cpu_to_le32(index + 1);
-		spin_unlock_irqrestore(q->lock, qflags);
-		dprintk((KERN_DEBUG "aac_fib_send: inserting a queue entry at index %d.\n",index));
-		if (!(nointr & aac_config.irq_mod))
-			aac_adapter_notify(dev, AdapNormCmdQueue);
-	}
+	aac_adapter_deliver(fibptr);
 
 	/*
 	 *	If the caller wanted us to wait for response wait now. 
@@ -520,6 +491,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
 			while (down_trylock(&fibptr->event_wait)) {
 				int blink;
 				if (--count == 0) {
+					struct aac_queue * q = &dev->queues->queue[AdapNormCmdQueue];
 					spin_lock_irqsave(q->lock, qflags);
 					q->numpending--;
 					spin_unlock_irqrestore(q->lock, qflags);
@@ -659,7 +631,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
 	unsigned long qflags;
 
 	if (hw_fib->header.XferState == 0) {
-		if (dev->new_comm_interface)
+		if (dev->comm_interface == AAC_COMM_MESSAGE)
 			kfree (hw_fib);
         	return 0;
 	}
@@ -667,7 +639,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
 	 *	If we plan to do anything check the structure type first.
 	 */ 
 	if ( hw_fib->header.StructType != FIB_MAGIC ) {
-		if (dev->new_comm_interface)
+		if (dev->comm_interface == AAC_COMM_MESSAGE)
 			kfree (hw_fib);
         	return -EINVAL;
 	}
@@ -679,7 +651,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
 	 *	send the completed cdb to the adapter.
 	 */
 	if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) {
-		if (dev->new_comm_interface) {
+		if (dev->comm_interface == AAC_COMM_MESSAGE) {
 			kfree (hw_fib);
 		} else {
 	       		u32 index;
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index d2cf875af59b..a9734e08fe28 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -157,6 +157,7 @@ static struct pci_device_id aac_pci_tbl[] = {
 	{ 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 58 }, /* Legend Catchall */
 	{ 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */
 	{ 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */
+	{ 0x9005, 0x0288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 61 }, /* Adaptec NEMER/ARK Catch All */
 	{ 0,}
 };
 MODULE_DEVICE_TABLE(pci, aac_pci_tbl);
@@ -230,7 +231,8 @@ static struct aac_driver_ident aac_drivers[] = {
 	{ aac_rx_init, "aacraid",  "DELL    ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Dell Catchall */
 	{ aac_rx_init, "aacraid",  "Legend  ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Legend Catchall */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec Catch All */
-	{ aac_rkt_init, "aacraid", "ADAPTEC ", "RAID            ", 2 } /* Adaptec Rocket Catch All */
+	{ aac_rkt_init, "aacraid", "ADAPTEC ", "RAID            ", 2 }, /* Adaptec Rocket Catch All */
+	{ aac_nark_init, "aacraid", "ADAPTEC ", "RAID            ", 2 } /* Adaptec NEMER/ARK Catch All */
 };
 
 /**
@@ -396,11 +398,15 @@ static int aac_slave_configure(struct scsi_device *sdev)
 		sdev->skip_ms_page_3f = 1;
 	}
 	if ((sdev->type == TYPE_DISK) &&
-			!expose_physicals &&
 			(sdev_channel(sdev) != CONTAINER_CHANNEL)) {
-		struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata;
-		if (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))
-			sdev->no_uld_attach = 1;
+		if (expose_physicals == 0)
+			return -ENXIO;
+		if (expose_physicals < 0) {
+			struct aac_dev *aac =
+				(struct aac_dev *)sdev->host->hostdata;
+			if (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))
+				sdev->no_uld_attach = 1;
+		}
 	}
 	if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
 			(sdev_channel(sdev) == CONTAINER_CHANNEL)) {
@@ -804,7 +810,6 @@ static struct scsi_host_template aac_driver_template = {
 	.emulated                       = 1,
 };
 
-
 static int __devinit aac_probe_one(struct pci_dev *pdev,
 		const struct pci_device_id *id)
 {
diff --git a/drivers/scsi/aacraid/nark.c b/drivers/scsi/aacraid/nark.c
new file mode 100644
index 000000000000..c76b611b6afb
--- /dev/null
+++ b/drivers/scsi/aacraid/nark.c
@@ -0,0 +1,87 @@
+/*
+ *	Adaptec AAC series RAID controller driver
+ *	(c) Copyright 2001 Red Hat Inc.	<alan@redhat.com>
+ *
+ * based on the old aacraid driver that is..
+ * Adaptec aacraid device driver for Linux.
+ *
+ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Module Name:
+ *  nark.c
+ *
+ * Abstract: Hardware Device Interface for NEMER/ARK
+ *
+ */
+
+#include <linux/pci.h>
+#include <linux/blkdev.h>
+
+#include <scsi/scsi_host.h>
+
+#include "aacraid.h"
+
+/**
+ *	aac_nark_ioremap
+ *	@size: mapping resize request
+ *
+ */
+static int aac_nark_ioremap(struct aac_dev * dev, u32 size)
+{
+	if (!size) {
+		iounmap(dev->regs.rx);
+		dev->regs.rx = NULL;
+		iounmap(dev->base);
+		dev->base = NULL;
+		return 0;
+	}
+	dev->scsi_host_ptr->base = pci_resource_start(dev->pdev, 2);
+	dev->regs.rx = ioremap((u64)pci_resource_start(dev->pdev, 0) |
+	  ((u64)pci_resource_start(dev->pdev, 1) << 32),
+	  sizeof(struct rx_registers) - sizeof(struct rx_inbound));
+	dev->base = NULL;
+	if (dev->regs.rx == NULL)
+		return -1;
+	dev->base = ioremap(dev->scsi_host_ptr->base, size);
+	if (dev->base == NULL) {
+		iounmap(dev->regs.rx);
+		dev->regs.rx = NULL;
+		return -1;
+	}
+	dev->IndexRegs = &((struct rx_registers __iomem *)dev->base)->IndexRegs;
+	return 0;
+}
+
+/**
+ *	aac_nark_init	-	initialize an NEMER/ARK Split Bar card
+ *	@dev: device to configure
+ *
+ */
+
+int aac_nark_init(struct aac_dev * dev)
+{
+	extern int _aac_rx_init(struct aac_dev *dev);
+	extern int aac_rx_select_comm(struct aac_dev *dev, int comm);
+
+	/*
+	 *	Fill in the function dispatch table.
+	 */
+	dev->a_ops.adapter_ioremap = aac_nark_ioremap;
+	dev->a_ops.adapter_comm = aac_rx_select_comm;
+
+	return _aac_rx_init(dev);
+}
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index 643f23b5ded8..d953c3fe998a 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -34,6 +34,40 @@
 
 #include "aacraid.h"
 
+#define AAC_NUM_IO_FIB_RKT      (246 - AAC_NUM_MGT_FIB)
+
+/**
+ *	aac_rkt_select_comm	-	Select communications method
+ *	@dev: Adapter
+ *	@comm: communications method
+ */
+
+static int aac_rkt_select_comm(struct aac_dev *dev, int comm)
+{
+	int retval;
+	extern int aac_rx_select_comm(struct aac_dev *dev, int comm);
+	retval = aac_rx_select_comm(dev, comm);
+	if (comm == AAC_COMM_MESSAGE) {
+		/*
+		 * FIB Setup has already been done, but we can minimize the
+		 * damage by at least ensuring the OS never issues more
+		 * commands than we can handle. The Rocket adapters currently
+		 * can only handle 246 commands and 8 AIFs at the same time,
+		 * and in fact do notify us accordingly if we negotiate the
+		 * FIB size. The problem that causes us to add this check is
+		 * to ensure that we do not overdo it with the adapter when a
+		 * hard coded FIB override is being utilized. This special
+		 * case warrants this half baked, but convenient, check here.
+		 */
+		if (dev->scsi_host_ptr->can_queue > AAC_NUM_IO_FIB_RKT) {
+			dev->init->MaxIoCommands =
+				cpu_to_le32(AAC_NUM_IO_FIB_RKT + AAC_NUM_MGT_FIB);
+			dev->scsi_host_ptr->can_queue = AAC_NUM_IO_FIB_RKT;
+		}
+	}
+	return retval;
+}
+
 /**
  *	aac_rkt_ioremap
  *	@size: mapping resize request
@@ -63,39 +97,13 @@ static int aac_rkt_ioremap(struct aac_dev * dev, u32 size)
 
 int aac_rkt_init(struct aac_dev *dev)
 {
-	int retval;
 	extern int _aac_rx_init(struct aac_dev *dev);
-	extern void aac_rx_start_adapter(struct aac_dev *dev);
 
 	/*
 	 *	Fill in the function dispatch table.
 	 */
 	dev->a_ops.adapter_ioremap = aac_rkt_ioremap;
+	dev->a_ops.adapter_comm = aac_rkt_select_comm;
 
-	retval = _aac_rx_init(dev);
-	if (retval)
-		return retval;
-	if (dev->new_comm_interface) {
-		/*
-		 * FIB Setup has already been done, but we can minimize the
-		 * damage by at least ensuring the OS never issues more
-		 * commands than we can handle. The Rocket adapters currently
-		 * can only handle 246 commands and 8 AIFs at the same time,
-		 * and in fact do notify us accordingly if we negotiate the
-		 * FIB size. The problem that causes us to add this check is
-		 * to ensure that we do not overdo it with the adapter when a
-		 * hard coded FIB override is being utilized. This special
-		 * case warrants this half baked, but convenient, check here.
-		 */
-		if (dev->scsi_host_ptr->can_queue > (246 - AAC_NUM_MGT_FIB)) {
-			dev->init->MaxIoCommands = cpu_to_le32(246);
-			dev->scsi_host_ptr->can_queue = 246 - AAC_NUM_MGT_FIB;
-		}
-	}
-	/*
-	 *	Tell the adapter that all is configured, and it can start
-	 *	accepting requests
-	 */
-	aac_rx_start_adapter(dev);
-	return 0;
+	return _aac_rx_init(dev);
 }
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index dcc8b0ea7a9d..c632d9354a26 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -46,60 +46,60 @@
 
 #include "aacraid.h"
 
-static irqreturn_t aac_rx_intr(int irq, void *dev_id)
+static irqreturn_t aac_rx_intr_producer(int irq, void *dev_id)
 {
 	struct aac_dev *dev = dev_id;
+	unsigned long bellbits;
+	u8 intstat = rx_readb(dev, MUnit.OISR);
 
-	dprintk((KERN_DEBUG "aac_rx_intr(%d,%p)\n", irq, dev_id));
-	if (dev->new_comm_interface) {
-		u32 Index = rx_readl(dev, MUnit.OutboundQueue);
-		if (Index == 0xFFFFFFFFL)
-			Index = rx_readl(dev, MUnit.OutboundQueue);
-		if (Index != 0xFFFFFFFFL) {
-			do {
-				if (aac_intr_normal(dev, Index)) {
-					rx_writel(dev, MUnit.OutboundQueue, Index);
-					rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady);
-				}
-				Index = rx_readl(dev, MUnit.OutboundQueue);
-			} while (Index != 0xFFFFFFFFL);
-			return IRQ_HANDLED;
+	/*
+	 *	Read mask and invert because drawbridge is reversed.
+	 *	This allows us to only service interrupts that have
+	 *	been enabled.
+	 *	Check to see if this is our interrupt.  If it isn't just return
+	 */
+	if (intstat & ~(dev->OIMR)) {
+		bellbits = rx_readl(dev, OutboundDoorbellReg);
+		if (bellbits & DoorBellPrintfReady) {
+			aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5]));
+			rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
+			rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
 		}
-	} else {
-		unsigned long bellbits;
-		u8 intstat;
-		intstat = rx_readb(dev, MUnit.OISR);
-		/*
-		 *	Read mask and invert because drawbridge is reversed.
-		 *	This allows us to only service interrupts that have 
-		 *	been enabled.
-		 *	Check to see if this is our interrupt.  If it isn't just return
-		 */
-		if (intstat & ~(dev->OIMR)) 
-		{
-			bellbits = rx_readl(dev, OutboundDoorbellReg);
-			if (bellbits & DoorBellPrintfReady) {
-				aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5]));
-				rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
-				rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
-			}
-			else if (bellbits & DoorBellAdapterNormCmdReady) {
-				rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
-				aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
-			}
-			else if (bellbits & DoorBellAdapterNormRespReady) {
-				rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
-				aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
-			}
-			else if (bellbits & DoorBellAdapterNormCmdNotFull) {
-				rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
-			}
-			else if (bellbits & DoorBellAdapterNormRespNotFull) {
-				rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
-				rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
-			}
-			return IRQ_HANDLED;
+		else if (bellbits & DoorBellAdapterNormCmdReady) {
+			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
+			aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
+		}
+		else if (bellbits & DoorBellAdapterNormRespReady) {
+			rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
+			aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
+		}
+		else if (bellbits & DoorBellAdapterNormCmdNotFull) {
+			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
 		}
+		else if (bellbits & DoorBellAdapterNormRespNotFull) {
+			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
+			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
+		}
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+static irqreturn_t aac_rx_intr_message(int irq, void *dev_id)
+{
+	struct aac_dev *dev = dev_id;
+	u32 Index = rx_readl(dev, MUnit.OutboundQueue);
+	if (Index == 0xFFFFFFFFL)
+		Index = rx_readl(dev, MUnit.OutboundQueue);
+	if (Index != 0xFFFFFFFFL) {
+		do {
+			if (aac_intr_normal(dev, Index)) {
+				rx_writel(dev, MUnit.OutboundQueue, Index);
+				rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady);
+			}
+			Index = rx_readl(dev, MUnit.OutboundQueue);
+		} while (Index != 0xFFFFFFFFL);
+		return IRQ_HANDLED;
 	}
 	return IRQ_NONE;
 }
@@ -115,6 +115,26 @@ static void aac_rx_disable_interrupt(struct aac_dev *dev)
 }
 
 /**
+ *	aac_rx_enable_interrupt_producer	-	Enable interrupts
+ *	@dev: Adapter
+ */
+
+static void aac_rx_enable_interrupt_producer(struct aac_dev *dev)
+{
+	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
+}
+
+/**
+ *	aac_rx_enable_interrupt_message	-	Enable interrupts
+ *	@dev: Adapter
+ */
+
+static void aac_rx_enable_interrupt_message(struct aac_dev *dev)
+{
+	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
+}
+
+/**
  *	rx_sync_cmd	-	send a command and wait
  *	@dev: Adapter
  *	@command: Command to execute
@@ -189,10 +209,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command,
 		/*
 		 *	Restore interrupt mask even though we timed out
 		 */
-		if (dev->new_comm_interface)
-			rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
-		else
-			rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
+		aac_adapter_enable_int(dev);
 		return -ETIMEDOUT;
 	}
 	/*
@@ -215,10 +232,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command,
 	/*
 	 *	Restore interrupt mask
 	 */
-	if (dev->new_comm_interface)
-		rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
-	else
-		rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
+	aac_adapter_enable_int(dev);
 	return 0;
 
 }
@@ -360,35 +374,72 @@ static int aac_rx_check_health(struct aac_dev *dev)
 }
 
 /**
- *	aac_rx_send
+ *	aac_rx_deliver_producer
  *	@fib: fib to issue
  *
  *	Will send a fib, returning 0 if successful.
  */
-static int aac_rx_send(struct fib * fib)
+static int aac_rx_deliver_producer(struct fib * fib)
 {
-	u64 addr = fib->hw_fib_pa;
 	struct aac_dev *dev = fib->dev;
-	volatile void __iomem *device = dev->regs.rx;
+	struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
+	unsigned long qflags;
 	u32 Index;
+	unsigned long nointr = 0;
 
-	dprintk((KERN_DEBUG "%p->aac_rx_send(%p->%llx)\n", dev, fib, addr));
-	Index = rx_readl(dev, MUnit.InboundQueue);
-	if (Index == 0xFFFFFFFFL)
+	spin_lock_irqsave(q->lock, qflags);
+	aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib, 1, fib, &nointr);
+
+	q->numpending++;
+	*(q->headers.producer) = cpu_to_le32(Index + 1);
+	spin_unlock_irqrestore(q->lock, qflags);
+	if (!(nointr & aac_config.irq_mod))
+		aac_adapter_notify(dev, AdapNormCmdQueue);
+
+	return 0;
+}
+
+/**
+ *	aac_rx_deliver_message
+ *	@fib: fib to issue
+ *
+ *	Will send a fib, returning 0 if successful.
+ */
+static int aac_rx_deliver_message(struct fib * fib)
+{
+	struct aac_dev *dev = fib->dev;
+	struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
+	unsigned long qflags;
+	u32 Index;
+	u64 addr;
+	volatile void __iomem *device;
+
+	unsigned long count = 10000000L; /* 50 seconds */
+	spin_lock_irqsave(q->lock, qflags);
+	q->numpending++;
+	spin_unlock_irqrestore(q->lock, qflags);
+	for(;;) {
 		Index = rx_readl(dev, MUnit.InboundQueue);
-	dprintk((KERN_DEBUG "Index = 0x%x\n", Index));
-	if (Index == 0xFFFFFFFFL)
-		return Index;
+		if (Index == 0xFFFFFFFFL)
+			Index = rx_readl(dev, MUnit.InboundQueue);
+		if (Index != 0xFFFFFFFFL)
+			break;
+		if (--count == 0) {
+			spin_lock_irqsave(q->lock, qflags);
+			q->numpending--;
+			spin_unlock_irqrestore(q->lock, qflags);
+			return -ETIMEDOUT;
+		}
+		udelay(5);
+	}
 	device = dev->base + Index;
-	dprintk((KERN_DEBUG "entry = %x %x %u\n", (u32)(addr & 0xffffffff),
-	  (u32)(addr >> 32), (u32)le16_to_cpu(fib->hw_fib->header.Size)));
+	addr = fib->hw_fib_pa;
 	writel((u32)(addr & 0xffffffff), device);
 	device += sizeof(u32);
 	writel((u32)(addr >> 32), device);
 	device += sizeof(u32);
 	writel(le16_to_cpu(fib->hw_fib->header.Size), device);
 	rx_writel(dev, MUnit.InboundQueue, Index);
-	dprintk((KERN_DEBUG "aac_rx_send - return 0\n"));
 	return 0;
 }
 
@@ -430,6 +481,31 @@ static int aac_rx_restart_adapter(struct aac_dev *dev)
 }
 
 /**
+ *	aac_rx_select_comm	-	Select communications method
+ *	@dev: Adapter
+ *	@comm: communications method
+ */
+
+int aac_rx_select_comm(struct aac_dev *dev, int comm)
+{
+	switch (comm) {
+	case AAC_COMM_PRODUCER:
+		dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt_producer;
+		dev->a_ops.adapter_intr = aac_rx_intr_producer;
+		dev->a_ops.adapter_deliver = aac_rx_deliver_producer;
+		break;
+	case AAC_COMM_MESSAGE:
+		dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt_message;
+		dev->a_ops.adapter_intr = aac_rx_intr_message;
+		dev->a_ops.adapter_deliver = aac_rx_deliver_message;
+		break;
+	default:
+		return 1;
+	}
+	return 0;
+}
+
+/**
  *	aac_rx_init	-	initialize an i960 based AAC card
  *	@dev: device to configure
  *
@@ -489,40 +565,42 @@ int _aac_rx_init(struct aac_dev *dev)
 		}
 		msleep(1);
 	}
-	if (request_irq(dev->scsi_host_ptr->irq, aac_rx_intr, IRQF_SHARED|IRQF_DISABLED, "aacraid", (void *)dev)<0)
-	{
-		printk(KERN_ERR "%s%d: Interrupt unavailable.\n", name, instance);
-		goto error_iounmap;
-	}
 	/*
-	 *	Fill in the function dispatch table.
+	 *	Fill in the common function dispatch table.
 	 */
 	dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter;
 	dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt;
 	dev->a_ops.adapter_notify = aac_rx_notify_adapter;
 	dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
 	dev->a_ops.adapter_check_health = aac_rx_check_health;
-	dev->a_ops.adapter_send = aac_rx_send;
 
 	/*
 	 *	First clear out all interrupts.  Then enable the one's that we
 	 *	can handle.
 	 */
-	rx_writeb(dev, MUnit.OIMR, 0xff);
+	aac_adapter_comm(dev, AAC_COMM_PRODUCER);
+	aac_adapter_disable_int(dev);
 	rx_writel(dev, MUnit.ODR, 0xffffffff);
-	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
+	aac_adapter_enable_int(dev);
 
 	if (aac_init_adapter(dev) == NULL)
-		goto error_irq;
-	if (dev->new_comm_interface)
-		rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
+		goto error_iounmap;
+	aac_adapter_comm(dev, dev->comm_interface);
+	if (request_irq(dev->scsi_host_ptr->irq, dev->a_ops.adapter_intr,
+			IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) {
+		printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
+			name, instance);
+		goto error_iounmap;
+	}
+	aac_adapter_enable_int(dev);
+	/*
+	 *	Tell the adapter that all is configured, and it can
+	 * start accepting requests
+	 */
+	aac_rx_start_adapter(dev);
 
 	return 0;
 
-error_irq:
-	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
-	free_irq(dev->scsi_host_ptr->irq, (void *)dev);
-
 error_iounmap:
 
 	return -1;
@@ -530,20 +608,11 @@ error_iounmap:
 
 int aac_rx_init(struct aac_dev *dev)
 {
-	int retval;
-
 	/*
 	 *	Fill in the function dispatch table.
 	 */
 	dev->a_ops.adapter_ioremap = aac_rx_ioremap;
+	dev->a_ops.adapter_comm = aac_rx_select_comm;
 
-	retval = _aac_rx_init(dev);
-	if (!retval) {
-		/*
-		 *	Tell the adapter that all is configured, and it can
-		 * start accepting requests
-		 */
-		aac_rx_start_adapter(dev);
-	}
-	return retval;
+	return _aac_rx_init(dev);
 }
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index 511b0a938fb1..8535db068c2f 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -92,6 +92,17 @@ static void aac_sa_disable_interrupt (struct aac_dev *dev)
 }
 
 /**
+ *	aac_sa_enable_interrupt	-	enable interrupt
+ *	@dev: Which adapter to enable.
+ */
+
+static void aac_sa_enable_interrupt (struct aac_dev *dev)
+{
+	sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 |
+				DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
+}
+
+/**
  *	aac_sa_notify_adapter		-	handle adapter notification
  *	@dev:	Adapter that notification is for
  *	@event:	Event to notidy
@@ -347,32 +358,36 @@ int aac_sa_init(struct aac_dev *dev)
 		msleep(1);
 	}
 
-	if (request_irq(dev->scsi_host_ptr->irq, aac_sa_intr, IRQF_SHARED|IRQF_DISABLED, "aacraid", (void *)dev ) < 0) {
-		printk(KERN_WARNING "%s%d: Interrupt unavailable.\n", name, instance);
-		goto error_iounmap;
-	}
-
 	/*
 	 *	Fill in the function dispatch table.
 	 */
 
 	dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter;
 	dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt;
+	dev->a_ops.adapter_enable_int = aac_sa_enable_interrupt;
 	dev->a_ops.adapter_notify = aac_sa_notify_adapter;
 	dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
 	dev->a_ops.adapter_check_health = aac_sa_check_health;
+	dev->a_ops.adapter_intr = aac_sa_intr;
 	dev->a_ops.adapter_ioremap = aac_sa_ioremap;
 
 	/*
 	 *	First clear out all interrupts.  Then enable the one's that 
 	 *	we can handle.
 	 */
-	sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
-	sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | 
-				DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
+	aac_adapter_disable_int(dev);
+	aac_adapter_enable_int(dev);
 
 	if(aac_init_adapter(dev) == NULL)
 		goto error_irq;
+	if (request_irq(dev->scsi_host_ptr->irq, dev->a_ops.adapter_intr,
+			IRQF_SHARED|IRQF_DISABLED,
+			"aacraid", (void *)dev ) < 0) {
+		printk(KERN_WARNING "%s%d: Interrupt unavailable.\n",
+			name, instance);
+		goto error_iounmap;
+	}
+	aac_adapter_enable_int(dev);
 
 	/*
 	 *	Tell the adapter that all is configure, and it can start 
@@ -382,7 +397,7 @@ int aac_sa_init(struct aac_dev *dev)
 	return 0;
 
 error_irq:
-	sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
+	aac_sa_disable_interrupt(dev);
 	free_irq(dev->scsi_host_ptr->irq, (void *)dev);
 
 error_iounmap:
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 306bec355e45..9b3303b64113 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -4403,7 +4403,7 @@ advansys_detect(struct scsi_host_template *tpnt)
                         ASC_DBG1(1,
                                 "advansys_detect: probing I/O port 0x%x...\n",
                             iop);
-                        if (check_region(iop, ASC_IOADR_GAP) != 0) {
+			if (!request_region(iop, ASC_IOADR_GAP, "advansys")){
                             printk(
 "AdvanSys SCSI: specified I/O Port 0x%X is busy\n", iop);
                             /* Don't try this I/O port twice. */
@@ -4413,6 +4413,7 @@ advansys_detect(struct scsi_host_template *tpnt)
                             printk(
 "AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", iop);
                             /* Don't try this I/O port twice. */
+			    release_region(iop, ASC_IOADR_GAP);
                             asc_ioport[ioport] = 0;
                             goto ioport_try_again;
                         } else {
@@ -4431,6 +4432,7 @@ advansys_detect(struct scsi_host_template *tpnt)
                                   * 'ioport' past this board.
                                   */
                                  ioport++;
+				 release_region(iop, ASC_IOADR_GAP);
                                  goto ioport_try_again;
                             }
                         }
@@ -9740,13 +9742,14 @@ AscSearchIOPortAddr11(
     }
     for (; i < ASC_IOADR_TABLE_MAX_IX; i++) {
         iop_base = _asc_def_iop_base[i];
-        if (check_region(iop_base, ASC_IOADR_GAP) != 0) {
+	if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")){
             ASC_DBG1(1,
                "AscSearchIOPortAddr11: check_region() failed I/O port 0x%x\n",
                      iop_base);
             continue;
         }
         ASC_DBG1(1, "AscSearchIOPortAddr11: probing I/O port 0x%x\n", iop_base);
+	release_region(iop_base, ASC_IOADR_GAP);
         if (AscFindSignature(iop_base)) {
             return (iop_base);
         }
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index 170a4344cbb2..27adbb294ac1 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -1337,9 +1337,6 @@ int	ahd_pci_test_register_access(struct ahd_softc *);
 /************************** SCB and SCB queue management **********************/
 void		ahd_qinfifo_requeue_tail(struct ahd_softc *ahd,
 					 struct scb *scb);
-int		ahd_match_scb(struct ahd_softc *ahd, struct scb *scb,
-			      int target, char channel, int lun,
-			      u_int tag, role_t role);
 
 /****************************** Initialization ********************************/
 struct ahd_softc	*ahd_alloc(void *platform_arg, char *name);
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 07a86a30f676..9ddc6e4a74b0 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -262,6 +262,9 @@ static void		ahd_update_coalescing_values(struct ahd_softc *ahd,
 						     u_int mincmds);
 static int		ahd_verify_vpd_cksum(struct vpd_config *vpd);
 static int		ahd_wait_seeprom(struct ahd_softc *ahd);
+static int		ahd_match_scb(struct ahd_softc *ahd, struct scb *scb,
+				      int target, char channel, int lun,
+				      u_int tag, role_t role);
 
 /******************************** Private Inlines *****************************/
 
@@ -7256,7 +7259,7 @@ ahd_busy_tcl(struct ahd_softc *ahd, u_int tcl, u_int scbid)
 }
 
 /************************** SCB and SCB queue management **********************/
-int
+static int
 ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, int target,
 	      char channel, int lun, u_int tag, role_t role)
 {
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 9bfcca5ede08..c7fe478f4813 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -1126,15 +1126,6 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
 	return 0;
 }
 
-uint64_t
-ahd_linux_get_memsize(void)
-{
-	struct sysinfo si;
-
-	si_meminfo(&si);
-	return ((uint64_t)si.totalram << PAGE_SHIFT);
-}
-
 /*
  * Place the SCSI bus into a known state by either resetting it,
  * or forcing transfer negotiations on the next command to any
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index 3a67fc578d78..147c83c456a5 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -496,8 +496,6 @@ ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
 int		ahd_linux_register_host(struct ahd_softc *,
 					struct scsi_host_template *);
 
-uint64_t	ahd_linux_get_memsize(void);
-
 /*************************** Pretty Printing **********************************/
 struct info_str {
 	char *buffer;
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
index 1a3ab6aa856b..c62ce41f2793 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
@@ -132,6 +132,7 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	struct		 ahd_pci_identity *entry;
 	char		*name;
 	int		 error;
+	struct device	*dev = &pdev->dev;
 
 	pci = pdev;
 	entry = ahd_find_pci_device(pci);
@@ -161,20 +162,18 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	pci_set_master(pdev);
 
 	if (sizeof(dma_addr_t) > 4) {
-		uint64_t   memsize;
-		const uint64_t mask_39bit = 0x7FFFFFFFFFULL;
+		const u64 required_mask = dma_get_required_mask(dev);
 
-		memsize = ahd_linux_get_memsize();
-
-		if (memsize >= 0x8000000000ULL
-	 	 && pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) {
+		if (required_mask > DMA_39BIT_MASK &&
+		    dma_set_mask(dev, DMA_64BIT_MASK) == 0)
 			ahd->flags |= AHD_64BIT_ADDRESSING;
-		} else if (memsize > 0x80000000
-			&& pci_set_dma_mask(pdev, mask_39bit) == 0) {
+		else if (required_mask > DMA_32BIT_MASK &&
+			 dma_set_mask(dev, DMA_39BIT_MASK) == 0)
 			ahd->flags |= AHD_39BIT_ADDRESSING;
-		}
+		else
+			dma_set_mask(dev, DMA_32BIT_MASK);
 	} else {
-		pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+		dma_set_mask(dev, DMA_32BIT_MASK);
 	}
 	ahd->dev_softc = pci;
 	error = ahd_pci_config(ahd, entry);
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index 2cf7bb3123f0..8d72bbae96ad 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -88,7 +88,7 @@ ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
 
 #define SUBID_9005_LEGACYCONN_FUNC(id) ((id) & 0x20)
 
-#define SUBID_9005_SEEPTYPE(id) ((id) & 0x0C0) >> 6)
+#define SUBID_9005_SEEPTYPE(id) (((id) & 0x0C0) >> 6)
 #define		SUBID_9005_SEEPTYPE_NONE	0x0
 #define		SUBID_9005_SEEPTYPE_4K		0x1
 
diff --git a/drivers/scsi/aic94xx/aic94xx_dev.c b/drivers/scsi/aic94xx/aic94xx_dev.c
index 6f8901b748f7..c520e5b41fb5 100644
--- a/drivers/scsi/aic94xx/aic94xx_dev.c
+++ b/drivers/scsi/aic94xx/aic94xx_dev.c
@@ -37,18 +37,14 @@
 
 static inline int asd_get_ddb(struct asd_ha_struct *asd_ha)
 {
-	unsigned long flags;
 	int ddb, i;
 
-	spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
 	ddb = FIND_FREE_DDB(asd_ha);
 	if (ddb >= asd_ha->hw_prof.max_ddbs) {
 		ddb = -ENOMEM;
-		spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
 		goto out;
 	}
 	SET_DDB(ddb, asd_ha);
-	spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
 
 	for (i = 0; i < sizeof(struct asd_ddb_ssp_smp_target_port); i+= 4)
 		asd_ddbsite_write_dword(asd_ha, ddb, i, 0);
@@ -77,14 +73,10 @@ out:
 
 static inline void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb)
 {
-	unsigned long flags;
-
 	if (!ddb || ddb >= 0xFFFF)
 		return;
 	asd_ddbsite_write_byte(asd_ha, ddb, DDB_TYPE, DDB_TYPE_UNUSED);
-	spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
 	CLEAR_DDB(ddb, asd_ha);
-	spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
 }
 
 static inline void asd_set_ddb_type(struct domain_device *dev)
@@ -320,8 +312,11 @@ out:
 
 int asd_dev_found(struct domain_device *dev)
 {
+	unsigned long flags;
 	int res = 0;
+	struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
 
+	spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
 	switch (dev->dev_type) {
 	case SATA_PM:
 		res = asd_init_sata_pm_ddb(dev);
@@ -335,14 +330,18 @@ int asd_dev_found(struct domain_device *dev)
 		else
 			res = asd_init_initiator_ddb(dev);
 	}
+	spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
+
 	return res;
 }
 
 void asd_dev_gone(struct domain_device *dev)
 {
 	int ddb, sister_ddb;
+	unsigned long flags;
 	struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
 
+	spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
 	ddb = (int) (unsigned long) dev->lldd_dev;
 	sister_ddb = asd_ddbsite_read_word(asd_ha, ddb, SISTER_DDB);
 
@@ -350,4 +349,5 @@ void asd_dev_gone(struct domain_device *dev)
 		asd_free_ddb(asd_ha, sister_ddb);
 	asd_free_ddb(asd_ha, ddb);
 	dev->lldd_dev = NULL;
+	spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
 }
diff --git a/drivers/scsi/aic94xx/aic94xx_dump.c b/drivers/scsi/aic94xx/aic94xx_dump.c
index e6ade5996d95..6bd8e3059d27 100644
--- a/drivers/scsi/aic94xx/aic94xx_dump.c
+++ b/drivers/scsi/aic94xx/aic94xx_dump.c
@@ -556,7 +556,7 @@ static void asd_dump_lseq_state(struct asd_ha_struct *asd_ha, int lseq)
 	PRINT_LMIP_word(asd_ha, lseq, Q_TGTXFR_TAIL);
 	PRINT_LMIP_byte(asd_ha, lseq, LINK_NUMBER);
 	PRINT_LMIP_byte(asd_ha, lseq, SCRATCH_FLAGS);
-	PRINT_LMIP_qword(asd_ha, lseq, CONNECTION_STATE);
+	PRINT_LMIP_dword(asd_ha, lseq, CONNECTION_STATE);
 	PRINT_LMIP_word(asd_ha, lseq, CONCTL);
 	PRINT_LMIP_byte(asd_ha, lseq, CONSTAT);
 	PRINT_LMIP_byte(asd_ha, lseq, CONNECTION_MODES);
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index fbc82b00a418..bc7744e35ad0 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -38,7 +38,7 @@
 #include "aic94xx_seq.h"
 
 /* The format is "version.release.patchlevel" */
-#define ASD_DRIVER_VERSION "1.0.2"
+#define ASD_DRIVER_VERSION "1.0.3"
 
 static int use_msi = 0;
 module_param_named(use_msi, use_msi, int, S_IRUGO);
@@ -57,6 +57,8 @@ MODULE_PARM_DESC(collector, "\n"
 char sas_addr_str[2*SAS_ADDR_SIZE + 1] = "";
 
 static struct scsi_transport_template *aic94xx_transport_template;
+static int asd_scan_finished(struct Scsi_Host *, unsigned long);
+static void asd_scan_start(struct Scsi_Host *);
 
 static struct scsi_host_template aic94xx_sht = {
 	.module			= THIS_MODULE,
@@ -66,6 +68,8 @@ static struct scsi_host_template aic94xx_sht = {
 	.target_alloc		= sas_target_alloc,
 	.slave_configure	= sas_slave_configure,
 	.slave_destroy		= sas_slave_destroy,
+	.scan_finished		= asd_scan_finished,
+	.scan_start		= asd_scan_start,
 	.change_queue_depth	= sas_change_queue_depth,
 	.change_queue_type	= sas_change_queue_type,
 	.bios_param		= sas_bios_param,
@@ -75,6 +79,8 @@ static struct scsi_host_template aic94xx_sht = {
 	.sg_tablesize		= SG_ALL,
 	.max_sectors		= SCSI_DEFAULT_MAX_SECTORS,
 	.use_clustering		= ENABLE_CLUSTERING,
+	.eh_device_reset_handler	= sas_eh_device_reset_handler,
+	.eh_bus_reset_handler	= sas_eh_bus_reset_handler,
 };
 
 static int __devinit asd_map_memio(struct asd_ha_struct *asd_ha)
@@ -234,7 +240,7 @@ static int __devinit asd_common_setup(struct asd_ha_struct *asd_ha)
 	}
 	/* Provide some sane default values. */
 	asd_ha->hw_prof.max_scbs = 512;
-	asd_ha->hw_prof.max_ddbs = 128;
+	asd_ha->hw_prof.max_ddbs = ASD_MAX_DDBS;
 	asd_ha->hw_prof.num_phys = ASD_MAX_PHYS;
 	/* All phys are enabled, by default. */
 	asd_ha->hw_prof.enabled_phys = 0xFF;
@@ -526,6 +532,7 @@ static int asd_register_sas_ha(struct asd_ha_struct *asd_ha)
 	asd_ha->sas_ha.num_phys= ASD_MAX_PHYS;
 
 	asd_ha->sas_ha.lldd_queue_size = asd_ha->seq.can_queue;
+	asd_ha->sas_ha.lldd_max_execute_num = lldd_max_execute_num;
 
 	return sas_register_ha(&asd_ha->sas_ha);
 }
@@ -671,21 +678,10 @@ static int __devinit asd_pci_probe(struct pci_dev *dev,
 	if (err)
 		goto Err_reg_sas;
 
-	err = asd_enable_phys(asd_ha, asd_ha->hw_prof.enabled_phys);
-	if (err) {
-		asd_printk("coudln't enable phys, err:%d\n", err);
-		goto Err_en_phys;
-	}
-	ASD_DPRINTK("enabled phys\n");
-	/* give the phy enabling interrupt event time to come in (1s
-	 * is empirically about all it takes) */
-	ssleep(1);
-	/* Wait for discovery to finish */
-	scsi_flush_work(asd_ha->sas_ha.core.shost);
+	scsi_scan_host(shost);
 
 	return 0;
-Err_en_phys:
-	asd_unregister_sas_ha(asd_ha);
+
 Err_reg_sas:
 	asd_remove_dev_attrs(asd_ha);
 Err_dev_attrs:
@@ -778,6 +774,28 @@ static void __devexit asd_pci_remove(struct pci_dev *dev)
 	return;
 }
 
+static void asd_scan_start(struct Scsi_Host *shost)
+{
+	struct asd_ha_struct *asd_ha;
+	int err;
+
+	asd_ha = SHOST_TO_SAS_HA(shost)->lldd_ha;
+	err = asd_enable_phys(asd_ha, asd_ha->hw_prof.enabled_phys);
+	if (err)
+		asd_printk("Couldn't enable phys, err:%d\n", err);
+}
+
+static int asd_scan_finished(struct Scsi_Host *shost, unsigned long time)
+{
+	/* give the phy enabling interrupt event time to come in (1s
+	 * is empirically about all it takes) */
+	if (time < HZ)
+		return 0;
+	/* Wait for discovery to finish */
+	scsi_flush_work(shost);
+	return 1;
+}
+
 static ssize_t asd_version_show(struct device_driver *driver, char *buf)
 {
 	return snprintf(buf, PAGE_SIZE, "%s\n", ASD_DRIVER_VERSION);
@@ -885,6 +903,7 @@ static void __exit aic94xx_exit(void)
 	asd_remove_driver_attrs(&aic94xx_pci_driver.driver);
 	pci_unregister_driver(&aic94xx_pci_driver);
 	sas_release_transport(aic94xx_transport_template);
+	asd_release_firmware();
 	asd_destroy_global_caches();
 	asd_printk("%s version %s unloaded\n", ASD_DRIVER_DESCRIPTION,
 		   ASD_DRIVER_VERSION);
diff --git a/drivers/scsi/aic94xx/aic94xx_reg_def.h b/drivers/scsi/aic94xx/aic94xx_reg_def.h
index a11f4e6d8bd9..a43e8cdf4ee4 100644
--- a/drivers/scsi/aic94xx/aic94xx_reg_def.h
+++ b/drivers/scsi/aic94xx/aic94xx_reg_def.h
@@ -2226,9 +2226,10 @@
 #define LmSEQ_SAS_RESET_MODE(LinkNum)		(LmSCRATCH(LinkNum) + 0x0074)
 #define LmSEQ_LINK_RESET_RETRY_COUNT(LinkNum)	(LmSCRATCH(LinkNum) + 0x0075)
 #define LmSEQ_NUM_LINK_RESET_RETRIES(LinkNum)	(LmSCRATCH(LinkNum) + 0x0076)
-#define LmSEQ_OOB_INT_ENABLES(LinkNum)		(LmSCRATCH(LinkNum) + 0x007A)
+#define LmSEQ_OOB_INT_ENABLES(LinkNum)		(LmSCRATCH(LinkNum) + 0x0078)
+#define LmSEQ_NOTIFY_TIMER_DOWN_COUNT(LinkNum)	(LmSCRATCH(LinkNum) + 0x007A)
 #define LmSEQ_NOTIFY_TIMER_TIMEOUT(LinkNum)	(LmSCRATCH(LinkNum) + 0x007C)
-#define LmSEQ_NOTIFY_TIMER_DOWN_COUNT(LinkNum)	(LmSCRATCH(LinkNum) + 0x007E)
+#define LmSEQ_NOTIFY_TIMER_INITIAL_COUNT(LinkNum) (LmSCRATCH(LinkNum) + 0x007E)
 
 /* Mode dependent scratch page 1, mode 0 and mode 1 */
 #define LmSEQ_SG_LIST_PTR_ADDR0(LinkNum)        (LmSCRATCH(LinkNum) + 0x0020)
diff --git a/drivers/scsi/aic94xx/aic94xx_sas.h b/drivers/scsi/aic94xx/aic94xx_sas.h
index 9050e93bfd5e..fa7c5290257d 100644
--- a/drivers/scsi/aic94xx/aic94xx_sas.h
+++ b/drivers/scsi/aic94xx/aic94xx_sas.h
@@ -34,6 +34,7 @@
  * domain that this sequencer can maintain low-level connections for
  * us.  They are be 64 bytes.
  */
+#define ASD_MAX_DDBS	128
 
 struct asd_ddb_ssp_smp_target_port {
 	u8     conn_type;	  /* byte 0 */
diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c
index 75ed6b0569d1..8f43ff772f23 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -413,40 +413,6 @@ void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id)
 	}
 }
 
-/* hard reset a phy later */
-static void do_phy_reset_later(struct work_struct *work)
-{
-	struct sas_phy *sas_phy =
-		container_of(work, struct sas_phy, reset_work);
-	int error;
-
-	ASD_DPRINTK("%s: About to hard reset phy %d\n", __FUNCTION__,
-		    sas_phy->identify.phy_identifier);
-	/* Reset device port */
-	error = sas_phy_reset(sas_phy, 1);
-	if (error)
-		ASD_DPRINTK("%s: Hard reset of phy %d failed (%d).\n",
-			    __FUNCTION__, sas_phy->identify.phy_identifier, error);
-}
-
-static void phy_reset_later(struct sas_phy *sas_phy, struct Scsi_Host *shost)
-{
-	INIT_WORK(&sas_phy->reset_work, do_phy_reset_later);
-	queue_work(shost->work_q, &sas_phy->reset_work);
-}
-
-/* start up the ABORT TASK tmf... */
-static void task_kill_later(struct asd_ascb *ascb)
-{
-	struct asd_ha_struct *asd_ha = ascb->ha;
-	struct sas_ha_struct *sas_ha = &asd_ha->sas_ha;
-	struct Scsi_Host *shost = sas_ha->core.shost;
-	struct sas_task *task = ascb->uldd_task;
-
-	INIT_WORK(&task->abort_work, sas_task_abort);
-	queue_work(shost->work_q, &task->abort_work);
-}
-
 static void escb_tasklet_complete(struct asd_ascb *ascb,
 				  struct done_list_struct *dl)
 {
@@ -479,26 +445,55 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
 	case REQ_TASK_ABORT: {
 		struct asd_ascb *a, *b;
 		u16 tc_abort;
+		struct domain_device *failed_dev = NULL;
+
+		ASD_DPRINTK("%s: REQ_TASK_ABORT, reason=0x%X\n",
+			    __FUNCTION__, dl->status_block[3]);
 
+		/*
+		 * Find the task that caused the abort and abort it first.
+		 * The sequencer won't put anything on the done list until
+		 * that happens.
+		 */
 		tc_abort = *((u16*)(&dl->status_block[1]));
 		tc_abort = le16_to_cpu(tc_abort);
 
-		ASD_DPRINTK("%s: REQ_TASK_ABORT, reason=0x%X\n",
-			    __FUNCTION__, dl->status_block[3]);
+		list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) {
+			struct sas_task *task = ascb->uldd_task;
 
-		/* Find the pending task and abort it. */
-		list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list)
-			if (a->tc_index == tc_abort) {
-				task_kill_later(a);
+			if (task && a->tc_index == tc_abort) {
+				failed_dev = task->dev;
+				sas_task_abort(task);
 				break;
 			}
+		}
+
+		if (!failed_dev) {
+			ASD_DPRINTK("%s: Can't find task (tc=%d) to abort!\n",
+				    __FUNCTION__, tc_abort);
+			goto out;
+		}
+
+		/*
+		 * Now abort everything else for that device (hba?) so
+		 * that the EH will wake up and do something.
+		 */
+		list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) {
+			struct sas_task *task = ascb->uldd_task;
+
+			if (task &&
+			    task->dev == failed_dev &&
+			    a->tc_index != tc_abort)
+				sas_task_abort(task);
+		}
+
 		goto out;
 	}
 	case REQ_DEVICE_RESET: {
-		struct Scsi_Host *shost = sas_ha->core.shost;
-		struct sas_phy *dev_phy;
 		struct asd_ascb *a;
 		u16 conn_handle;
+		unsigned long flags;
+		struct sas_task *last_dev_task = NULL;
 
 		conn_handle = *((u16*)(&dl->status_block[1]));
 		conn_handle = le16_to_cpu(conn_handle);
@@ -506,32 +501,47 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
 		ASD_DPRINTK("%s: REQ_DEVICE_RESET, reason=0x%X\n", __FUNCTION__,
 			    dl->status_block[3]);
 
-		/* Kill all pending tasks and reset the device */
-		dev_phy = NULL;
+		/* Find the last pending task for the device... */
 		list_for_each_entry(a, &asd_ha->seq.pend_q, list) {
-			struct sas_task *task;
-			struct domain_device *dev;
 			u16 x;
+			struct domain_device *dev;
+			struct sas_task *task = a->uldd_task;
 
-			task = a->uldd_task;
 			if (!task)
 				continue;
 			dev = task->dev;
 
 			x = (unsigned long)dev->lldd_dev;
-			if (x == conn_handle) {
-				dev_phy = dev->port->phy;
-				task_kill_later(a);
-			}
+			if (x == conn_handle)
+				last_dev_task = task;
 		}
 
-		/* Reset device port */
-		if (!dev_phy) {
-			ASD_DPRINTK("%s: No pending commands; can't reset.\n",
-				    __FUNCTION__);
+		if (!last_dev_task) {
+			ASD_DPRINTK("%s: Device reset for idle device %d?\n",
+				    __FUNCTION__, conn_handle);
 			goto out;
 		}
-		phy_reset_later(dev_phy, shost);
+
+		/* ...and set the reset flag */
+		spin_lock_irqsave(&last_dev_task->task_state_lock, flags);
+		last_dev_task->task_state_flags |= SAS_TASK_NEED_DEV_RESET;
+		spin_unlock_irqrestore(&last_dev_task->task_state_lock, flags);
+
+		/* Kill all pending tasks for the device */
+		list_for_each_entry(a, &asd_ha->seq.pend_q, list) {
+			u16 x;
+			struct domain_device *dev;
+			struct sas_task *task = a->uldd_task;
+
+			if (!task)
+				continue;
+			dev = task->dev;
+
+			x = (unsigned long)dev->lldd_dev;
+			if (x == conn_handle)
+				sas_task_abort(task);
+		}
+
 		goto out;
 	}
 	case SIGNAL_NCQ_ERROR:
diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c
index e5a0ec37e954..5b0932f61473 100644
--- a/drivers/scsi/aic94xx/aic94xx_sds.c
+++ b/drivers/scsi/aic94xx/aic94xx_sds.c
@@ -427,7 +427,7 @@ struct asd_manuf_sec {
 
 struct asd_manuf_phy_desc {
 	u8    state;         /* low 4 bits */
-#define MS_PHY_STATE_ENABLEABLE 0
+#define MS_PHY_STATE_ENABLED    0
 #define MS_PHY_STATE_REPORTED   1
 #define MS_PHY_STATE_HIDDEN     2
 	u8    phy_id;
@@ -756,11 +756,11 @@ static void *asd_find_ll_by_id(void * const start, const u8 id0, const u8 id1)
  *
  * HIDDEN phys do not count in the total count.  REPORTED phys cannot
  * be enabled but are reported and counted towards the total.
- * ENEBLEABLE phys are enabled by default and count towards the total.
+ * ENABLED phys are enabled by default and count towards the total.
  * The absolute total phy number is ASD_MAX_PHYS.  hw_prof->num_phys
  * merely specifies the number of phys the host adapter decided to
  * report.  E.g., it is possible for phys 0, 1 and 2 to be HIDDEN,
- * phys 3, 4 and 5 to be REPORTED and phys 6 and 7 to be ENEBLEABLE.
+ * phys 3, 4 and 5 to be REPORTED and phys 6 and 7 to be ENABLED.
  * In this case ASD_MAX_PHYS is 8, hw_prof->num_phys is 5, and only 2
  * are actually enabled (enabled by default, max number of phys
  * enableable in this case).
@@ -816,8 +816,8 @@ static int asd_ms_get_phy_params(struct asd_ha_struct *asd_ha,
 			asd_ha->hw_prof.enabled_phys &= ~(1 << i);
 			rep_phys++;
 			continue;
-		case MS_PHY_STATE_ENABLEABLE:
-			ASD_DPRINTK("ms: phy%d: ENEBLEABLE\n", i);
+		case MS_PHY_STATE_ENABLED:
+			ASD_DPRINTK("ms: phy%d: ENABLED\n", i);
 			asd_ha->hw_prof.enabled_phys |= (1 << i);
 			en_phys++;
 			break;
diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c
index 845112539d05..eae7a247bece 100644
--- a/drivers/scsi/aic94xx/aic94xx_seq.c
+++ b/drivers/scsi/aic94xx/aic94xx_seq.c
@@ -810,6 +810,8 @@ static void asd_init_lseq_mdp(struct asd_ha_struct *asd_ha,  int lseq)
 	/* No delay for the first NOTIFY to be sent to the attached target. */
 	asd_write_reg_word(asd_ha, LmSEQ_NOTIFY_TIMER_DOWN_COUNT(lseq),
 			   ASD_NOTIFY_DOWN_COUNT);
+	asd_write_reg_word(asd_ha, LmSEQ_NOTIFY_TIMER_INITIAL_COUNT(lseq),
+			   ASD_NOTIFY_DOWN_COUNT);
 
 	/* LSEQ Mode dependent, mode 0 and 1, page 1 setup. */
 	for (i = 0; i < 2; i++)	{
@@ -907,6 +909,16 @@ static void asd_init_scb_sites(struct asd_ha_struct *asd_ha)
 		for (i = 0; i < ASD_SCB_SIZE; i += 4)
 			asd_scbsite_write_dword(asd_ha, site_no, i, 0);
 
+		/* Initialize SCB Site Opcode field to invalid. */
+		asd_scbsite_write_byte(asd_ha, site_no,
+				       offsetof(struct scb_header, opcode),
+				       0xFF);
+
+		/* Initialize SCB Site Flags field to mean a response
+		 * frame has been received.  This means inadvertent
+		 * frames received to be dropped. */
+		asd_scbsite_write_byte(asd_ha, site_no, 0x49, 0x01);
+
 		/* Workaround needed by SEQ to fix a SATA issue is to exclude
 		 * certain SCB sites from the free list. */
 		if (!SCB_SITE_VALID(site_no))
@@ -922,16 +934,6 @@ static void asd_init_scb_sites(struct asd_ha_struct *asd_ha)
 		/* Q_NEXT field of the last SCB is invalidated. */
 		asd_scbsite_write_word(asd_ha, site_no, 0, first_scb_site_no);
 
-		/* Initialize SCB Site Opcode field to invalid. */
-		asd_scbsite_write_byte(asd_ha, site_no,
-				       offsetof(struct scb_header, opcode),
-				       0xFF);
-
-		/* Initialize SCB Site Flags field to mean a response
-		 * frame has been received.  This means inadvertent
-		 * frames received to be dropped. */
-		asd_scbsite_write_byte(asd_ha, site_no, 0x49, 0x01);
-
 		first_scb_site_no = site_no;
 		max_scbs++;
 	}
@@ -1173,6 +1175,16 @@ static void asd_init_ddb_0(struct asd_ha_struct *asd_ha)
 	set_bit(0, asd_ha->hw_prof.ddb_bitmap);
 }
 
+static void asd_seq_init_ddb_sites(struct asd_ha_struct *asd_ha)
+{
+	unsigned int i;
+	unsigned int ddb_site;
+
+	for (ddb_site = 0 ; ddb_site < ASD_MAX_DDBS; ddb_site++)
+		for (i = 0; i < sizeof(struct asd_ddb_ssp_smp_target_port); i+= 4)
+			asd_ddbsite_write_dword(asd_ha, ddb_site, i, 0);
+}
+
 /**
  * asd_seq_setup_seqs -- setup and initialize central and link sequencers
  * @asd_ha: pointer to host adapter structure
@@ -1182,6 +1194,9 @@ static void asd_seq_setup_seqs(struct asd_ha_struct *asd_ha)
 	int 		lseq;
 	u8		lseq_mask;
 
+	/* Initialize DDB sites */
+	asd_seq_init_ddb_sites(asd_ha);
+
 	/* Initialize SCB sites. Done first to compute some values which
 	 * the rest of the init code depends on. */
 	asd_init_scb_sites(asd_ha);
@@ -1232,6 +1247,13 @@ static int asd_seq_start_lseq(struct asd_ha_struct *asd_ha, int lseq)
 	return asd_seq_unpause_lseq(asd_ha, lseq);
 }
 
+int asd_release_firmware(void)
+{
+	if (sequencer_fw)
+		release_firmware(sequencer_fw);
+	return 0;
+}
+
 static int asd_request_firmware(struct asd_ha_struct *asd_ha)
 {
 	int err, i;
@@ -1375,7 +1397,9 @@ void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
 	u8  phy_is_up;
 	u8  mask;
 	int i, err;
+	unsigned long flags;
 
+	spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
 	for_each_phy(phy_mask, mask, i)
 		asd_ddbsite_write_byte(asd_ha, 0,
 				       offsetof(struct asd_ddb_seq_shared,
@@ -1395,6 +1419,7 @@ void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
 			break;
 		}
 	}
+	spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
 
 	if (err)
 		asd_printk("couldn't update DDB 0:error:%d\n", err);
diff --git a/drivers/scsi/aic94xx/aic94xx_seq.h b/drivers/scsi/aic94xx/aic94xx_seq.h
index 9e715e5496af..9437ff0ae3a4 100644
--- a/drivers/scsi/aic94xx/aic94xx_seq.h
+++ b/drivers/scsi/aic94xx/aic94xx_seq.h
@@ -63,6 +63,7 @@ int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask);
 int asd_unpause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask);
 int asd_init_seqs(struct asd_ha_struct *asd_ha);
 int asd_start_seqs(struct asd_ha_struct *asd_ha);
+int asd_release_firmware(void);
 
 void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy);
 #endif
diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c
index d202ed5a6709..e2ad5bed9403 100644
--- a/drivers/scsi/aic94xx/aic94xx_task.c
+++ b/drivers/scsi/aic94xx/aic94xx_task.c
@@ -349,6 +349,7 @@ Again:
 
 	spin_lock_irqsave(&task->task_state_lock, flags);
 	task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
+	task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
 	task->task_state_flags |= SAS_TASK_STATE_DONE;
 	if (unlikely((task->task_state_flags & SAS_TASK_STATE_ABORTED))) {
 		spin_unlock_irqrestore(&task->task_state_lock, flags);
@@ -557,6 +558,7 @@ int asd_execute_task(struct sas_task *task, const int num,
 	struct sas_task *t = task;
 	struct asd_ascb *ascb = NULL, *a;
 	struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha;
+	unsigned long flags;
 
 	res = asd_can_queue(asd_ha, num);
 	if (res)
@@ -599,6 +601,10 @@ int asd_execute_task(struct sas_task *task, const int num,
 		}
 		if (res)
 			goto out_err_unmap;
+
+		spin_lock_irqsave(&t->task_state_lock, flags);
+		t->task_state_flags |= SAS_TASK_AT_INITIATOR;
+		spin_unlock_irqrestore(&t->task_state_lock, flags);
 	}
 	list_del_init(&alist);
 
@@ -617,6 +623,9 @@ out_err_unmap:
 			if (a == b)
 				break;
 			t = a->uldd_task;
+			spin_lock_irqsave(&t->task_state_lock, flags);
+			t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+			spin_unlock_irqrestore(&t->task_state_lock, flags);
 			switch (t->task_proto) {
 			case SATA_PROTO:
 			case SAS_PROTO_STP:
diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c
index 61234384503b..9a14a6d97275 100644
--- a/drivers/scsi/aic94xx/aic94xx_tmf.c
+++ b/drivers/scsi/aic94xx/aic94xx_tmf.c
@@ -566,9 +566,7 @@ static int asd_initiate_ssp_tmf(struct domain_device *dev, u8 *lun,
 		res = TMF_RESP_FUNC_ESUPP;
 		break;
 	default:
-		ASD_DPRINTK("%s: converting result 0x%x to TMF_RESP_FUNC_FAILED\n",
-			    __FUNCTION__, res);
-		res = TMF_RESP_FUNC_FAILED;
+		/* Allow TMF response codes to propagate upwards */
 		break;
 	}
 out_err:
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 821386c7b576..95045e33710d 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -595,10 +595,8 @@ static int ipr_save_pcix_cmd_reg(struct ipr_ioa_cfg *ioa_cfg)
 {
 	int pcix_cmd_reg = pci_find_capability(ioa_cfg->pdev, PCI_CAP_ID_PCIX);
 
-	if (pcix_cmd_reg == 0) {
-		dev_err(&ioa_cfg->pdev->dev, "Failed to save PCI-X command register\n");
-		return -EIO;
-	}
+	if (pcix_cmd_reg == 0)
+		return 0;
 
 	if (pci_read_config_word(ioa_cfg->pdev, pcix_cmd_reg + PCI_X_CMD,
 				 &ioa_cfg->saved_pcix_cmd_reg) != PCIBIOS_SUCCESSFUL) {
@@ -627,10 +625,6 @@ static int ipr_set_pcix_cmd_reg(struct ipr_ioa_cfg *ioa_cfg)
 			dev_err(&ioa_cfg->pdev->dev, "Failed to setup PCI-X command register\n");
 			return -EIO;
 		}
-	} else {
-		dev_err(&ioa_cfg->pdev->dev,
-			"Failed to setup PCI-X command register\n");
-		return -EIO;
 	}
 
 	return 0;
@@ -6314,7 +6308,6 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
 	int rc;
 
 	ENTER;
-	pci_unblock_user_cfg_access(ioa_cfg->pdev);
 	rc = pci_restore_state(ioa_cfg->pdev);
 
 	if (rc != PCIBIOS_SUCCESSFUL) {
@@ -6355,6 +6348,24 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
 }
 
 /**
+ * ipr_reset_bist_done - BIST has completed on the adapter.
+ * @ipr_cmd:	ipr command struct
+ *
+ * Description: Unblock config space and resume the reset process.
+ *
+ * Return value:
+ * 	IPR_RC_JOB_CONTINUE
+ **/
+static int ipr_reset_bist_done(struct ipr_cmnd *ipr_cmd)
+{
+	ENTER;
+	pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev);
+	ipr_cmd->job_step = ipr_reset_restore_cfg_space;
+	LEAVE;
+	return IPR_RC_JOB_CONTINUE;
+}
+
+/**
  * ipr_reset_start_bist - Run BIST on the adapter.
  * @ipr_cmd:	ipr command struct
  *
@@ -6376,7 +6387,7 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
 		ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR);
 		rc = IPR_RC_JOB_CONTINUE;
 	} else {
-		ipr_cmd->job_step = ipr_reset_restore_cfg_space;
+		ipr_cmd->job_step = ipr_reset_bist_done;
 		ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT);
 		rc = IPR_RC_JOB_RETURN;
 	}
@@ -7166,9 +7177,6 @@ ipr_get_chip_cfg(const struct pci_device_id *dev_id)
 {
 	int i;
 
-	if (dev_id->driver_data)
-		return (const struct ipr_chip_cfg_t *)dev_id->driver_data;
-
 	for (i = 0; i < ARRAY_SIZE(ipr_chip); i++)
 		if (ipr_chip[i].vendor == dev_id->vendor &&
 		    ipr_chip[i].device == dev_id->device)
@@ -7517,62 +7525,43 @@ static void ipr_shutdown(struct pci_dev *pdev)
 
 static struct pci_device_id ipr_pci_table[] __devinitdata = {
 	{ PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5702,
-		0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5702, 0, 0, 0 },
 	{ PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5703,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5703, 0, 0, 0 },
 	{ PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573D,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573D, 0, 0, 0 },
 	{ PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573E,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573E, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571B,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571B, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572E,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572E, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571A,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571A, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575B,
-		0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575B, 0, 0, 0 },
 	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
-	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 },
 	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
-	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 },
 	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
-	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
-	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
-	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
-	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
-	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7,
-	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780,
-		0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, 0, 0, 0 },
 	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571E,
-		0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571E, 0, 0, 0 },
 	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F,
-		0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, 0, 0, 0 },
 	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F,
-		0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, 0, 0, 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, ipr_pci_table);
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 9f62a1d4d511..88f285de97bb 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -37,8 +37,8 @@
 /*
  * Literals
  */
-#define IPR_DRIVER_VERSION "2.3.0"
-#define IPR_DRIVER_DATE "(November 8, 2006)"
+#define IPR_DRIVER_VERSION "2.3.1"
+#define IPR_DRIVER_DATE "(January 23, 2007)"
 
 /*
  * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
index f0871c3ac3d9..2aae1b081fcf 100644
--- a/drivers/scsi/lasi700.c
+++ b/drivers/scsi/lasi700.c
@@ -123,6 +123,7 @@ lasi700_probe(struct parisc_device *dev)
 		hostdata->force_le_on_be = 0;
 		hostdata->chip710 = 1;
 		hostdata->dmode_extra = DMODE_FC2;
+		hostdata->burst_length = 8;
 	}
 
 	host = NCR_700_detect(&lasi700_template, hostdata, &dev->dev);
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index fb7df7b75811..a65598b1e536 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -548,7 +548,7 @@ int sas_discover_sata(struct domain_device *dev)
 
 	res = sas_notify_lldd_dev_found(dev);
 	if (res)
-		return res;
+		goto out_err2;
 
 	switch (dev->dev_type) {
 	case SATA_DEV:
@@ -560,11 +560,23 @@ int sas_discover_sata(struct domain_device *dev)
 	default:
 		break;
 	}
+	if (res)
+		goto out_err;
 
 	sas_notify_lldd_dev_gone(dev);
-	if (!res) {
-		sas_notify_lldd_dev_found(dev);
-	}
+	res = sas_notify_lldd_dev_found(dev);
+	if (res)
+		goto out_err2;
+
+	res = sas_rphy_add(dev->rphy);
+	if (res)
+		goto out_err;
+
+	return res;
+
+out_err:
+	sas_notify_lldd_dev_gone(dev);
+out_err2:
 	return res;
 }
 
@@ -580,21 +592,17 @@ int sas_discover_end_dev(struct domain_device *dev)
 
 	res = sas_notify_lldd_dev_found(dev);
 	if (res)
-		return res;
+		goto out_err2;
 
 	res = sas_rphy_add(dev->rphy);
 	if (res)
 		goto out_err;
 
-	/* do this to get the end device port attributes which will have
-	 * been scanned in sas_rphy_add */
-	sas_notify_lldd_dev_gone(dev);
-	sas_notify_lldd_dev_found(dev);
-
 	return 0;
 
 out_err:
 	sas_notify_lldd_dev_gone(dev);
+out_err2:
 	return res;
 }
 
@@ -649,6 +657,7 @@ void sas_unregister_domain_devices(struct asd_sas_port *port)
  */
 static void sas_discover_domain(struct work_struct *work)
 {
+	struct domain_device *dev;
 	int error = 0;
 	struct sas_discovery_event *ev =
 		container_of(work, struct sas_discovery_event, work);
@@ -658,35 +667,42 @@ static void sas_discover_domain(struct work_struct *work)
 			&port->disc.pending);
 
 	if (port->port_dev)
-		return ;
-	else {
-		error = sas_get_port_device(port);
-		if (error)
-			return;
-	}
+		return;
+
+	error = sas_get_port_device(port);
+	if (error)
+		return;
+	dev = port->port_dev;
 
 	SAS_DPRINTK("DOING DISCOVERY on port %d, pid:%d\n", port->id,
 		    current->pid);
 
-	switch (port->port_dev->dev_type) {
+	switch (dev->dev_type) {
 	case SAS_END_DEV:
-		error = sas_discover_end_dev(port->port_dev);
+		error = sas_discover_end_dev(dev);
 		break;
 	case EDGE_DEV:
 	case FANOUT_DEV:
-		error = sas_discover_root_expander(port->port_dev);
+		error = sas_discover_root_expander(dev);
 		break;
 	case SATA_DEV:
 	case SATA_PM:
-		error = sas_discover_sata(port->port_dev);
+		error = sas_discover_sata(dev);
 		break;
 	default:
-		SAS_DPRINTK("unhandled device %d\n", port->port_dev->dev_type);
+		SAS_DPRINTK("unhandled device %d\n", dev->dev_type);
 		break;
 	}
 
 	if (error) {
-		kfree(port->port_dev); /* not kobject_register-ed yet */
+		sas_rphy_free(dev->rphy);
+		dev->rphy = NULL;
+
+		spin_lock(&port->dev_list_lock);
+		list_del_init(&dev->dev_list_node);
+		spin_unlock(&port->dev_list_lock);
+
+		kfree(dev); /* not kobject_register-ed yet */
 		port->port_dev = NULL;
 	}
 
@@ -726,7 +742,7 @@ int sas_discover_event(struct asd_sas_port *port, enum discover_event ev)
 	BUG_ON(ev >= DISC_NUM_EVENTS);
 
 	sas_queue_event(ev, &disc->disc_event_lock, &disc->pending,
-			&disc->disc_work[ev].work, port->ha->core.shost);
+			&disc->disc_work[ev].work, port->ha);
 
 	return 0;
 }
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index d83392ee6823..9db30fb5caf2 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -31,7 +31,7 @@ static void notify_ha_event(struct sas_ha_struct *sas_ha, enum ha_event event)
 	BUG_ON(event >= HA_NUM_EVENTS);
 
 	sas_queue_event(event, &sas_ha->event_lock, &sas_ha->pending,
-			&sas_ha->ha_events[event].work, sas_ha->core.shost);
+			&sas_ha->ha_events[event].work, sas_ha);
 }
 
 static void notify_port_event(struct asd_sas_phy *phy, enum port_event event)
@@ -41,7 +41,7 @@ static void notify_port_event(struct asd_sas_phy *phy, enum port_event event)
 	BUG_ON(event >= PORT_NUM_EVENTS);
 
 	sas_queue_event(event, &ha->event_lock, &phy->port_events_pending,
-			&phy->port_events[event].work, ha->core.shost);
+			&phy->port_events[event].work, ha);
 }
 
 static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
@@ -51,7 +51,7 @@ static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
 	BUG_ON(event >= PHY_NUM_EVENTS);
 
 	sas_queue_event(event, &ha->event_lock, &phy->phy_events_pending,
-			&phy->phy_events[event].work, ha->core.shost);
+			&phy->phy_events[event].work, ha);
 }
 
 int sas_init_events(struct sas_ha_struct *sas_ha)
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index d31e6fa466f7..dc70c180e115 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -667,8 +667,9 @@ static struct domain_device *sas_ex_discover_end_dev(
 	return child;
 
  out_list_del:
+	sas_rphy_free(child->rphy);
+	child->rphy = NULL;
 	list_del(&child->dev_list_node);
-	sas_rphy_free(rphy);
  out_free:
 	sas_port_delete(phy->port);
  out_err:
@@ -677,6 +678,29 @@ static struct domain_device *sas_ex_discover_end_dev(
 	return NULL;
 }
 
+/* See if this phy is part of a wide port */
+static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id)
+{
+	struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id];
+	int i;
+
+	for (i = 0; i < parent->ex_dev.num_phys; i++) {
+		struct ex_phy *ephy = &parent->ex_dev.ex_phy[i];
+
+		if (ephy == phy)
+			continue;
+
+		if (!memcmp(phy->attached_sas_addr, ephy->attached_sas_addr,
+			    SAS_ADDR_SIZE) && ephy->port) {
+			sas_port_add_phy(ephy->port, phy->phy);
+			phy->phy_state = PHY_DEVICE_DISCOVERED;
+			return 0;
+		}
+	}
+
+	return -ENODEV;
+}
+
 static struct domain_device *sas_ex_discover_expander(
 	struct domain_device *parent, int phy_id)
 {
@@ -809,6 +833,13 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
 		return res;
 	}
 
+	res = sas_ex_join_wide_port(dev, phy_id);
+	if (!res) {
+		SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n",
+			    phy_id, SAS_ADDR(ex_phy->attached_sas_addr));
+		return res;
+	}
+
 	switch (ex_phy->attached_dev_type) {
 	case SAS_END_DEV:
 		child = sas_ex_discover_end_dev(dev, phy_id);
@@ -1431,14 +1462,23 @@ int sas_discover_root_expander(struct domain_device *dev)
 	int res;
 	struct sas_expander_device *ex = rphy_to_expander_device(dev->rphy);
 
-	sas_rphy_add(dev->rphy);
+	res = sas_rphy_add(dev->rphy);
+	if (res)
+		goto out_err;
 
 	ex->level = dev->port->disc.max_level; /* 0 */
 	res = sas_discover_expander(dev);
-	if (!res)
-		sas_ex_bfs_disc(dev->port);
+	if (res)
+		goto out_err2;
+
+	sas_ex_bfs_disc(dev->port);
 
 	return res;
+
+out_err2:
+	sas_rphy_remove(dev->rphy);
+out_err:
+	return res;
 }
 
 /* ---------- Domain revalidation ---------- */
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 2f0c07fc3f48..965698c8b7bf 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -87,6 +87,9 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
 	else if (sas_ha->lldd_queue_size == -1)
 		sas_ha->lldd_queue_size = 128; /* Sanity */
 
+	sas_ha->state = SAS_HA_REGISTERED;
+	spin_lock_init(&sas_ha->state_lock);
+
 	error = sas_register_phys(sas_ha);
 	if (error) {
 		printk(KERN_NOTICE "couldn't register sas phys:%d\n", error);
@@ -127,12 +130,22 @@ Undo_phys:
 
 int sas_unregister_ha(struct sas_ha_struct *sas_ha)
 {
+	unsigned long flags;
+
+	/* Set the state to unregistered to avoid further
+	 * events to be queued */
+	spin_lock_irqsave(&sas_ha->state_lock, flags);
+	sas_ha->state = SAS_HA_UNREGISTERED;
+	spin_unlock_irqrestore(&sas_ha->state_lock, flags);
+	scsi_flush_work(sas_ha->core.shost);
+
+	sas_unregister_ports(sas_ha);
+
 	if (sas_ha->lldd_max_execute_num > 1) {
 		sas_shutdown_queue(sas_ha);
+		sas_ha->lldd_max_execute_num = 1;
 	}
 
-	sas_unregister_ports(sas_ha);
-
 	return 0;
 }
 
@@ -146,6 +159,36 @@ static int sas_get_linkerrors(struct sas_phy *phy)
 	return sas_smp_get_phy_events(phy);
 }
 
+int sas_phy_enable(struct sas_phy *phy, int enable)
+{
+	int ret;
+	enum phy_func command;
+
+	if (enable)
+		command = PHY_FUNC_LINK_RESET;
+	else
+		command = PHY_FUNC_DISABLE;
+
+	if (scsi_is_sas_phy_local(phy)) {
+		struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+		struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
+		struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
+		struct sas_internal *i =
+			to_sas_internal(sas_ha->core.shost->transportt);
+
+		if (!enable) {
+			sas_phy_disconnected(asd_phy);
+			sas_ha->notify_phy_event(asd_phy, PHYE_LOSS_OF_SIGNAL);
+		}
+		ret = i->dft->lldd_control_phy(asd_phy, command, NULL);
+	} else {
+		struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent);
+		struct domain_device *ddev = sas_find_dev_by_rphy(rphy);
+		ret = sas_smp_phy_control(ddev, phy->number, command, NULL);
+	}
+	return ret;
+}
+
 int sas_phy_reset(struct sas_phy *phy, int hard_reset)
 {
 	int ret;
@@ -172,8 +215,8 @@ int sas_phy_reset(struct sas_phy *phy, int hard_reset)
 	return ret;
 }
 
-static int sas_set_phy_speed(struct sas_phy *phy,
-			     struct sas_phy_linkrates *rates)
+int sas_set_phy_speed(struct sas_phy *phy,
+		      struct sas_phy_linkrates *rates)
 {
 	int ret;
 
@@ -212,6 +255,7 @@ static int sas_set_phy_speed(struct sas_phy *phy,
 }
 
 static struct sas_function_template sft = {
+	.phy_enable = sas_phy_enable,
 	.phy_reset = sas_phy_reset,
 	.set_phy_speed = sas_set_phy_speed,
 	.get_linkerrors = sas_get_linkerrors,
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index 137d7e496b6d..a78638df2018 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -80,7 +80,7 @@ void sas_hae_reset(struct work_struct *work);
 static inline void sas_queue_event(int event, spinlock_t *lock,
 				   unsigned long *pending,
 				   struct work_struct *work,
-				   struct Scsi_Host *shost)
+				   struct sas_ha_struct *sas_ha)
 {
 	unsigned long flags;
 
@@ -91,7 +91,12 @@ static inline void sas_queue_event(int event, spinlock_t *lock,
 	}
 	__set_bit(event, pending);
 	spin_unlock_irqrestore(lock, flags);
-	scsi_queue_work(shost, work);
+
+	spin_lock_irqsave(&sas_ha->state_lock, flags);
+	if (sas_ha->state != SAS_HA_UNREGISTERED) {
+		scsi_queue_work(sas_ha->core.shost, work);
+	}
+	spin_unlock_irqrestore(&sas_ha->state_lock, flags);
 }
 
 static inline void sas_begin_event(int event, spinlock_t *lock,
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c
index 971c37ceecb4..e1e2d085c920 100644
--- a/drivers/scsi/libsas/sas_port.c
+++ b/drivers/scsi/libsas/sas_port.c
@@ -42,10 +42,11 @@ static void sas_form_port(struct asd_sas_phy *phy)
 	struct asd_sas_port *port = phy->port;
 	struct sas_internal *si =
 		to_sas_internal(sas_ha->core.shost->transportt);
+	unsigned long flags;
 
 	if (port) {
 		if (memcmp(port->attached_sas_addr, phy->attached_sas_addr,
-			   SAS_ADDR_SIZE) == 0)
+			   SAS_ADDR_SIZE) != 0)
 			sas_deform_port(phy);
 		else {
 			SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n",
@@ -56,7 +57,7 @@ static void sas_form_port(struct asd_sas_phy *phy)
 	}
 
 	/* find a port */
-	spin_lock(&sas_ha->phy_port_lock);
+	spin_lock_irqsave(&sas_ha->phy_port_lock, flags);
 	for (i = 0; i < sas_ha->num_phys; i++) {
 		port = sas_ha->sas_port[i];
 		spin_lock(&port->phy_list_lock);
@@ -78,7 +79,7 @@ static void sas_form_port(struct asd_sas_phy *phy)
 	if (i >= sas_ha->num_phys) {
 		printk(KERN_NOTICE "%s: couldn't find a free port, bug?\n",
 		       __FUNCTION__);
-		spin_unlock(&sas_ha->phy_port_lock);
+		spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags);
 		return;
 	}
 
@@ -105,7 +106,7 @@ static void sas_form_port(struct asd_sas_phy *phy)
 	} else
 		port->linkrate = max(port->linkrate, phy->linkrate);
 	spin_unlock(&port->phy_list_lock);
-	spin_unlock(&sas_ha->phy_port_lock);
+	spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags);
 
 	if (!port->port) {
 		port->port = sas_port_alloc(phy->phy->dev.parent, port->id);
@@ -137,6 +138,7 @@ void sas_deform_port(struct asd_sas_phy *phy)
 	struct asd_sas_port *port = phy->port;
 	struct sas_internal *si =
 		to_sas_internal(sas_ha->core.shost->transportt);
+	unsigned long flags;
 
 	if (!port)
 		return;		  /* done by a phy event */
@@ -155,7 +157,7 @@ void sas_deform_port(struct asd_sas_phy *phy)
 	if (si->dft->lldd_port_deformed)
 		si->dft->lldd_port_deformed(phy);
 
-	spin_lock(&sas_ha->phy_port_lock);
+	spin_lock_irqsave(&sas_ha->phy_port_lock, flags);
 	spin_lock(&port->phy_list_lock);
 
 	list_del_init(&phy->port_phy_el);
@@ -174,7 +176,7 @@ void sas_deform_port(struct asd_sas_phy *phy)
 		port->phy_mask = 0;
 	}
 	spin_unlock(&port->phy_list_lock);
-	spin_unlock(&sas_ha->phy_port_lock);
+	spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags);
 
 	return;
 }
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 22672d54aa27..897a5e2c55e4 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -34,6 +34,7 @@
 #include <scsi/scsi_transport_sas.h>
 #include "../scsi_sas_internal.h"
 #include "../scsi_transport_api.h"
+#include "../scsi_priv.h"
 
 #include <linux/err.h>
 #include <linux/blkdev.h>
@@ -130,7 +131,7 @@ static enum task_attribute sas_scsi_get_task_attr(struct scsi_cmnd *cmd)
 	if (cmd->request && blk_rq_tagged(cmd->request)) {
 		if (cmd->device->ordered_tags &&
 		    (cmd->request->cmd_flags & REQ_HARDBARRIER))
-			ta = TASK_ATTR_HOQ;
+			ta = TASK_ATTR_ORDERED;
 	}
 	return ta;
 }
@@ -281,6 +282,7 @@ enum task_disposition {
 	TASK_IS_ABORTED,
 	TASK_IS_AT_LU,
 	TASK_IS_NOT_AT_LU,
+	TASK_ABORT_FAILED,
 };
 
 static enum task_disposition sas_scsi_find_task(struct sas_task *task)
@@ -310,15 +312,6 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task)
 		spin_unlock_irqrestore(&core->task_queue_lock, flags);
 	}
 
-	spin_lock_irqsave(&task->task_state_lock, flags);
-	if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) {
-		spin_unlock_irqrestore(&task->task_state_lock, flags);
-		SAS_DPRINTK("%s: task 0x%p already aborted\n",
-			    __FUNCTION__, task);
-		return TASK_IS_ABORTED;
-	}
-	spin_unlock_irqrestore(&task->task_state_lock, flags);
-
 	for (i = 0; i < 5; i++) {
 		SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task);
 		res = si->dft->lldd_abort_task(task);
@@ -340,15 +333,21 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task)
 			SAS_DPRINTK("%s: querying task 0x%p\n",
 				    __FUNCTION__, task);
 			res = si->dft->lldd_query_task(task);
-			if (res == TMF_RESP_FUNC_SUCC) {
+			switch (res) {
+			case TMF_RESP_FUNC_SUCC:
 				SAS_DPRINTK("%s: task 0x%p at LU\n",
 					    __FUNCTION__, task);
 				return TASK_IS_AT_LU;
-			} else if (res == TMF_RESP_FUNC_COMPLETE) {
+			case TMF_RESP_FUNC_COMPLETE:
 				SAS_DPRINTK("%s: task 0x%p not at LU\n",
 					    __FUNCTION__, task);
 				return TASK_IS_NOT_AT_LU;
-			}
+			case TMF_RESP_FUNC_FAILED:
+                                SAS_DPRINTK("%s: task 0x%p failed to abort\n",
+                                                __FUNCTION__, task);
+                                return TASK_ABORT_FAILED;
+                        }
+
 		}
 	}
 	return res;
@@ -398,35 +397,113 @@ static int sas_recover_I_T(struct domain_device *dev)
 	return res;
 }
 
-void sas_scsi_recover_host(struct Scsi_Host *shost)
+/* Find the sas_phy that's attached to this device */
+struct sas_phy *find_local_sas_phy(struct domain_device *dev)
+{
+	struct domain_device *pdev = dev->parent;
+	struct ex_phy *exphy = NULL;
+	int i;
+
+	/* Directly attached device */
+	if (!pdev)
+		return dev->port->phy;
+
+	/* Otherwise look in the expander */
+	for (i = 0; i < pdev->ex_dev.num_phys; i++)
+		if (!memcmp(dev->sas_addr,
+			    pdev->ex_dev.ex_phy[i].attached_sas_addr,
+			    SAS_ADDR_SIZE)) {
+			exphy = &pdev->ex_dev.ex_phy[i];
+			break;
+		}
+
+	BUG_ON(!exphy);
+	return exphy->phy;
+}
+
+/* Attempt to send a LUN reset message to a device */
+int sas_eh_device_reset_handler(struct scsi_cmnd *cmd)
+{
+	struct domain_device *dev = cmd_to_domain_dev(cmd);
+	struct sas_internal *i =
+		to_sas_internal(dev->port->ha->core.shost->transportt);
+	struct scsi_lun lun;
+	int res;
+
+	int_to_scsilun(cmd->device->lun, &lun);
+
+	if (!i->dft->lldd_lu_reset)
+		return FAILED;
+
+	res = i->dft->lldd_lu_reset(dev, lun.scsi_lun);
+	if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE)
+		return SUCCESS;
+
+	return FAILED;
+}
+
+/* Attempt to send a phy (bus) reset */
+int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd)
+{
+	struct domain_device *dev = cmd_to_domain_dev(cmd);
+	struct sas_phy *phy = find_local_sas_phy(dev);
+	int res;
+
+	res = sas_phy_reset(phy, 1);
+	if (res)
+		SAS_DPRINTK("Bus reset of %s failed 0x%x\n",
+			    phy->dev.kobj.k_name,
+			    res);
+	if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE)
+		return SUCCESS;
+
+	return FAILED;
+}
+
+/* Try to reset a device */
+static int try_to_reset_cmd_device(struct Scsi_Host *shost,
+				   struct scsi_cmnd *cmd)
+{
+	int res;
+
+	if (!shost->hostt->eh_device_reset_handler)
+		goto try_bus_reset;
+
+	res = shost->hostt->eh_device_reset_handler(cmd);
+	if (res == SUCCESS)
+		return res;
+
+try_bus_reset:
+	if (shost->hostt->eh_bus_reset_handler)
+		return shost->hostt->eh_bus_reset_handler(cmd);
+
+	return FAILED;
+}
+
+static int sas_eh_handle_sas_errors(struct Scsi_Host *shost,
+				    struct list_head *work_q,
+				    struct list_head *done_q)
 {
-	struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
-	unsigned long flags;
-	LIST_HEAD(error_q);
 	struct scsi_cmnd *cmd, *n;
 	enum task_disposition res = TASK_IS_DONE;
-	int tmf_resp;
+	int tmf_resp, need_reset;
 	struct sas_internal *i = to_sas_internal(shost->transportt);
+	unsigned long flags;
+	struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
 
-	spin_lock_irqsave(shost->host_lock, flags);
-	list_splice_init(&shost->eh_cmd_q, &error_q);
-	spin_unlock_irqrestore(shost->host_lock, flags);
-
-	SAS_DPRINTK("Enter %s\n", __FUNCTION__);
-
-	/* All tasks on this list were marked SAS_TASK_STATE_ABORTED
-	 * by sas_scsi_timed_out() callback.
-	 */
 Again:
-	SAS_DPRINTK("going over list...\n");
-	list_for_each_entry_safe(cmd, n, &error_q, eh_entry) {
+	list_for_each_entry_safe(cmd, n, work_q, eh_entry) {
 		struct sas_task *task = TO_SAS_TASK(cmd);
-		list_del_init(&cmd->eh_entry);
 
-		if (!task) {
-			SAS_DPRINTK("%s: taskless cmd?!\n", __FUNCTION__);
+		if (!task)
 			continue;
-		}
+
+		list_del_init(&cmd->eh_entry);
+
+		spin_lock_irqsave(&task->task_state_lock, flags);
+		need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET;
+		spin_unlock_irqrestore(&task->task_state_lock, flags);
+
 		SAS_DPRINTK("trying to find task 0x%p\n", task);
 		res = sas_scsi_find_task(task);
 
@@ -437,11 +514,15 @@ Again:
 			SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__,
 				    task);
 			task->task_done(task);
+			if (need_reset)
+				try_to_reset_cmd_device(shost, cmd);
 			continue;
 		case TASK_IS_ABORTED:
 			SAS_DPRINTK("%s: task 0x%p is aborted\n",
 				    __FUNCTION__, task);
 			task->task_done(task);
+			if (need_reset)
+				try_to_reset_cmd_device(shost, cmd);
 			continue;
 		case TASK_IS_AT_LU:
 			SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task);
@@ -452,11 +533,14 @@ Again:
 					    SAS_ADDR(task->dev),
 					    cmd->device->lun);
 				task->task_done(task);
-				sas_scsi_clear_queue_lu(&error_q, cmd);
+				if (need_reset)
+					try_to_reset_cmd_device(shost, cmd);
+				sas_scsi_clear_queue_lu(work_q, cmd);
 				goto Again;
 			}
 			/* fallthrough */
 		case TASK_IS_NOT_AT_LU:
+		case TASK_ABORT_FAILED:
 			SAS_DPRINTK("task 0x%p is not at LU: I_T recover\n",
 				    task);
 			tmf_resp = sas_recover_I_T(task->dev);
@@ -464,7 +548,9 @@ Again:
 				SAS_DPRINTK("I_T %016llx recovered\n",
 					    SAS_ADDR(task->dev->sas_addr));
 				task->task_done(task);
-				sas_scsi_clear_queue_I_T(&error_q, task->dev);
+				if (need_reset)
+					try_to_reset_cmd_device(shost, cmd);
+				sas_scsi_clear_queue_I_T(work_q, task->dev);
 				goto Again;
 			}
 			/* Hammer time :-) */
@@ -477,7 +563,9 @@ Again:
 					SAS_DPRINTK("clear nexus port:%d "
 						    "succeeded\n", port->id);
 					task->task_done(task);
-					sas_scsi_clear_queue_port(&error_q,
+					if (need_reset)
+						try_to_reset_cmd_device(shost, cmd);
+					sas_scsi_clear_queue_port(work_q,
 								  port);
 					goto Again;
 				}
@@ -489,6 +577,8 @@ Again:
 					SAS_DPRINTK("clear nexus ha "
 						    "succeeded\n");
 					task->task_done(task);
+					if (need_reset)
+						try_to_reset_cmd_device(shost, cmd);
 					goto out;
 				}
 			}
@@ -502,20 +592,54 @@ Again:
 				    cmd->device->lun);
 
 			task->task_done(task);
+			if (need_reset)
+				try_to_reset_cmd_device(shost, cmd);
 			goto clear_q;
 		}
 	}
 out:
-	scsi_eh_flush_done_q(&ha->eh_done_q);
-	SAS_DPRINTK("--- Exit %s\n", __FUNCTION__);
-	return;
+	return list_empty(work_q);
 clear_q:
 	SAS_DPRINTK("--- Exit %s -- clear_q\n", __FUNCTION__);
-	list_for_each_entry_safe(cmd, n, &error_q, eh_entry) {
+	list_for_each_entry_safe(cmd, n, work_q, eh_entry) {
 		struct sas_task *task = TO_SAS_TASK(cmd);
 		list_del_init(&cmd->eh_entry);
 		task->task_done(task);
 	}
+	return list_empty(work_q);
+}
+
+void sas_scsi_recover_host(struct Scsi_Host *shost)
+{
+	struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
+	unsigned long flags;
+	LIST_HEAD(eh_work_q);
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	list_splice_init(&shost->eh_cmd_q, &eh_work_q);
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
+	SAS_DPRINTK("Enter %s\n", __FUNCTION__);
+	/*
+	 * Deal with commands that still have SAS tasks (i.e. they didn't
+	 * complete via the normal sas_task completion mechanism)
+	 */
+	if (sas_eh_handle_sas_errors(shost, &eh_work_q, &ha->eh_done_q))
+		goto out;
+
+	/*
+	 * Now deal with SCSI commands that completed ok but have a an error
+	 * code (and hopefully sense data) attached.  This is roughly what
+	 * scsi_unjam_host does, but we skip scsi_eh_abort_cmds because any
+	 * command we see here has no sas_task and is thus unknown to the HA.
+	 */
+	if (!scsi_eh_get_sense(&eh_work_q, &ha->eh_done_q))
+		scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q);
+
+out:
+	scsi_eh_flush_done_q(&ha->eh_done_q);
+	SAS_DPRINTK("--- Exit %s\n", __FUNCTION__);
+	return;
 }
 
 enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
@@ -524,24 +648,30 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
 	unsigned long flags;
 
 	if (!task) {
-		SAS_DPRINTK("command 0x%p, task 0x%p, gone: EH_HANDLED\n",
-			    cmd, task);
-		return EH_HANDLED;
+		cmd->timeout_per_command /= 2;
+		SAS_DPRINTK("command 0x%p, task 0x%p, gone: %s\n",
+			    cmd, task, (cmd->timeout_per_command ?
+			    "EH_RESET_TIMER" : "EH_NOT_HANDLED"));
+		if (!cmd->timeout_per_command)
+			return EH_NOT_HANDLED;
+		return EH_RESET_TIMER;
 	}
 
 	spin_lock_irqsave(&task->task_state_lock, flags);
-	if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) {
-		spin_unlock_irqrestore(&task->task_state_lock, flags);
-		SAS_DPRINTK("command 0x%p, task 0x%p, aborted by initiator: "
-			    "EH_NOT_HANDLED\n", cmd, task);
-		return EH_NOT_HANDLED;
-	}
+	BUG_ON(task->task_state_flags & SAS_TASK_STATE_ABORTED);
 	if (task->task_state_flags & SAS_TASK_STATE_DONE) {
 		spin_unlock_irqrestore(&task->task_state_lock, flags);
 		SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n",
 			    cmd, task);
 		return EH_HANDLED;
 	}
+	if (!(task->task_state_flags & SAS_TASK_AT_INITIATOR)) {
+		spin_unlock_irqrestore(&task->task_state_lock, flags);
+		SAS_DPRINTK("command 0x%p, task 0x%p, not at initiator: "
+			    "EH_RESET_TIMER\n",
+			    cmd, task);
+		return EH_RESET_TIMER;
+	}
 	task->task_state_flags |= SAS_TASK_STATE_ABORTED;
 	spin_unlock_irqrestore(&task->task_state_lock, flags);
 
@@ -557,8 +687,9 @@ struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy)
 	struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
 	struct domain_device *found_dev = NULL;
 	int i;
+	unsigned long flags;
 
-	spin_lock(&ha->phy_port_lock);
+	spin_lock_irqsave(&ha->phy_port_lock, flags);
 	for (i = 0; i < ha->num_phys; i++) {
 		struct asd_sas_port *port = ha->sas_port[i];
 		struct domain_device *dev;
@@ -574,7 +705,7 @@ struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy)
 		spin_unlock(&port->dev_list_lock);
 	}
  found:
-	spin_unlock(&ha->phy_port_lock);
+	spin_unlock_irqrestore(&ha->phy_port_lock, flags);
 
 	return found_dev;
 }
@@ -623,6 +754,8 @@ int sas_slave_configure(struct scsi_device *scsi_dev)
 		scsi_deactivate_tcq(scsi_dev, 1);
 	}
 
+	scsi_dev->allow_restart = 1;
+
 	return 0;
 }
 
@@ -799,46 +932,42 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha)
 	spin_unlock_irqrestore(&core->task_queue_lock, flags);
 }
 
-static int do_sas_task_abort(struct sas_task *task)
+/*
+ * Call the LLDD task abort routine directly.  This function is intended for
+ * use by upper layers that need to tell the LLDD to abort a task.
+ */
+int __sas_task_abort(struct sas_task *task)
 {
-	struct scsi_cmnd *sc = task->uldd_task;
 	struct sas_internal *si =
 		to_sas_internal(task->dev->port->ha->core.shost->transportt);
 	unsigned long flags;
 	int res;
 
 	spin_lock_irqsave(&task->task_state_lock, flags);
-	if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
+	if (task->task_state_flags & SAS_TASK_STATE_ABORTED ||
+	    task->task_state_flags & SAS_TASK_STATE_DONE) {
 		spin_unlock_irqrestore(&task->task_state_lock, flags);
-		SAS_DPRINTK("%s: Task %p already aborted.\n", __FUNCTION__,
+		SAS_DPRINTK("%s: Task %p already finished.\n", __FUNCTION__,
 			    task);
 		return 0;
 	}
-
-	task->task_state_flags |= SAS_TASK_INITIATOR_ABORTED;
-	if (!(task->task_state_flags & SAS_TASK_STATE_DONE))
-		task->task_state_flags |= SAS_TASK_STATE_ABORTED;
+	task->task_state_flags |= SAS_TASK_STATE_ABORTED;
 	spin_unlock_irqrestore(&task->task_state_lock, flags);
 
 	if (!si->dft->lldd_abort_task)
 		return -ENODEV;
 
 	res = si->dft->lldd_abort_task(task);
+
+	spin_lock_irqsave(&task->task_state_lock, flags);
 	if ((task->task_state_flags & SAS_TASK_STATE_DONE) ||
 	    (res == TMF_RESP_FUNC_COMPLETE))
 	{
-		/* SMP commands don't have scsi_cmds(?) */
-		if (!sc) {
-			task->task_done(task);
-			return 0;
-		}
-		scsi_req_abort_cmd(sc);
-		scsi_schedule_eh(sc->device->host);
+		spin_unlock_irqrestore(&task->task_state_lock, flags);
+		task->task_done(task);
 		return 0;
 	}
 
-	spin_lock_irqsave(&task->task_state_lock, flags);
-	task->task_state_flags &= ~SAS_TASK_INITIATOR_ABORTED;
 	if (!(task->task_state_flags & SAS_TASK_STATE_DONE))
 		task->task_state_flags &= ~SAS_TASK_STATE_ABORTED;
 	spin_unlock_irqrestore(&task->task_state_lock, flags);
@@ -846,17 +975,24 @@ static int do_sas_task_abort(struct sas_task *task)
 	return -EAGAIN;
 }
 
-void sas_task_abort(struct work_struct *work)
+/*
+ * Tell an upper layer that it needs to initiate an abort for a given task.
+ * This should only ever be called by an LLDD.
+ */
+void sas_task_abort(struct sas_task *task)
 {
-	struct sas_task *task =
-		container_of(work, struct sas_task, abort_work);
-	int i;
+	struct scsi_cmnd *sc = task->uldd_task;
 
-	for (i = 0; i < 5; i++)
-		if (!do_sas_task_abort(task))
+	/* Escape for libsas internal commands */
+	if (!sc) {
+		if (!del_timer(&task->timer))
 			return;
+		task->timer.function(task->timer.data);
+		return;
+	}
 
-	SAS_DPRINTK("%s: Could not kill task!\n", __FUNCTION__);
+	scsi_req_abort_cmd(sc);
+	scsi_schedule_eh(sc->device->host);
 }
 
 EXPORT_SYMBOL_GPL(sas_queuecommand);
@@ -866,5 +1002,9 @@ EXPORT_SYMBOL_GPL(sas_slave_destroy);
 EXPORT_SYMBOL_GPL(sas_change_queue_depth);
 EXPORT_SYMBOL_GPL(sas_change_queue_type);
 EXPORT_SYMBOL_GPL(sas_bios_param);
+EXPORT_SYMBOL_GPL(__sas_task_abort);
 EXPORT_SYMBOL_GPL(sas_task_abort);
 EXPORT_SYMBOL_GPL(sas_phy_reset);
+EXPORT_SYMBOL_GPL(sas_phy_enable);
+EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler);
+EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler);
diff --git a/drivers/scsi/megaraid/mbox_defs.h b/drivers/scsi/megaraid/mbox_defs.h
index 3052869f51f4..170399ef06f4 100644
--- a/drivers/scsi/megaraid/mbox_defs.h
+++ b/drivers/scsi/megaraid/mbox_defs.h
@@ -748,7 +748,7 @@ typedef struct {
 
 
 /**
- * private_bios_data - bios private data for boot devices
+ * struct private_bios_data - bios private data for boot devices
  * @geometry	: bits 0-3 - BIOS geometry, 0x0001 - 1GB, 0x0010 - 2GB,
  *		0x1000 - 8GB, Others values are invalid
  * @unused	: bits 4-7 are unused
diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h
index b50e27e66024..26e1e6c55654 100644
--- a/drivers/scsi/megaraid/mega_common.h
+++ b/drivers/scsi/megaraid/mega_common.h
@@ -46,17 +46,17 @@
 
 /**
  * scb_t - scsi command control block
- * @param ccb		: command control block for individual driver
- * @param list		: list of control blocks
- * @param gp		: general purpose field for LLDs
- * @param sno		: all SCBs have a serial number
- * @param scp		: associated scsi command
- * @param state		: current state of scb
- * @param dma_dir	: direction of data transfer
- * @param dma_type	: transfer with sg list, buffer, or no data transfer
- * @param dev_channel	: actual channel on the device
- * @param dev_target	: actual target on the device
- * @param status	: completion status
+ * @ccb			: command control block for individual driver
+ * @list		: list of control blocks
+ * @gp			: general purpose field for LLDs
+ * @sno			: all SCBs have a serial number
+ * @scp			: associated scsi command
+ * @state		: current state of scb
+ * @dma_dir		: direction of data transfer
+ * @dma_type		: transfer with sg list, buffer, or no data transfer
+ * @dev_channel		: actual channel on the device
+ * @dev_target		: actual target on the device
+ * @status		: completion status
  *
  * This is our central data structure to issue commands the each driver.
  * Driver specific data structures are maintained in the ccb field.
@@ -99,42 +99,42 @@ typedef struct {
 
 /**
  * struct adapter_t - driver's initialization structure
- * @param dpc_h			: tasklet handle
- * @param pdev			: pci configuration pointer for kernel
- * @param host			: pointer to host structure of mid-layer
- * @param lock			: synchronization lock for mid-layer and driver
- * @param quiescent		: driver is quiescent for now.
- * @param outstanding_cmds	: number of commands pending in the driver
- * @param kscb_list		: pointer to the bulk of SCBs pointers for IO
- * @param kscb_pool		: pool of free scbs for IO
- * @param kscb_pool_lock	: lock for pool of free scbs
- * @param pend_list		: pending commands list
- * @param pend_list_lock	: exlusion lock for pending commands list
- * @param completed_list	: list of completed commands
- * @param completed_list_lock	: exclusion lock for list of completed commands
- * @param sglen			: max sg elements supported
- * @param device_ids		: to convert kernel device addr to our devices.
- * @param raid_device		: raid adapter specific pointer
- * @param max_channel		: maximum channel number supported - inclusive
- * @param max_target		: max target supported - inclusive
- * @param max_lun		: max lun supported - inclusive
- * @param unique_id		: unique identifier for each adapter
- * @param irq			: IRQ for this adapter
- * @param ito			: internal timeout value, (-1) means no timeout
- * @param ibuf			: buffer to issue internal commands
- * @param ibuf_dma_h		: dma handle for the above buffer
- * @param uscb_list		: SCB pointers for user cmds, common mgmt module
- * @param uscb_pool		: pool of SCBs for user commands
- * @param uscb_pool_lock	: exclusion lock for these SCBs
- * @param max_cmds		: max outstanding commands
- * @param fw_version		: firmware version
- * @param bios_version		: bios version
- * @param max_cdb_sz		: biggest CDB size supported.
- * @param ha			: is high availability present - clustering
- * @param init_id		: initiator ID, the default value should be 7
- * @param max_sectors		: max sectors per request
- * @param cmd_per_lun		: max outstanding commands per LUN
- * @param being_detached	: set when unloading, no more mgmt calls
+ * @aram dpc_h			: tasklet handle
+ * @pdev			: pci configuration pointer for kernel
+ * @host			: pointer to host structure of mid-layer
+ * @lock			: synchronization lock for mid-layer and driver
+ * @quiescent			: driver is quiescent for now.
+ * @outstanding_cmds		: number of commands pending in the driver
+ * @kscb_list			: pointer to the bulk of SCBs pointers for IO
+ * @kscb_pool			: pool of free scbs for IO
+ * @kscb_pool_lock		: lock for pool of free scbs
+ * @pend_list			: pending commands list
+ * @pend_list_lock		: exclusion lock for pending commands list
+ * @completed_list		: list of completed commands
+ * @completed_list_lock		: exclusion lock for list of completed commands
+ * @sglen			: max sg elements supported
+ * @device_ids			: to convert kernel device addr to our devices.
+ * @raid_device			: raid adapter specific pointer
+ * @max_channel			: maximum channel number supported - inclusive
+ * @max_target			: max target supported - inclusive
+ * @max_lun			: max lun supported - inclusive
+ * @unique_id			: unique identifier for each adapter
+ * @irq				: IRQ for this adapter
+ * @ito				: internal timeout value, (-1) means no timeout
+ * @ibuf			: buffer to issue internal commands
+ * @ibuf_dma_h			: dma handle for the above buffer
+ * @uscb_list			: SCB pointers for user cmds, common mgmt module
+ * @uscb_pool			: pool of SCBs for user commands
+ * @uscb_pool_lock		: exclusion lock for these SCBs
+ * @max_cmds			: max outstanding commands
+ * @fw_version			: firmware version
+ * @bios_version		: bios version
+ * @max_cdb_sz			: biggest CDB size supported.
+ * @ha				: is high availability present - clustering
+ * @init_id			: initiator ID, the default value should be 7
+ * @max_sectors			: max sectors per request
+ * @cmd_per_lun			: max outstanding commands per LUN
+ * @being_detached		: set when unloading, no more mgmt calls
  *
  *
  * mraid_setup_device_map() can be called anytime after the device map is
@@ -211,23 +211,23 @@ typedef struct {
 #define SCP2ADAPTER(scp)	(adapter_t *)SCSIHOST2ADAP(SCP2HOST(scp))
 
 
-/**
- * MRAID_GET_DEVICE_MAP - device ids
- * @param adp		- Adapter's soft state
- * @param scp		- mid-layer scsi command pointer
- * @param p_chan	- physical channel on the controller
- * @param target	- target id of the device or logical drive number
- * @param islogical	- set if the command is for the logical drive
- *
- * Macro to retrieve information about device class, logical or physical and
- * the corresponding physical channel and target or logical drive number
- **/
 #define MRAID_IS_LOGICAL(adp, scp)	\
 	(SCP2CHANNEL(scp) == (adp)->max_channel) ? 1 : 0
 
 #define MRAID_IS_LOGICAL_SDEV(adp, sdev)	\
 	(sdev->channel == (adp)->max_channel) ? 1 : 0
 
+/**
+ * MRAID_GET_DEVICE_MAP - device ids
+ * @adp			: adapter's soft state
+ * @scp			: mid-layer scsi command pointer
+ * @p_chan		: physical channel on the controller
+ * @target		: target id of the device or logical drive number
+ * @islogical		: set if the command is for the logical drive
+ *
+ * Macro to retrieve information about device class, logical or physical and
+ * the corresponding physical channel and target or logical drive number
+ */
 #define MRAID_GET_DEVICE_MAP(adp, scp, p_chan, target, islogical)	\
 	/*								\
 	 * Is the request coming for the virtual channel		\
@@ -271,10 +271,10 @@ typedef struct {
 #define ASSERT(expression)
 #endif
 
-/*
+/**
  * struct mraid_pci_blk - structure holds DMA memory block info
- * @param vaddr		: virtual address to a memory block
- * @param dma_addr	: DMA handle to a memory block
+ * @vaddr		: virtual address to a memory block
+ * @dma_addr		: DMA handle to a memory block
  *
  * This structure is filled up for the caller. It is the responsibilty of the
  * caller to allocate this array big enough to store addresses for all
diff --git a/drivers/scsi/megaraid/megaraid_ioctl.h b/drivers/scsi/megaraid/megaraid_ioctl.h
index b8aa34202ec3..706fa05a187a 100644
--- a/drivers/scsi/megaraid/megaraid_ioctl.h
+++ b/drivers/scsi/megaraid/megaraid_ioctl.h
@@ -22,23 +22,23 @@
 
 #include "mbox_defs.h"
 
+/*
+ * console messages debug levels
+ */
+#define	CL_ANN		0	/* print unconditionally, announcements */
+#define CL_DLEVEL1	1	/* debug level 1, informative */
+#define CL_DLEVEL2	2	/* debug level 2, verbose */
+#define CL_DLEVEL3	3	/* debug level 3, very verbose */
+
 /**
  * con_log() - console log routine
- * @param level		: indicates the severity of the message.
- * @fparam mt		: format string
+ * @level		: indicates the severity of the message.
+ * @fmt			: format string
  *
  * con_log displays the error messages on the console based on the current
  * debug level. Also it attaches the appropriate kernel severity level with
  * the message.
- *
- *
- * consolge messages debug levels
  */
-#define	CL_ANN		0	/* print unconditionally, announcements */
-#define CL_DLEVEL1	1	/* debug level 1, informative */
-#define CL_DLEVEL2	2	/* debug level 2, verbose */
-#define CL_DLEVEL3	3	/* debug level 3, very verbose */
-
 #define	con_log(level, fmt) if (LSI_DBGLVL >= level) printk fmt;
 
 /*
@@ -157,14 +157,14 @@ typedef struct uioc {
 /**
  * struct mraid_hba_info - information about the controller
  *
- * @param pci_vendor_id		: PCI vendor id
- * @param pci_device_id		: PCI device id
- * @param subsystem_vendor_id	: PCI subsystem vendor id
- * @param subsystem_device_id	: PCI subsystem device id
- * @param baseport		: base port of hba memory
- * @param pci_bus		: PCI bus
- * @param pci_dev_fn		: PCI device/function values
- * @param irq			: interrupt vector for the device
+ * @pci_vendor_id		: PCI vendor id
+ * @pci_device_id		: PCI device id
+ * @subsystem_vendor_id		: PCI subsystem vendor id
+ * @subsystem_device_id		: PCI subsystem device id
+ * @baseport			: base port of hba memory
+ * @pci_bus			: PCI bus
+ * @pci_dev_fn			: PCI device/function values
+ * @irq				: interrupt vector for the device
  *
  * Extended information of 256 bytes about the controller. Align on the single
  * byte boundary so that 32-bit applications can be run on 64-bit platform
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index 7bac86dda88f..04d0b6918c61 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -10,13 +10,13 @@
  *	   2 of the License, or (at your option) any later version.
  *
  * FILE		: megaraid_mbox.c
- * Version	: v2.20.4.9 (Jul 16 2006)
+ * Version	: v2.20.5.1 (Nov 16 2006)
  *
  * Authors:
- * 	Atul Mukker		<Atul.Mukker@lsil.com>
- * 	Sreenivas Bagalkote	<Sreenivas.Bagalkote@lsil.com>
- * 	Manoj Jose		<Manoj.Jose@lsil.com>
- * 	Seokmann Ju		<Seokmann.Ju@lsil.com>
+ * 	Atul Mukker		<Atul.Mukker@lsi.com>
+ * 	Sreenivas Bagalkote	<Sreenivas.Bagalkote@lsi.com>
+ * 	Manoj Jose		<Manoj.Jose@lsi.com>
+ * 	Seokmann Ju
  *
  * List of supported controllers
  *
@@ -107,6 +107,7 @@ static int megaraid_mbox_support_random_del(adapter_t *);
 static int megaraid_mbox_get_max_sg(adapter_t *);
 static void megaraid_mbox_enum_raid_scsi(adapter_t *);
 static void megaraid_mbox_flush_cache(adapter_t *);
+static int megaraid_mbox_fire_sync_cmd(adapter_t *);
 
 static void megaraid_mbox_display_scb(adapter_t *, scb_t *);
 static void megaraid_mbox_setup_device_map(adapter_t *);
@@ -137,7 +138,7 @@ static int wait_till_fw_empty(adapter_t *);
 
 
 
-MODULE_AUTHOR("sju@lsil.com");
+MODULE_AUTHOR("megaraidlinux@lsi.com");
 MODULE_DESCRIPTION("LSI Logic MegaRAID Mailbox Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(MEGARAID_VERSION);
@@ -146,7 +147,7 @@ MODULE_VERSION(MEGARAID_VERSION);
  * ### modules parameters for driver ###
  */
 
-/**
+/*
  * Set to enable driver to expose unconfigured disk to kernel
  */
 static int megaraid_expose_unconf_disks = 0;
@@ -154,7 +155,7 @@ module_param_named(unconf_disks, megaraid_expose_unconf_disks, int, 0);
 MODULE_PARM_DESC(unconf_disks,
 	"Set to expose unconfigured disks to kernel (default=0)");
 
-/**
+/*
  * driver wait time if the adapter's mailbox is busy
  */
 static unsigned int max_mbox_busy_wait = MBOX_BUSY_WAIT;
@@ -162,7 +163,7 @@ module_param_named(busy_wait, max_mbox_busy_wait, int, 0);
 MODULE_PARM_DESC(busy_wait,
 	"Max wait for mailbox in microseconds if busy (default=10)");
 
-/**
+/*
  * number of sectors per IO command
  */
 static unsigned int megaraid_max_sectors = MBOX_MAX_SECTORS;
@@ -170,7 +171,7 @@ module_param_named(max_sectors, megaraid_max_sectors, int, 0);
 MODULE_PARM_DESC(max_sectors,
 	"Maximum number of sectors per IO command (default=128)");
 
-/**
+/*
  * number of commands per logical unit
  */
 static unsigned int megaraid_cmd_per_lun = MBOX_DEF_CMD_PER_LUN;
@@ -179,7 +180,7 @@ MODULE_PARM_DESC(cmd_per_lun,
 	"Maximum number of commands per logical unit (default=64)");
 
 
-/**
+/*
  * Fast driver load option, skip scanning for physical devices during load.
  * This would result in non-disk devices being skipped during driver load
  * time. These can be later added though, using /proc/scsi/scsi
@@ -190,7 +191,7 @@ MODULE_PARM_DESC(fast_load,
 	"Faster loading of the driver, skips physical devices! (default=0)");
 
 
-/**
+/*
  * mraid_debug level - threshold for amount of information to be displayed by
  * the driver. This level can be changed through modules parameters, ioctl or
  * sysfs/proc interface. By default, print the announcement messages only.
@@ -337,7 +338,7 @@ static struct device_attribute *megaraid_sdev_attrs[] = {
  *
  * Return value:
  * 	actual depth set
- **/
+ */
 static int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
 	if (qdepth > MBOX_MAX_SCSI_CMDS)
@@ -369,8 +370,8 @@ static struct scsi_host_template megaraid_template_g = {
  * megaraid_init - module load hook
  *
  * We register ourselves as hotplug enabled module and let PCI subsystem
- * discover our adaters
- **/
+ * discover our adapters.
+ */
 static int __init
 megaraid_init(void)
 {
@@ -405,7 +406,7 @@ megaraid_init(void)
 /**
  * megaraid_exit - driver unload entry point
  *
- * We simply unwrap the megaraid_init routine here
+ * We simply unwrap the megaraid_init routine here.
  */
 static void __exit
 megaraid_exit(void)
@@ -421,12 +422,12 @@ megaraid_exit(void)
 
 /**
  * megaraid_probe_one - PCI hotplug entry point
- * @param pdev	: handle to this controller's PCI configuration space
- * @param id	: pci device id of the class of controllers
+ * @pdev	: handle to this controller's PCI configuration space
+ * @id		: pci device id of the class of controllers
  *
  * This routine should be called whenever a new adapter is detected by the
  * PCI hotplug susbsytem.
- **/
+ */
 static int __devinit
 megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
@@ -542,16 +543,15 @@ out_probe_one:
 
 
 /**
- * megaraid_detach_one - release the framework resources and call LLD release
- * routine
- * @param pdev	: handle for our PCI cofiguration space
+ * megaraid_detach_one - release framework resources and call LLD release routine
+ * @pdev	: handle for our PCI cofiguration space
  *
  * This routine is called during driver unload. We free all the allocated
  * resources and call the corresponding LLD so that it can also release all
  * its resources.
  *
- * This routine is also called from the PCI hotplug system
- **/
+ * This routine is also called from the PCI hotplug system.
+ */
 static void
 megaraid_detach_one(struct pci_dev *pdev)
 {
@@ -615,9 +615,9 @@ megaraid_detach_one(struct pci_dev *pdev)
 
 /**
  * megaraid_mbox_shutdown - PCI shutdown for megaraid HBA
- * @param device	: generice driver model device
+ * @pdev		: generic driver model device
  *
- * Shutdown notification, perform flush cache
+ * Shutdown notification, perform flush cache.
  */
 static void
 megaraid_mbox_shutdown(struct pci_dev *pdev)
@@ -643,10 +643,10 @@ megaraid_mbox_shutdown(struct pci_dev *pdev)
 
 /**
  * megaraid_io_attach - attach a device with the IO subsystem
- * @param adapter	: controller's soft state
+ * @adapter		: controller's soft state
  *
- * Attach this device with the IO subsystem
- **/
+ * Attach this device with the IO subsystem.
+ */
 static int
 megaraid_io_attach(adapter_t *adapter)
 {
@@ -695,10 +695,10 @@ megaraid_io_attach(adapter_t *adapter)
 
 /**
  * megaraid_io_detach - detach a device from the IO subsystem
- * @param adapter	: controller's soft state
+ * @adapter		: controller's soft state
  *
- * Detach this device from the IO subsystem
- **/
+ * Detach this device from the IO subsystem.
+ */
 static void
 megaraid_io_detach(adapter_t *adapter)
 {
@@ -722,13 +722,13 @@ megaraid_io_detach(adapter_t *adapter)
 
 /**
  * megaraid_init_mbox - initialize controller
- * @param adapter	- our soft state
+ * @adapter		: our soft state
  *
- * . Allocate 16-byte aligned mailbox memory for firmware handshake
- * . Allocate controller's memory resources
- * . Find out all initialization data
- * . Allocate memory required for all the commands
- * . Use internal library of FW routines, build up complete soft state
+ * - Allocate 16-byte aligned mailbox memory for firmware handshake
+ * - Allocate controller's memory resources
+ * - Find out all initialization data
+ * - Allocate memory required for all the commands
+ * - Use internal library of FW routines, build up complete soft state
  */
 static int __devinit
 megaraid_init_mbox(adapter_t *adapter)
@@ -779,33 +779,39 @@ megaraid_init_mbox(adapter_t *adapter)
 		goto out_release_regions;
 	}
 
-	//
-	// Setup the rest of the soft state using the library of FW routines
-	//
+	/* initialize the mutual exclusion lock for the mailbox */
+	spin_lock_init(&raid_dev->mailbox_lock);
 
-	// request IRQ and register the interrupt service routine
+	/* allocate memory required for commands */
+	if (megaraid_alloc_cmd_packets(adapter) != 0)
+		goto out_iounmap;
+
+	/*
+	 * Issue SYNC cmd to flush the pending cmds in the adapter
+	 * and initialize its internal state
+	 */
+
+	if (megaraid_mbox_fire_sync_cmd(adapter))
+		con_log(CL_ANN, ("megaraid: sync cmd failed\n"));
+
+	/*
+	 * Setup the rest of the soft state using the library of
+	 * FW routines
+	 */
+
+	/* request IRQ and register the interrupt service routine */
 	if (request_irq(adapter->irq, megaraid_isr, IRQF_SHARED, "megaraid",
 		adapter)) {
 
 		con_log(CL_ANN, (KERN_WARNING
 			"megaraid: Couldn't register IRQ %d!\n", adapter->irq));
+		goto out_alloc_cmds;
 
-		goto out_iounmap;
-	}
-
-
-	// initialize the mutual exclusion lock for the mailbox
-	spin_lock_init(&raid_dev->mailbox_lock);
-
-	// allocate memory required for commands
-	if (megaraid_alloc_cmd_packets(adapter) != 0) {
-		goto out_free_irq;
 	}
 
 	// Product info
-	if (megaraid_mbox_product_info(adapter) != 0) {
-		goto out_alloc_cmds;
-	}
+	if (megaraid_mbox_product_info(adapter) != 0)
+		goto out_free_irq;
 
 	// Do we support extended CDBs
 	adapter->max_cdb_sz = 10;
@@ -874,9 +880,8 @@ megaraid_init_mbox(adapter_t *adapter)
 	 * Allocate resources required to issue FW calls, when sysfs is
 	 * accessed
 	 */
-	if (megaraid_sysfs_alloc_resources(adapter) != 0) {
-		goto out_alloc_cmds;
-	}
+	if (megaraid_sysfs_alloc_resources(adapter) != 0)
+		goto out_free_irq;
 
 	// Set the DMA mask to 64-bit. All supported controllers as capable of
 	// DMA in this range
@@ -920,10 +925,10 @@ megaraid_init_mbox(adapter_t *adapter)
 
 out_free_sysfs_res:
 	megaraid_sysfs_free_resources(adapter);
-out_alloc_cmds:
-	megaraid_free_cmd_packets(adapter);
 out_free_irq:
 	free_irq(adapter->irq, adapter);
+out_alloc_cmds:
+	megaraid_free_cmd_packets(adapter);
 out_iounmap:
 	iounmap(raid_dev->baseaddr);
 out_release_regions:
@@ -937,7 +942,7 @@ out_free_raid_dev:
 
 /**
  * megaraid_fini_mbox - undo controller initialization
- * @param adapter	: our soft state
+ * @adapter		: our soft state
  */
 static void
 megaraid_fini_mbox(adapter_t *adapter)
@@ -967,12 +972,12 @@ megaraid_fini_mbox(adapter_t *adapter)
 
 /**
  * megaraid_alloc_cmd_packets - allocate shared mailbox
- * @param adapter	: soft state of the raid controller
+ * @adapter		: soft state of the raid controller
  *
  * Allocate and align the shared mailbox. This maibox is used to issue
  * all the commands. For IO based controllers, the mailbox is also regsitered
  * with the FW. Allocate memory for all commands as well.
- * This is our big allocator
+ * This is our big allocator.
  */
 static int
 megaraid_alloc_cmd_packets(adapter_t *adapter)
@@ -1132,9 +1137,9 @@ out_free_common_mbox:
 
 /**
  * megaraid_free_cmd_packets - free memory
- * @param adapter	: soft state of the raid controller
+ * @adapter		: soft state of the raid controller
  *
- * Release memory resources allocated for commands
+ * Release memory resources allocated for commands.
  */
 static void
 megaraid_free_cmd_packets(adapter_t *adapter)
@@ -1156,10 +1161,10 @@ megaraid_free_cmd_packets(adapter_t *adapter)
 
 /**
  * megaraid_mbox_setup_dma_pools - setup dma pool for command packets
- * @param adapter	: HBA soft state
+ * @adapter		: HBA soft state
  *
- * setup the dma pools for mailbox, passthru and extended passthru structures,
- * and scatter-gather lists
+ * Setup the dma pools for mailbox, passthru and extended passthru structures,
+ * and scatter-gather lists.
  */
 static int
 megaraid_mbox_setup_dma_pools(adapter_t *adapter)
@@ -1252,10 +1257,10 @@ fail_setup_dma_pool:
 
 /**
  * megaraid_mbox_teardown_dma_pools - teardown dma pools for command packets
- * @param adapter	: HBA soft state
+ * @adapter		: HBA soft state
  *
- * teardown the dma pool for mailbox, passthru and extended passthru
- * structures, and scatter-gather lists
+ * Teardown the dma pool for mailbox, passthru and extended passthru
+ * structures, and scatter-gather lists.
  */
 static void
 megaraid_mbox_teardown_dma_pools(adapter_t *adapter)
@@ -1300,10 +1305,11 @@ megaraid_mbox_teardown_dma_pools(adapter_t *adapter)
 /**
  * megaraid_alloc_scb - detach and return a scb from the free list
  * @adapter	: controller's soft state
+ * @scp		: pointer to the scsi command to be executed
  *
- * return the scb from the head of the free list. NULL if there are none
- * available
- **/
+ * Return the scb from the head of the free list. %NULL if there are none
+ * available.
+ */
 static scb_t *
 megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp)
 {
@@ -1337,11 +1343,11 @@ megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp)
  * @adapter	: controller's soft state
  * @scb		: scb to be freed
  *
- * return the scb back to the free list of scbs. The caller must 'flush' the
+ * Return the scb back to the free list of scbs. The caller must 'flush' the
  * SCB before calling us. E.g., performing pci_unamp and/or pci_sync etc.
  * NOTE NOTE: Make sure the scb is not on any list before calling this
  * routine.
- **/
+ */
 static inline void
 megaraid_dealloc_scb(adapter_t *adapter, scb_t *scb)
 {
@@ -1362,10 +1368,10 @@ megaraid_dealloc_scb(adapter_t *adapter, scb_t *scb)
 
 /**
  * megaraid_mbox_mksgl - make the scatter-gather list
- * @adapter	- controller's soft state
- * @scb		- scsi control block
+ * @adapter	: controller's soft state
+ * @scb		: scsi control block
  *
- * prepare the scatter-gather list
+ * Prepare the scatter-gather list.
  */
 static int
 megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb)
@@ -1435,10 +1441,10 @@ megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb)
 
 /**
  * mbox_post_cmd - issue a mailbox command
- * @adapter	- controller's soft state
- * @scb		- command to be issued
+ * @adapter	: controller's soft state
+ * @scb		: command to be issued
  *
- * post the command to the controller if mailbox is availble.
+ * Post the command to the controller if mailbox is available.
  */
 static int
 mbox_post_cmd(adapter_t *adapter, scb_t *scb)
@@ -1518,7 +1524,7 @@ mbox_post_cmd(adapter_t *adapter, scb_t *scb)
  * Queue entry point for mailbox based controllers.
  */
 static int
-megaraid_queue_command(struct scsi_cmnd *scp, void (* done)(struct scsi_cmnd *))
+megaraid_queue_command(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
 {
 	adapter_t	*adapter;
 	scb_t		*scb;
@@ -1548,15 +1554,15 @@ megaraid_queue_command(struct scsi_cmnd *scp, void (* done)(struct scsi_cmnd *))
 }
 
 /**
- * megaraid_mbox_build_cmd - transform the mid-layer scsi command to megaraid
- * firmware lingua
- * @adapter	- controller's soft state
- * @scp		- mid-layer scsi command pointer
- * @busy	- set if request could not be completed because of lack of
+ * megaraid_mbox_build_cmd - transform the mid-layer scsi commands
+ * @adapter	: controller's soft state
+ * @scp		: mid-layer scsi command pointer
+ * @busy	: set if request could not be completed because of lack of
  *		resources
  *
- * convert the command issued by mid-layer to format understood by megaraid
- * firmware. We also complete certain command without sending them to firmware
+ * Transform the mid-layer scsi command to megaraid firmware lingua.
+ * Convert the command issued by mid-layer to format understood by megaraid
+ * firmware. We also complete certain commands without sending them to firmware.
  */
 static scb_t *
 megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy)
@@ -1937,9 +1943,9 @@ megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy)
 /**
  * megaraid_mbox_runpendq - execute commands queued in the pending queue
  * @adapter	: controller's soft state
- * @scb		: SCB to be queued in the pending list
+ * @scb_q	: SCB to be queued in the pending list
  *
- * scan the pending list for commands which are not yet issued and try to
+ * Scan the pending list for commands which are not yet issued and try to
  * post to the controller. The SCB can be a null pointer, which would indicate
  * no SCB to be queue, just try to execute the ones in the pending list.
  *
@@ -2012,11 +2018,11 @@ megaraid_mbox_runpendq(adapter_t *adapter, scb_t *scb_q)
 
 /**
  * megaraid_mbox_prepare_pthru - prepare a command for physical devices
- * @adapter	- pointer to controller's soft state
- * @scb		- scsi control block
- * @scp		- scsi command from the mid-layer
+ * @adapter	: pointer to controller's soft state
+ * @scb		: scsi control block
+ * @scp		: scsi command from the mid-layer
  *
- * prepare a command for the scsi physical devices
+ * Prepare a command for the scsi physical devices.
  */
 static void
 megaraid_mbox_prepare_pthru(adapter_t *adapter, scb_t *scb,
@@ -2060,12 +2066,12 @@ megaraid_mbox_prepare_pthru(adapter_t *adapter, scb_t *scb,
 
 /**
  * megaraid_mbox_prepare_epthru - prepare a command for physical devices
- * @adapter	- pointer to controller's soft state
- * @scb		- scsi control block
- * @scp		- scsi command from the mid-layer
+ * @adapter	: pointer to controller's soft state
+ * @scb		: scsi control block
+ * @scp		: scsi command from the mid-layer
  *
- * prepare a command for the scsi physical devices. This rountine prepares
- * commands for devices which can take extended CDBs (>10 bytes)
+ * Prepare a command for the scsi physical devices. This rountine prepares
+ * commands for devices which can take extended CDBs (>10 bytes).
  */
 static void
 megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb,
@@ -2109,9 +2115,9 @@ megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb,
 
 /**
  * megaraid_ack_sequence - interrupt ack sequence for memory mapped HBAs
- * @adapter	- controller's soft state
+ * @adapter	: controller's soft state
  *
- * Interrupt ackrowledgement sequence for memory mapped HBAs. Find out the
+ * Interrupt acknowledgement sequence for memory mapped HBAs. Find out the
  * completed command and put them on the completed list for later processing.
  *
  * Returns:	1 if the interrupt is valid, 0 otherwise
@@ -2224,9 +2230,8 @@ megaraid_ack_sequence(adapter_t *adapter)
 
 /**
  * megaraid_isr - isr for memory based mailbox based controllers
- * @irq		- irq
- * @devp	- pointer to our soft state
- * @regs	- unused
+ * @irq		: irq
+ * @devp	: pointer to our soft state
  *
  * Interrupt service routine for memory-mapped mailbox controllers.
  */
@@ -2671,7 +2676,7 @@ megaraid_abort_handler(struct scsi_cmnd *scp)
  * the FW is still live, in which case the outstanding commands counter mut go
  * down to 0. If that happens, also issue the reservation reset command to
  * relinquish (possible) reservations on the logical drives connected to this
- * host
+ * host.
  **/
 static int
 megaraid_reset_handler(struct scsi_cmnd *scp)
@@ -2823,11 +2828,11 @@ megaraid_reset_handler(struct scsi_cmnd *scp)
 
 /**
  * mbox_post_sync_cmd() - blocking command to the mailbox based controllers
- * @adapter	- controller's soft state
- * @raw_mbox	- the mailbox
+ * @adapter	: controller's soft state
+ * @raw_mbox	: the mailbox
  *
  * Issue a scb in synchronous and non-interrupt mode for mailbox based
- * controllers
+ * controllers.
  */
 static int
 mbox_post_sync_cmd(adapter_t *adapter, uint8_t raw_mbox[])
@@ -2955,12 +2960,12 @@ blocked_mailbox:
 
 /**
  * mbox_post_sync_cmd_fast - blocking command to the mailbox based controllers
- * @adapter	- controller's soft state
- * @raw_mbox	- the mailbox
+ * @adapter	: controller's soft state
+ * @raw_mbox	: the mailbox
  *
  * Issue a scb in synchronous and non-interrupt mode for mailbox based
  * controllers. This is a faster version of the synchronous command and
- * therefore can be called in interrupt-context as well
+ * therefore can be called in interrupt-context as well.
  */
 static int
 mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[])
@@ -3008,10 +3013,10 @@ mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[])
 
 /**
  * megaraid_busywait_mbox() - Wait until the controller's mailbox is available
- * @raid_dev	- RAID device (HBA) soft state
+ * @raid_dev	: RAID device (HBA) soft state
  *
- * wait until the controller's mailbox is available to accept more commands.
- * wait for at most 1 second
+ * Wait until the controller's mailbox is available to accept more commands.
+ * Wait for at most 1 second.
  */
 static int
 megaraid_busywait_mbox(mraid_device_t *raid_dev)
@@ -3032,9 +3037,9 @@ megaraid_busywait_mbox(mraid_device_t *raid_dev)
 
 /**
  * megaraid_mbox_product_info - some static information about the controller
- * @adapter	- our soft state
+ * @adapter	: our soft state
  *
- * issue commands to the controller to grab some parameters required by our
+ * Issue commands to the controller to grab some parameters required by our
  * caller.
  */
 static int
@@ -3157,10 +3162,10 @@ megaraid_mbox_product_info(adapter_t *adapter)
 
 /**
  * megaraid_mbox_extended_cdb - check for support for extended CDBs
- * @adapter	- soft state for the controller
+ * @adapter	: soft state for the controller
  *
- * this routine check whether the controller in question supports extended
- * ( > 10 bytes ) CDBs
+ * This routine check whether the controller in question supports extended
+ * ( > 10 bytes ) CDBs.
  */
 static int
 megaraid_mbox_extended_cdb(adapter_t *adapter)
@@ -3193,8 +3198,8 @@ megaraid_mbox_extended_cdb(adapter_t *adapter)
 
 /**
  * megaraid_mbox_support_ha - Do we support clustering
- * @adapter	- soft state for the controller
- * @init_id	- ID of the initiator
+ * @adapter	: soft state for the controller
+ * @init_id	: ID of the initiator
  *
  * Determine if the firmware supports clustering and the ID of the initiator.
  */
@@ -3236,9 +3241,9 @@ megaraid_mbox_support_ha(adapter_t *adapter, uint16_t *init_id)
 
 /**
  * megaraid_mbox_support_random_del - Do we support random deletion
- * @adapter	- soft state for the controller
+ * @adapter	: soft state for the controller
  *
- * Determine if the firmware supports random deletion
+ * Determine if the firmware supports random deletion.
  * Return:	1 is operation supported, 0 otherwise
  */
 static int
@@ -3271,10 +3276,10 @@ megaraid_mbox_support_random_del(adapter_t *adapter)
 
 /**
  * megaraid_mbox_get_max_sg - maximum sg elements supported by the firmware
- * @adapter	- soft state for the controller
+ * @adapter	: soft state for the controller
  *
  * Find out the maximum number of scatter-gather elements supported by the
- * firmware
+ * firmware.
  */
 static int
 megaraid_mbox_get_max_sg(adapter_t *adapter)
@@ -3311,10 +3316,10 @@ megaraid_mbox_get_max_sg(adapter_t *adapter)
 
 /**
  * megaraid_mbox_enum_raid_scsi - enumerate the RAID and SCSI channels
- * @adapter	- soft state for the controller
+ * @adapter	: soft state for the controller
  *
- * Enumerate the RAID and SCSI channels for ROMB platoforms so that channels
- * can be exported as regular SCSI channels
+ * Enumerate the RAID and SCSI channels for ROMB platforms so that channels
+ * can be exported as regular SCSI channels.
  */
 static void
 megaraid_mbox_enum_raid_scsi(adapter_t *adapter)
@@ -3348,9 +3353,9 @@ megaraid_mbox_enum_raid_scsi(adapter_t *adapter)
 
 /**
  * megaraid_mbox_flush_cache - flush adapter and disks cache
- * @param adapter	: soft state for the controller
+ * @adapter		: soft state for the controller
  *
- * Flush adapter cache followed by disks cache
+ * Flush adapter cache followed by disks cache.
  */
 static void
 megaraid_mbox_flush_cache(adapter_t *adapter)
@@ -3380,13 +3385,91 @@ megaraid_mbox_flush_cache(adapter_t *adapter)
 
 
 /**
+ * megaraid_mbox_fire_sync_cmd - fire the sync cmd
+ * @adapter		: soft state for the controller
+ *
+ * Clears the pending cmds in FW and reinits its RAID structs.
+ */
+static int
+megaraid_mbox_fire_sync_cmd(adapter_t *adapter)
+{
+	mbox_t	*mbox;
+	uint8_t	raw_mbox[sizeof(mbox_t)];
+	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
+	mbox64_t *mbox64;
+	int	status = 0;
+	int i;
+	uint32_t dword;
+
+	mbox = (mbox_t *)raw_mbox;
+
+	memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
+
+	raw_mbox[0] = 0xFF;
+
+	mbox64	= raid_dev->mbox64;
+	mbox	= raid_dev->mbox;
+
+	/* Wait until mailbox is free */
+	if (megaraid_busywait_mbox(raid_dev) != 0) {
+		status = 1;
+		goto blocked_mailbox;
+	}
+
+	/* Copy mailbox data into host structure */
+	memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 16);
+	mbox->cmdid		= 0xFE;
+	mbox->busy		= 1;
+	mbox->poll		= 0;
+	mbox->ack		= 0;
+	mbox->numstatus		= 0;
+	mbox->status		= 0;
+
+	wmb();
+	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
+
+	/* Wait for maximum 1 min for status to post.
+	 * If the Firmware SUPPORTS the ABOVE COMMAND,
+	 * mbox->cmd will be set to 0
+	 * else
+	 * the firmware will reject the command with
+	 * mbox->numstatus set to 1
+	 */
+
+	i = 0;
+	status = 0;
+	while (!mbox->numstatus && mbox->cmd == 0xFF) {
+		rmb();
+		msleep(1);
+		i++;
+		if (i > 1000 * 60) {
+			status = 1;
+			break;
+		}
+	}
+	if (mbox->numstatus == 1)
+		status = 1; /*cmd not supported*/
+
+	/* Check for interrupt line */
+	dword = RDOUTDOOR(raid_dev);
+	WROUTDOOR(raid_dev, dword);
+	WRINDOOR(raid_dev,2);
+
+	return status;
+
+blocked_mailbox:
+	con_log(CL_ANN, (KERN_WARNING "megaraid: blocked mailbox\n"));
+	return status;
+}
+
+/**
  * megaraid_mbox_display_scb - display SCB information, mostly debug purposes
- * @param adapter	: controllers' soft state
- * @param scb		: SCB to be displayed
- * @param level	: debug level for console print
+ * @adapter		: controller's soft state
+ * @scb			: SCB to be displayed
+ * @level		: debug level for console print
  *
  * Diplay information about the given SCB iff the current debug level is
- * verbose
+ * verbose.
  */
 static void
 megaraid_mbox_display_scb(adapter_t *adapter, scb_t *scb)
@@ -3434,7 +3517,7 @@ megaraid_mbox_display_scb(adapter_t *adapter, scb_t *scb)
  * scsi addresses and megaraid scsi and logical drive addresses. We export
  * scsi devices on their actual addresses, whereas the logical drives are
  * exported on a virtual scsi channel.
- **/
+ */
 static void
 megaraid_mbox_setup_device_map(adapter_t *adapter)
 {
@@ -3472,7 +3555,7 @@ megaraid_mbox_setup_device_map(adapter_t *adapter)
 
 /**
  * megaraid_cmm_register - register with the mangement module
- * @param adapter	: HBA soft state
+ * @adapter		: HBA soft state
  *
  * Register with the management module, which allows applications to issue
  * ioctl calls to the drivers. This interface is used by the management module
@@ -3562,11 +3645,11 @@ megaraid_cmm_register(adapter_t *adapter)
 
 /**
  * megaraid_cmm_unregister - un-register with the mangement module
- * @param adapter	: HBA soft state
+ * @adapter		: HBA soft state
  *
  * Un-register with the management module.
  * FIXME: mgmt module must return failure for unregister if it has pending
- * commands in LLD
+ * commands in LLD.
  */
 static int
 megaraid_cmm_unregister(adapter_t *adapter)
@@ -3579,9 +3662,9 @@ megaraid_cmm_unregister(adapter_t *adapter)
 
 /**
  * megaraid_mbox_mm_handler - interface for CMM to issue commands to LLD
- * @param drvr_data	: LLD specific data
- * @param kioc		: CMM interface packet
- * @param action	: command action
+ * @drvr_data		: LLD specific data
+ * @kioc		: CMM interface packet
+ * @action		: command action
  *
  * This routine is invoked whenever the Common Mangement Module (CMM) has a
  * command for us. The 'action' parameter specifies if this is a new command
@@ -3634,8 +3717,8 @@ megaraid_mbox_mm_handler(unsigned long drvr_data, uioc_t *kioc, uint32_t action)
 
 /**
  * megaraid_mbox_mm_command - issues commands routed through CMM
- * @param adapter	: HBA soft state
- * @param kioc		: management command packet
+ * @adapter		: HBA soft state
+ * @kioc		: management command packet
  *
  * Issues commands, which are routed through the management module.
  */
@@ -3804,8 +3887,8 @@ megaraid_mbox_mm_done(adapter_t *adapter, scb_t *scb)
 
 /**
  * gather_hbainfo - HBA characteristics for the applications
- * @param adapter	: HBA soft state
- * @param hinfo		: pointer to the caller's host info strucuture
+ * @adapter		: HBA soft state
+ * @hinfo		: pointer to the caller's host info strucuture
  */
 static int
 gather_hbainfo(adapter_t *adapter, mraid_hba_info_t *hinfo)
@@ -3839,16 +3922,15 @@ gather_hbainfo(adapter_t *adapter, mraid_hba_info_t *hinfo)
 
 /**
  * megaraid_sysfs_alloc_resources - allocate sysfs related resources
+ * @adapter	: controller's soft state
  *
  * Allocate packets required to issue FW calls whenever the sysfs attributes
  * are read. These attributes would require up-to-date information from the
  * FW. Also set up resources for mutual exclusion to share these resources and
  * the wait queue.
  *
- * @param adapter : controller's soft state
- *
- * @return 0 on success
- * @return -ERROR_CODE on failure
+ * Return 0 on success.
+ * Return -ERROR_CODE on failure.
  */
 static int
 megaraid_sysfs_alloc_resources(adapter_t *adapter)
@@ -3885,10 +3967,9 @@ megaraid_sysfs_alloc_resources(adapter_t *adapter)
 
 /**
  * megaraid_sysfs_free_resources - free sysfs related resources
+ * @adapter	: controller's soft state
  *
  * Free packets allocated for sysfs FW commands
- *
- * @param adapter : controller's soft state
  */
 static void
 megaraid_sysfs_free_resources(adapter_t *adapter)
@@ -3907,10 +3988,9 @@ megaraid_sysfs_free_resources(adapter_t *adapter)
 
 /**
  * megaraid_sysfs_get_ldmap_done - callback for get ldmap
+ * @uioc	: completed packet
  *
  * Callback routine called in the ISR/tasklet context for get ldmap call
- *
- * @param uioc : completed packet
  */
 static void
 megaraid_sysfs_get_ldmap_done(uioc_t *uioc)
@@ -3926,12 +4006,11 @@ megaraid_sysfs_get_ldmap_done(uioc_t *uioc)
 
 /**
  * megaraid_sysfs_get_ldmap_timeout - timeout handling for get ldmap
+ * @data	: timed out packet
  *
  * Timeout routine to recover and return to application, in case the adapter
- * has stopped responding. A timeout of 60 seconds for this command seem like
- * a good value
- *
- * @param uioc : timed out packet
+ * has stopped responding. A timeout of 60 seconds for this command seems like
+ * a good value.
  */
 static void
 megaraid_sysfs_get_ldmap_timeout(unsigned long data)
@@ -3948,6 +4027,7 @@ megaraid_sysfs_get_ldmap_timeout(unsigned long data)
 
 /**
  * megaraid_sysfs_get_ldmap - get update logical drive map
+ * @adapter	: controller's soft state
  *
  * This routine will be called whenever user reads the logical drive
  * attributes, go get the current logical drive mapping table from the
@@ -3959,10 +4039,8 @@ megaraid_sysfs_get_ldmap_timeout(unsigned long data)
  * standalone libary. For now, this should suffice since there is no other
  * user of this interface.
  *
- * @param adapter : controller's soft state
- *
- * @return 0 on success
- * @return -1 on failure
+ * Return 0 on success.
+ * Return -1 on failure.
  */
 static int
 megaraid_sysfs_get_ldmap(adapter_t *adapter)
@@ -4064,13 +4142,12 @@ megaraid_sysfs_get_ldmap(adapter_t *adapter)
 
 /**
  * megaraid_sysfs_show_app_hndl - display application handle for this adapter
+ * @cdev	: class device object representation for the host
+ * @buf		: buffer to send data to
  *
  * Display the handle used by the applications while executing management
  * tasks on the adapter. We invoke a management module API to get the adapter
  * handle, since we do not interface with applications directly.
- *
- * @param cdev	: class device object representation for the host
- * @param buf	: buffer to send data to
  */
 static ssize_t
 megaraid_sysfs_show_app_hndl(struct class_device *cdev, char *buf)
@@ -4087,16 +4164,18 @@ megaraid_sysfs_show_app_hndl(struct class_device *cdev, char *buf)
 
 /**
  * megaraid_sysfs_show_ldnum - display the logical drive number for this device
+ * @dev		: device object representation for the scsi device
+ * @attr	: device attribute to show
+ * @buf		: buffer to send data to
  *
  * Display the logical drive number for the device in question, if it a valid
- * logical drive. For physical devices, "-1" is returned
- * The logical drive number is displayed in following format
+ * logical drive. For physical devices, "-1" is returned.
+ *
+ * The logical drive number is displayed in following format:
  *
  * <SCSI ID> <LD NUM> <LD STICKY ID> <APP ADAPTER HANDLE>
- *   <int>     <int>       <int>            <int>
  *
- * @param dev	: device object representation for the scsi device
- * @param buf	: buffer to send data to
+ *   <int>     <int>       <int>            <int>
  */
 static ssize_t
 megaraid_sysfs_show_ldnum(struct device *dev, struct device_attribute *attr, char *buf)
diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h
index 2b5a3285f799..9de803cebd4b 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.h
+++ b/drivers/scsi/megaraid/megaraid_mbox.h
@@ -21,8 +21,8 @@
 #include "megaraid_ioctl.h"
 
 
-#define MEGARAID_VERSION	"2.20.4.9"
-#define MEGARAID_EXT_VERSION	"(Release Date: Sun Jul 16 12:27:22 EST 2006)"
+#define MEGARAID_VERSION	"2.20.5.1"
+#define MEGARAID_EXT_VERSION	"(Release Date: Thu Nov 16 15:32:35 EST 2006)"
 
 
 /*
@@ -146,27 +146,27 @@ typedef struct {
 
 /**
  * mraid_device_t - adapter soft state structure for mailbox controllers
- * @param una_mbox64		: 64-bit mbox - unaligned
- * @param una_mbox64_dma	: mbox dma addr - unaligned
- * @param mbox			: 32-bit mbox - aligned
- * @param mbox64		: 64-bit mbox - aligned
- * @param mbox_dma		: mbox dma addr - aligned
- * @param mailbox_lock		: exclusion lock for the mailbox
- * @param baseport		: base port of hba memory
- * @param baseaddr		: mapped addr of hba memory
- * @param mbox_pool		: pool of mailboxes
- * @param mbox_pool_handle	: handle for the mailbox pool memory
- * @param epthru_pool		: a pool for extended passthru commands
- * @param epthru_pool_handle	: handle to the pool above
- * @param sg_pool		: pool of scatter-gather lists for this driver
- * @param sg_pool_handle	: handle to the pool above
- * @param ccb_list		: list of our command control blocks
- * @param uccb_list		: list of cmd control blocks for mgmt module
- * @param umbox64		: array of mailbox for user commands (cmm)
- * @param pdrv_state		: array for state of each physical drive.
- * @param last_disp		: flag used to show device scanning
- * @param hw_error		: set if FW not responding
- * @param fast_load		: If set, skip physical device scanning
+ * @una_mbox64			: 64-bit mbox - unaligned
+ * @una_mbox64_dma		: mbox dma addr - unaligned
+ * @mbox			: 32-bit mbox - aligned
+ * @mbox64			: 64-bit mbox - aligned
+ * @mbox_dma			: mbox dma addr - aligned
+ * @mailbox_lock		: exclusion lock for the mailbox
+ * @baseport			: base port of hba memory
+ * @baseaddr			: mapped addr of hba memory
+ * @mbox_pool			: pool of mailboxes
+ * @mbox_pool_handle		: handle for the mailbox pool memory
+ * @epthru_pool			: a pool for extended passthru commands
+ * @epthru_pool_handle		: handle to the pool above
+ * @sg_pool			: pool of scatter-gather lists for this driver
+ * @sg_pool_handle		: handle to the pool above
+ * @ccb_list			: list of our command control blocks
+ * @uccb_list			: list of cmd control blocks for mgmt module
+ * @umbox64			: array of mailbox for user commands (cmm)
+ * @pdrv_state			: array for state of each physical drive.
+ * @last_disp			: flag used to show device scanning
+ * @hw_error			: set if FW not responding
+ * @fast_load			: If set, skip physical device scanning
  * @channel_class		: channel class, RAID or SCSI
  * @sysfs_sem			: semaphore to serialize access to sysfs res.
  * @sysfs_uioc			: management packet to issue FW calls from sysfs
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index d85b9a8f1b8d..c1ff20c4747d 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -78,10 +78,10 @@ static struct file_operations lsi_fops = {
 
 /**
  * mraid_mm_open - open routine for char node interface
- * @inod	: unused
+ * @inode	: unused
  * @filep	: unused
  *
- * allow ioctl operations by apps only if they superuser privilege
+ * Allow ioctl operations by apps only if they have superuser privilege.
  */
 static int
 mraid_mm_open(struct inode *inode, struct file *filep)
@@ -214,7 +214,9 @@ mraid_mm_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
 /**
  * mraid_mm_get_adapter - Returns corresponding adapters for the mimd packet
  * @umimd	: User space mimd_t ioctl packet
- * @adapter	: pointer to the adapter (OUT)
+ * @rval	: returned success/error status
+ *
+ * The function return value is a pointer to the located @adapter.
  */
 static mraid_mmadp_t *
 mraid_mm_get_adapter(mimd_t __user *umimd, int *rval)
@@ -252,11 +254,11 @@ mraid_mm_get_adapter(mimd_t __user *umimd, int *rval)
 	return adapter;
 }
 
-/*
- * handle_drvrcmd - This routine checks if the opcode is a driver
- * 			  cmd and if it is, handles it.
+/**
+ * handle_drvrcmd - Checks if the opcode is a driver cmd and if it is, handles it.
  * @arg		: packet sent by the user app
  * @old_ioctl	: mimd if 1; uioc otherwise
+ * @rval	: pointer for command's returned value (not function status)
  */
 static int
 handle_drvrcmd(void __user *arg, uint8_t old_ioctl, int *rval)
@@ -322,8 +324,8 @@ old_packet:
 
 /**
  * mimd_to_kioc	- Converter from old to new ioctl format
- *
  * @umimd	: user space old MIMD IOCTL
+ * @adp		: adapter softstate
  * @kioc	: kernel space new format IOCTL
  *
  * Routine to convert MIMD interface IOCTL to new interface IOCTL packet. The
@@ -474,7 +476,6 @@ mimd_to_kioc(mimd_t __user *umimd, mraid_mmadp_t *adp, uioc_t *kioc)
 
 /**
  * mraid_mm_attch_buf - Attach a free dma buffer for required size
- *
  * @adp		: Adapter softstate
  * @kioc	: kioc that the buffer needs to be attached to
  * @xferlen	: required length for buffer
@@ -607,7 +608,6 @@ mraid_mm_alloc_kioc(mraid_mmadp_t *adp)
 
 /**
  * mraid_mm_dealloc_kioc - Return kioc to free pool
- *
  * @adp		: Adapter softstate
  * @kioc	: uioc_t node to be returned to free pool
  */
@@ -652,7 +652,6 @@ mraid_mm_dealloc_kioc(mraid_mmadp_t *adp, uioc_t *kioc)
 
 /**
  * lld_ioctl - Routine to issue ioctl to low level drvr
- *
  * @adp		: The adapter handle
  * @kioc	: The ioctl packet with kernel addresses
  */
@@ -705,7 +704,6 @@ lld_ioctl(mraid_mmadp_t *adp, uioc_t *kioc)
 
 /**
  * ioctl_done - callback from the low level driver
- *
  * @kioc	: completed ioctl packet
  */
 static void
@@ -756,9 +754,8 @@ ioctl_done(uioc_t *kioc)
 }
 
 
-/*
- * lld_timedout	: callback from the expired timer
- *
+/**
+ * lld_timedout	- callback from the expired timer
  * @ptr		: ioctl packet that timed out
  */
 static void
@@ -776,8 +773,7 @@ lld_timedout(unsigned long ptr)
 
 
 /**
- * kioc_to_mimd	: Converter from new back to old format
- *
+ * kioc_to_mimd	- Converter from new back to old format
  * @kioc	: Kernel space IOCTL packet (successfully issued)
  * @mimd	: User space MIMD packet
  */
@@ -855,7 +851,6 @@ kioc_to_mimd(uioc_t *kioc, mimd_t __user *mimd)
 
 /**
  * hinfo_to_cinfo - Convert new format hba info into old format
- *
  * @hinfo	: New format, more comprehensive adapter info
  * @cinfo	: Old format adapter info to support mimd_t apps
  */
@@ -878,10 +873,9 @@ hinfo_to_cinfo(mraid_hba_info_t *hinfo, mcontroller_t *cinfo)
 }
 
 
-/*
- * mraid_mm_register_adp - Registration routine for low level drvrs
- *
- * @adp	: Adapter objejct
+/**
+ * mraid_mm_register_adp - Registration routine for low level drivers
+ * @lld_adp	: Adapter objejct
  */
 int
 mraid_mm_register_adp(mraid_mmadp_t *lld_adp)
@@ -1007,15 +1001,14 @@ memalloc_error:
 
 /**
  * mraid_mm_adapter_app_handle - return the application handle for this adapter
+ * @unique_id	: adapter unique identifier
  *
- * For the given driver data, locate the adadpter in our global list and
+ * For the given driver data, locate the adapter in our global list and
  * return the corresponding handle, which is also used by applications to
  * uniquely identify an adapter.
  *
- * @param unique_id : adapter unique identifier
- *
- * @return adapter handle if found in the list
- * @return 0 if adapter could not be located, should never happen though
+ * Return adapter handle if found in the list.
+ * Return 0 if adapter could not be located, should never happen though.
  */
 uint32_t
 mraid_mm_adapter_app_handle(uint32_t unique_id)
@@ -1040,7 +1033,6 @@ mraid_mm_adapter_app_handle(uint32_t unique_id)
 
 /**
  * mraid_mm_setup_dma_pools - Set up dma buffer pools per adapter
- *
  * @adp	: Adapter softstate
  *
  * We maintain a pool of dma buffers per each adapter. Each pool has one
@@ -1093,11 +1085,11 @@ dma_pool_setup_error:
 }
 
 
-/*
+/**
  * mraid_mm_unregister_adp - Unregister routine for low level drivers
- *				  Assume no outstanding ioctls to llds.
- *
  * @unique_id	: UID of the adpater
+ *
+ * Assumes no outstanding ioctls to llds.
  */
 int
 mraid_mm_unregister_adp(uint32_t unique_id)
@@ -1131,7 +1123,6 @@ mraid_mm_unregister_adp(uint32_t unique_id)
 
 /**
  * mraid_mm_free_adp_resources - Free adapter softstate
- *
  * @adp	: Adapter softstate
  */
 static void
@@ -1162,7 +1153,6 @@ mraid_mm_free_adp_resources(mraid_mmadp_t *adp)
 
 /**
  * mraid_mm_teardown_dma_pools - Free all per adapter dma buffers
- *
  * @adp	: Adapter softstate
  */
 static void
@@ -1190,7 +1180,7 @@ mraid_mm_teardown_dma_pools(mraid_mmadp_t *adp)
 }
 
 /**
- * mraid_mm_init	: Module entry point
+ * mraid_mm_init	- Module entry point
  */
 static int __init
 mraid_mm_init(void)
@@ -1214,10 +1204,13 @@ mraid_mm_init(void)
 }
 
 
+#ifdef CONFIG_COMPAT
 /**
- * mraid_mm_compat_ioctl	: 32bit to 64bit ioctl conversion routine
+ * mraid_mm_compat_ioctl	- 32bit to 64bit ioctl conversion routine
+ * @filep	: file operations pointer (ignored)
+ * @cmd		: ioctl command
+ * @arg		: user ioctl packet
  */
-#ifdef CONFIG_COMPAT
 static long
 mraid_mm_compat_ioctl(struct file *filep, unsigned int cmd,
 		      unsigned long arg)
@@ -1231,7 +1224,7 @@ mraid_mm_compat_ioctl(struct file *filep, unsigned int cmd,
 #endif
 
 /**
- * mraid_mm_exit	: Module exit point
+ * mraid_mm_exit	- Module exit point
  */
 static void __exit
 mraid_mm_exit(void)
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 55eddcf8eb15..cacb3ad92527 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -15,7 +15,7 @@
 #ifndef LSI_MEGARAID_SAS_H
 #define LSI_MEGARAID_SAS_H
 
-/**
+/*
  * MegaRAID SAS Driver meta data
  */
 #define MEGASAS_VERSION				"00.00.03.05"
@@ -40,7 +40,7 @@
  * "message frames"
  */
 
-/**
+/*
  * FW posts its state in upper 4 bits of outbound_msg_0 register
  */
 #define MFI_STATE_MASK				0xF0000000
@@ -58,7 +58,7 @@
 
 #define MEGAMFI_FRAME_SIZE			64
 
-/**
+/*
  * During FW init, clear pending cmds & reset state using inbound_msg_0
  *
  * ABORT	: Abort all pending cmds
@@ -78,7 +78,7 @@
 						MFI_INIT_MFIMODE| \
 						MFI_INIT_ABORT
 
-/**
+/*
  * MFI frame flags
  */
 #define MFI_FRAME_POST_IN_REPLY_QUEUE		0x0000
@@ -92,12 +92,12 @@
 #define MFI_FRAME_DIR_READ			0x0010
 #define MFI_FRAME_DIR_BOTH			0x0018
 
-/**
+/*
  * Definition for cmd_status
  */
 #define MFI_CMD_STATUS_POLL_MODE		0xFF
 
-/**
+/*
  * MFI command opcodes
  */
 #define MFI_CMD_INIT				0x00
@@ -128,7 +128,7 @@
 #define MR_DCMD_CLUSTER_RESET_ALL		0x08010100
 #define MR_DCMD_CLUSTER_RESET_LD		0x08010200
 
-/**
+/*
  * MFI command completion codes
  */
 enum MFI_STAT {
diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h
index 625ca97da52d..9102cbdf1359 100644
--- a/drivers/scsi/pcmcia/nsp_cs.h
+++ b/drivers/scsi/pcmcia/nsp_cs.h
@@ -290,7 +290,6 @@ typedef struct _nsp_hw_data {
 #endif
 } nsp_hw_data;
 
-
 /****************************************************************************
  *
  */
@@ -302,22 +301,13 @@ static int        nsp_cs_config (struct pcmcia_device *link);
 
 /* Linux SCSI subsystem specific functions */
 static struct Scsi_Host *nsp_detect     (struct scsi_host_template *sht);
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-static        int        nsp_detect_old (struct scsi_host_template *sht);
-static        int        nsp_release_old(struct Scsi_Host *shpnt);
-#endif
 static const  char      *nsp_info       (struct Scsi_Host *shpnt);
 static        int        nsp_proc_info  (
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
 	                                 struct Scsi_Host *host,
-#endif
 					 char   *buffer,
 					 char  **start,
 					 off_t   offset,
 					 int     length,
-#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
-					 int     hostno,
-#endif
 					 int     inout);
 static int nsp_queuecommand(struct scsi_cmnd *SCpnt,
 			    void (* done)(struct scsi_cmnd *SCpnt));
@@ -356,7 +346,6 @@ static struct Scsi_Host *nsp_detect(struct scsi_host_template *sht);
 static int  __init nsp_cs_init(void);
 static void __exit nsp_cs_exit(void);
 
-
 /* Debug */
 #ifdef NSP_DEBUG
 static void show_command (struct scsi_cmnd *SCpnt);
@@ -401,7 +390,6 @@ enum _burst_mode {
 	BURST_MEM32 = 2,
 };
 
-
 /**************************************************************************
  * SCSI messaage
  */
@@ -413,62 +401,8 @@ enum _burst_mode {
 
 #define MSG_EXT_SDTR         0x01
 
-
-/**************************************************************************
- * Compatibility functions
- */
-
-/* for Kernel 2.4 */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
-#  define scsi_register_host(template)   scsi_register_module(MODULE_SCSI_HA, template)
-#  define scsi_unregister_host(template) scsi_unregister_module(MODULE_SCSI_HA, template)
-#  define scsi_host_put(host)            scsi_unregister(host)
-
-typedef void irqreturn_t;
-#  define IRQ_NONE      /* */
-#  define IRQ_HANDLED   /* */
-#  define IRQ_RETVAL(x) /* */
-
-/* This is ad-hoc version of scsi_host_get_next() */
-static inline struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *host)
-{
-	if (host == NULL) {
-		return scsi_hostlist;
-	} else {
-		return host->next;
-	}
-}
-
-/* This is ad-hoc version of scsi_host_hn_get() */
-static inline struct Scsi_Host *scsi_host_hn_get(unsigned short hostno)
-{
-	struct Scsi_Host *host;
-
-	for (host = scsi_host_get_next(NULL); host != NULL;
-	     host = scsi_host_get_next(host)) {
-		if (host->host_no == hostno) {
-			break;
-		}
-	}
-
-	return host;
-}
-
-static void cs_error(struct pcmcia_device *handle, int func, int ret)
-{
-	error_info_t err = { func, ret };
-	pcmcia_report_error(handle, &err);
-}
-
-/* scatter-gather table */
-#  define BUFFER_ADDR (SCpnt->SCp.buffer->address)
-#endif
-
-/* for Kernel 2.6 */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
 /* scatter-gather table */
 #  define BUFFER_ADDR ((char *)((unsigned int)(SCpnt->SCp.buffer->page) + SCpnt->SCp.buffer->offset))
-#endif
 
 #endif  /*__nsp_cs__*/
 /* end */
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 7b18a6c7b7eb..8081b637d97e 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -140,6 +140,8 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off,
 	ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count);
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
+	set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+
 	return (count);
 }
 
@@ -653,6 +655,43 @@ qla2x00_beacon_store(struct class_device *cdev, const char *buf,
 	return count;
 }
 
+static ssize_t
+qla2x00_optrom_bios_version_show(struct class_device *cdev, char *buf)
+{
+	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+
+	return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1],
+	    ha->bios_revision[0]);
+}
+
+static ssize_t
+qla2x00_optrom_efi_version_show(struct class_device *cdev, char *buf)
+{
+	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+
+	return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1],
+	    ha->efi_revision[0]);
+}
+
+static ssize_t
+qla2x00_optrom_fcode_version_show(struct class_device *cdev, char *buf)
+{
+	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+
+	return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fcode_revision[1],
+	    ha->fcode_revision[0]);
+}
+
+static ssize_t
+qla2x00_optrom_fw_version_show(struct class_device *cdev, char *buf)
+{
+	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
+
+	return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d %d\n",
+	    ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2],
+	    ha->fw_revision[3]);
+}
+
 static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show,
 	NULL);
 static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
@@ -669,6 +708,14 @@ static CLASS_DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show,
     qla2x00_zio_timer_store);
 static CLASS_DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show,
     qla2x00_beacon_store);
+static CLASS_DEVICE_ATTR(optrom_bios_version, S_IRUGO,
+    qla2x00_optrom_bios_version_show, NULL);
+static CLASS_DEVICE_ATTR(optrom_efi_version, S_IRUGO,
+    qla2x00_optrom_efi_version_show, NULL);
+static CLASS_DEVICE_ATTR(optrom_fcode_version, S_IRUGO,
+    qla2x00_optrom_fcode_version_show, NULL);
+static CLASS_DEVICE_ATTR(optrom_fw_version, S_IRUGO,
+    qla2x00_optrom_fw_version_show, NULL);
 
 struct class_device_attribute *qla2x00_host_attrs[] = {
 	&class_device_attr_driver_version,
@@ -683,6 +730,10 @@ struct class_device_attribute *qla2x00_host_attrs[] = {
 	&class_device_attr_zio,
 	&class_device_attr_zio_timer,
 	&class_device_attr_beacon,
+	&class_device_attr_optrom_bios_version,
+	&class_device_attr_optrom_efi_version,
+	&class_device_attr_optrom_fcode_version,
+	&class_device_attr_optrom_fw_version,
 	NULL,
 };
 
@@ -836,21 +887,24 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
 	link_stat_t stat_buf;
 	struct fc_host_statistics *pfc_host_stat;
 
+	rval = QLA_FUNCTION_FAILED;
 	pfc_host_stat = &ha->fc_host_stat;
 	memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics));
 
 	if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
 		rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf,
 		    sizeof(stat_buf) / 4, mb_stat);
-	} else {
+	} else if (atomic_read(&ha->loop_state) == LOOP_READY &&
+		    !test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) &&
+		    !test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) &&
+		    !ha->dpc_active) {
+		/* Must be in a 'READY' state for statistics retrieval. */
 		rval = qla2x00_get_link_status(ha, ha->loop_id, &stat_buf,
 		    mb_stat);
 	}
-	if (rval != 0) {
-		qla_printk(KERN_WARNING, ha,
-		    "Unable to retrieve host statistics (%d).\n", mb_stat[0]);
-		return pfc_host_stat;
-	}
+
+	if (rval != QLA_SUCCESS)
+		goto done;
 
 	pfc_host_stat->link_failure_count = stat_buf.link_fail_cnt;
 	pfc_host_stat->loss_of_sync_count = stat_buf.loss_sync_cnt;
@@ -858,7 +912,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
 	pfc_host_stat->prim_seq_protocol_err_count = stat_buf.prim_seq_err_cnt;
 	pfc_host_stat->invalid_tx_word_count = stat_buf.inval_xmit_word_cnt;
 	pfc_host_stat->invalid_crc_count = stat_buf.inval_crc_cnt;
-
+done:
 	return pfc_host_stat;
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 2c10130d9e03..05f4f2a378eb 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2045,6 +2045,29 @@ struct isp_operations {
 		uint32_t, uint32_t);
 	int (*write_optrom) (struct scsi_qla_host *, uint8_t *, uint32_t,
 		uint32_t);
+
+	int (*get_flash_version) (struct scsi_qla_host *, void *);
+};
+
+/* MSI-X Support *************************************************************/
+
+#define QLA_MSIX_CHIP_REV_24XX	3
+#define QLA_MSIX_FW_MODE(m)	(((m) & (BIT_7|BIT_8|BIT_9)) >> 7)
+#define QLA_MSIX_FW_MODE_1(m)	(QLA_MSIX_FW_MODE(m) == 1)
+
+#define QLA_MSIX_DEFAULT	0x00
+#define QLA_MSIX_RSP_Q		0x01
+
+#define QLA_MSIX_ENTRIES	2
+#define QLA_MIDX_DEFAULT	0
+#define QLA_MIDX_RSP_Q		1
+
+struct scsi_qla_host;
+
+struct qla_msix_entry {
+	int have_irq;
+	uint16_t msix_vector;
+	uint16_t msix_entry;
 };
 
 /*
@@ -2077,6 +2100,7 @@ typedef struct scsi_qla_host {
 		uint32_t	enable_lip_full_login	:1;
 		uint32_t	enable_target_reset	:1;
 		uint32_t	enable_led_scheme	:1;
+		uint32_t	inta_enabled		:1;
 		uint32_t	msi_enabled		:1;
 		uint32_t	msix_enabled		:1;
 		uint32_t	disable_serdes		:1;
@@ -2316,8 +2340,6 @@ typedef struct scsi_qla_host {
 #define MBX_INTR_WAIT	2
 #define MBX_UPDATE_FLASH_ACTIVE	3
 
-	spinlock_t	mbx_reg_lock;   /* Mbx Cmd Register Lock */
-
 	struct semaphore mbx_cmd_sem;	/* Serialialize mbx access */
 	struct semaphore mbx_intr_sem;  /* Used for completion notification */
 
@@ -2358,6 +2380,7 @@ typedef struct scsi_qla_host {
 
 	uint8_t		host_str[16];
 	uint32_t	pci_attr;
+	uint16_t	chip_revision;
 
 	uint16_t	product_id[4];
 
@@ -2379,6 +2402,15 @@ typedef struct scsi_qla_host {
 #define QLA_SREADING	1
 #define QLA_SWRITING	2
 
+        /* PCI expansion ROM image information. */
+#define ROM_CODE_TYPE_BIOS	0
+#define ROM_CODE_TYPE_FCODE	1
+#define ROM_CODE_TYPE_EFI	3
+	uint8_t		bios_revision[2];
+	uint8_t		efi_revision[2];
+	uint8_t		fcode_revision[16];
+	uint32_t	fw_revision[4];
+
 	/* Needed for BEACON */
 	uint16_t	beacon_blink_led;
 	uint8_t		beacon_color_state;
@@ -2391,6 +2423,8 @@ typedef struct scsi_qla_host {
 	uint16_t	zio_mode;
 	uint16_t	zio_timer;
 	struct fc_host_statistics fc_host_stat;
+
+	struct qla_msix_entry msix_entries[QLA_MSIX_ENTRIES];
 } scsi_qla_host_t;
 
 
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index e4dd12f4b80e..74544ae4b0e2 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -224,6 +224,9 @@ extern irqreturn_t qla24xx_intr_handler(int, void *);
 extern void qla2x00_process_response_queue(struct scsi_qla_host *);
 extern void qla24xx_process_response_queue(struct scsi_qla_host *);
 
+extern int qla2x00_request_irqs(scsi_qla_host_t *);
+extern void qla2x00_free_irqs(scsi_qla_host_t *);
+
 /*
  * Global Function Prototypes in qla_sup.c source file.
  */
@@ -259,6 +262,9 @@ extern uint8_t *qla24xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
 extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *,
     uint32_t, uint32_t);
 
+extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *);
+extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *);
+
 /*
  * Global Function Prototypes in qla_dbg.c source file.
  */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index b3dac26ddba3..98c01cd5e1a8 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -65,7 +65,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
 	ha->flags.reset_active = 0;
 	atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
 	atomic_set(&ha->loop_state, LOOP_DOWN);
-	ha->device_flags = 0;
+	ha->device_flags = DFLG_NO_CABLE;
 	ha->dpc_flags = 0;
 	ha->flags.management_server_logged_in = 0;
 	ha->marker_needed = 0;
@@ -77,16 +77,23 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
 	qla_printk(KERN_INFO, ha, "Configuring PCI space...\n");
 	rval = ha->isp_ops.pci_config(ha);
 	if (rval) {
-		DEBUG2(printk("scsi(%ld): Unable to configure PCI space=n",
+		DEBUG2(printk("scsi(%ld): Unable to configure PCI space.\n",
 		    ha->host_no));
 		return (rval);
 	}
 
 	ha->isp_ops.reset_chip(ha);
 
+	ha->isp_ops.get_flash_version(ha, ha->request_ring);
+
 	qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n");
 
-	ha->isp_ops.nvram_config(ha);
+	rval = ha->isp_ops.nvram_config(ha);
+	if (rval) {
+		DEBUG2(printk("scsi(%ld): Unable to verify NVRAM data.\n",
+		    ha->host_no));
+		return rval;
+	}
 
 	if (ha->flags.disable_serdes) {
 		/* Mask HBA via NVRAM settings? */
@@ -293,6 +300,8 @@ qla24xx_pci_config(scsi_qla_host_t *ha)
 	d &= ~PCI_ROM_ADDRESS_ENABLE;
 	pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
 
+	pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->chip_revision);
+
 	/* Get PCI bus information. */
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 	ha->pci_attr = RD_REG_DWORD(&reg->ctrl_status);
@@ -1351,6 +1360,39 @@ qla2x00_configure_hba(scsi_qla_host_t *ha)
 	return(rval);
 }
 
+static inline void
+qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *def)
+{
+	char *st, *en;
+	uint16_t index;
+
+	if (memcmp(model, BINZERO, len) != 0) {
+		strncpy(ha->model_number, model, len);
+		st = en = ha->model_number;
+		en += len - 1;
+		while (en > st) {
+			if (*en != 0x20 && *en != 0x00)
+				break;
+			*en-- = '\0';
+		}
+
+		index = (ha->pdev->subsystem_device & 0xff);
+		if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
+		    index < QLA_MODEL_NAMES)
+			ha->model_desc = qla2x00_model_name[index * 2 + 1];
+	} else {
+		index = (ha->pdev->subsystem_device & 0xff);
+		if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
+		    index < QLA_MODEL_NAMES) {
+			strcpy(ha->model_number,
+			    qla2x00_model_name[index * 2]);
+			ha->model_desc = qla2x00_model_name[index * 2 + 1];
+		} else {
+			strcpy(ha->model_number, def);
+		}
+	}
+}
+
 /*
 * NVRAM configuration for ISP 2xxx
 *
@@ -1367,7 +1409,6 @@ qla2x00_configure_hba(scsi_qla_host_t *ha)
 int
 qla2x00_nvram_config(scsi_qla_host_t *ha)
 {
-	int             rval;
 	uint8_t         chksum = 0;
 	uint16_t        cnt;
 	uint8_t         *dptr1, *dptr2;
@@ -1376,8 +1417,6 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
 	uint8_t         *ptr = (uint8_t *)ha->request_ring;
 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
 
-	rval = QLA_SUCCESS;
-
 	/* Determine NVRAM starting address. */
 	ha->nvram_size = sizeof(nvram_t);
 	ha->nvram_base = 0;
@@ -1401,55 +1440,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
 		qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
 		    "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
 		    nv->nvram_version);
-		qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
-		    "invalid -- WWPN) defaults.\n");
-
-		/*
-		 * Set default initialization control block.
-		 */
-		memset(nv, 0, ha->nvram_size);
-		nv->parameter_block_version = ICB_VERSION;
-
-		if (IS_QLA23XX(ha)) {
-			nv->firmware_options[0] = BIT_2 | BIT_1;
-			nv->firmware_options[1] = BIT_7 | BIT_5;
-			nv->add_firmware_options[0] = BIT_5;
-			nv->add_firmware_options[1] = BIT_5 | BIT_4;
-			nv->frame_payload_size = __constant_cpu_to_le16(2048);
-			nv->special_options[1] = BIT_7;
-		} else if (IS_QLA2200(ha)) {
-			nv->firmware_options[0] = BIT_2 | BIT_1;
-			nv->firmware_options[1] = BIT_7 | BIT_5;
-			nv->add_firmware_options[0] = BIT_5;
-			nv->add_firmware_options[1] = BIT_5 | BIT_4;
-			nv->frame_payload_size = __constant_cpu_to_le16(1024);
-		} else if (IS_QLA2100(ha)) {
-			nv->firmware_options[0] = BIT_3 | BIT_1;
-			nv->firmware_options[1] = BIT_5;
-			nv->frame_payload_size = __constant_cpu_to_le16(1024);
-		}
-
-		nv->max_iocb_allocation = __constant_cpu_to_le16(256);
-		nv->execution_throttle = __constant_cpu_to_le16(16);
-		nv->retry_count = 8;
-		nv->retry_delay = 1;
-
-		nv->port_name[0] = 33;
-		nv->port_name[3] = 224;
-		nv->port_name[4] = 139;
-
-		nv->login_timeout = 4;
-
-		/*
-		 * Set default host adapter parameters
-		 */
-		nv->host_p[1] = BIT_2;
-		nv->reset_delay = 5;
-		nv->port_down_retry_count = 8;
-		nv->max_luns_per_target = __constant_cpu_to_le16(8);
-		nv->link_down_timeout = 60;
-
-		rval = 1;
+		return QLA_FUNCTION_FAILED;
 	}
 
 #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
@@ -1489,33 +1480,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
 				strcpy(ha->model_number, "QLA2300");
 			}
 		} else {
-			if (rval == 0 &&
-			    memcmp(nv->model_number, BINZERO,
-				    sizeof(nv->model_number)) != 0) {
-				char *st, *en;
-
-				strncpy(ha->model_number, nv->model_number,
-				    sizeof(nv->model_number));
-				st = en = ha->model_number;
-				en += sizeof(nv->model_number) - 1;
-				while (en > st) {
-					if (*en != 0x20 && *en != 0x00)
-						break;
-					*en-- = '\0';
-				}
-			} else {
-				uint16_t        index;
-
-				index = (ha->pdev->subsystem_device & 0xff);
-				if (index < QLA_MODEL_NAMES) {
-					strcpy(ha->model_number,
-					    qla2x00_model_name[index * 2]);
-					ha->model_desc =
-					    qla2x00_model_name[index * 2 + 1];
-				} else {
-					strcpy(ha->model_number, "QLA23xx");
-				}
-			}
+			qla2x00_set_model_info(ha, nv->model_number,
+			    sizeof(nv->model_number), "QLA23xx");
 		}
 	} else if (IS_QLA2200(ha)) {
 		nv->firmware_options[0] |= BIT_2;
@@ -1687,11 +1653,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
 		}
 	}
 
-	if (rval) {
-		DEBUG2_3(printk(KERN_WARNING
-		    "scsi(%ld): NVRAM configuration failed!\n", ha->host_no));
-	}
-	return (rval);
+	return QLA_SUCCESS;
 }
 
 static void
@@ -3107,7 +3069,11 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
 		}
 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
-		ha->isp_ops.nvram_config(ha);
+		ha->isp_ops.get_flash_version(ha, ha->request_ring);
+
+		rval = ha->isp_ops.nvram_config(ha);
+		if (rval)
+			goto isp_abort_retry;
 
 		if (!qla2x00_restart_isp(ha)) {
 			clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
@@ -3137,6 +3103,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
 				}
 			}
 		} else {	/* failed the ISP abort */
+isp_abort_retry:
 			ha->flags.online = 1;
 			if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) {
 				if (ha->isp_abort_cnt == 0) {
@@ -3326,7 +3293,6 @@ qla24xx_reset_adapter(scsi_qla_host_t *ha)
 int
 qla24xx_nvram_config(scsi_qla_host_t *ha)
 {
-	int   rval;
 	struct init_cb_24xx *icb;
 	struct nvram_24xx *nv;
 	uint32_t *dptr;
@@ -3334,7 +3300,6 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
 	uint32_t chksum;
 	uint16_t cnt;
 
-	rval = QLA_SUCCESS;
 	icb = (struct init_cb_24xx *)ha->init_cb;
 	nv = (struct nvram_24xx *)ha->request_ring;
 
@@ -3367,51 +3332,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
 		qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
 		    "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
 		    le16_to_cpu(nv->nvram_version));
-		qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
-		    "invalid -- WWPN) defaults.\n");
-
-		/*
-		 * Set default initialization control block.
-		 */
-		memset(nv, 0, ha->nvram_size);
-		nv->nvram_version = __constant_cpu_to_le16(ICB_VERSION);
-		nv->version = __constant_cpu_to_le16(ICB_VERSION);
-		nv->frame_payload_size = __constant_cpu_to_le16(2048);
-		nv->execution_throttle = __constant_cpu_to_le16(0xFFFF);
-		nv->exchange_count = __constant_cpu_to_le16(0);
-		nv->hard_address = __constant_cpu_to_le16(124);
-		nv->port_name[0] = 0x21;
-		nv->port_name[1] = 0x00 + PCI_FUNC(ha->pdev->devfn);
-		nv->port_name[2] = 0x00;
-		nv->port_name[3] = 0xe0;
-		nv->port_name[4] = 0x8b;
-		nv->port_name[5] = 0x1c;
-		nv->port_name[6] = 0x55;
-		nv->port_name[7] = 0x86;
-		nv->node_name[0] = 0x20;
-		nv->node_name[1] = 0x00;
-		nv->node_name[2] = 0x00;
-		nv->node_name[3] = 0xe0;
-		nv->node_name[4] = 0x8b;
-		nv->node_name[5] = 0x1c;
-		nv->node_name[6] = 0x55;
-		nv->node_name[7] = 0x86;
-		nv->login_retry_count = __constant_cpu_to_le16(8);
-		nv->interrupt_delay_timer = __constant_cpu_to_le16(0);
-		nv->login_timeout = __constant_cpu_to_le16(0);
-		nv->firmware_options_1 =
-		    __constant_cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1);
-		nv->firmware_options_2 = __constant_cpu_to_le32(2 << 4);
-		nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12);
-		nv->firmware_options_3 = __constant_cpu_to_le32(2 << 13);
-		nv->host_p = __constant_cpu_to_le32(BIT_11|BIT_10);
-		nv->efi_parameters = __constant_cpu_to_le32(0);
-		nv->reset_delay = 5;
-		nv->max_luns_per_target = __constant_cpu_to_le16(128);
-		nv->port_down_retry_count = __constant_cpu_to_le16(30);
-		nv->link_down_timeout = __constant_cpu_to_le16(30);
-
-		rval = 1;
+		return QLA_FUNCTION_FAILED;
 	}
 
 	/* Reset Initialization control block */
@@ -3438,25 +3359,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
 	/*
 	 * Setup driver NVRAM options.
 	 */
-	if (memcmp(nv->model_name, BINZERO, sizeof(nv->model_name)) != 0) {
-		char *st, *en;
-		uint16_t index;
-
-		strncpy(ha->model_number, nv->model_name,
-		    sizeof(nv->model_name));
-		st = en = ha->model_number;
-		en += sizeof(nv->model_name) - 1;
-		while (en > st) {
-			if (*en != 0x20 && *en != 0x00)
-				break;
-			*en-- = '\0';
-		}
-
-		index = (ha->pdev->subsystem_device & 0xff);
-		if (index < QLA_MODEL_NAMES)
-			ha->model_desc = qla2x00_model_name[index * 2 + 1];
-	} else
-		strcpy(ha->model_number, "QLA2462");
+	qla2x00_set_model_info(ha, nv->model_name, sizeof(nv->model_name),
+	    "QLA2462");
 
 	/* Use alternate WWN? */
 	if (nv->host_p & __constant_cpu_to_le32(BIT_15)) {
@@ -3575,11 +3479,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
 		ha->flags.process_response_queue = 1;
 	}
 
-	if (rval) {
-		DEBUG2_3(printk(KERN_WARNING
-		    "scsi(%ld): NVRAM configuration failed!\n", ha->host_no));
-	}
-	return (rval);
+	return QLA_SUCCESS;
 }
 
 static int
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 39fd17b05be5..d4885616cd39 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -86,12 +86,8 @@ qla2100_intr_handler(int irq, void *dev_id)
 
 	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
 	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
-		spin_lock_irqsave(&ha->mbx_reg_lock, flags);
-
 		set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
 		up(&ha->mbx_intr_sem);
-
-		spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
 	}
 
 	return (IRQ_HANDLED);
@@ -199,12 +195,8 @@ qla2300_intr_handler(int irq, void *dev_id)
 
 	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
 	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
-		spin_lock_irqsave(&ha->mbx_reg_lock, flags);
-
 		set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
 		up(&ha->mbx_intr_sem);
-
-		spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
 	}
 
 	return (IRQ_HANDLED);
@@ -654,10 +646,8 @@ qla2x00_ramp_up_queue_depth(scsi_qla_host_t *ha, srb_t *sp)
 	    fcport->last_queue_full + ql2xqfullrampup * HZ))
 		return;
 
-	spin_unlock_irq(&ha->hardware_lock);
 	starget_for_each_device(sdev->sdev_target, fcport,
 	    qla2x00_adjust_sdev_qdepth_up);
-	spin_lock_irq(&ha->hardware_lock);
 }
 
 /**
@@ -927,10 +917,8 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
 
 			/* Adjust queue depth for all luns on the port. */
 			fcport->last_queue_full = jiffies;
-			spin_unlock_irq(&ha->hardware_lock);
 			starget_for_each_device(cp->device->sdev_target,
 			    fcport, qla2x00_adjust_sdev_qdepth_down);
-			spin_lock_irq(&ha->hardware_lock);
 			break;
 		}
 		if (lscsi_status != SS_CHECK_CONDITION)
@@ -995,6 +983,22 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
 		if (lscsi_status != 0) {
 			cp->result = DID_OK << 16 | lscsi_status;
 
+			if (lscsi_status == SAM_STAT_TASK_SET_FULL) {
+				DEBUG2(printk(KERN_INFO
+				    "scsi(%ld): QUEUE FULL status detected "
+				    "0x%x-0x%x.\n", ha->host_no, comp_status,
+				    scsi_status));
+
+				/*
+				 * Adjust queue depth for all luns on the
+				 * port.
+				 */
+				fcport->last_queue_full = jiffies;
+				starget_for_each_device(
+				    cp->device->sdev_target, fcport,
+				    qla2x00_adjust_sdev_qdepth_down);
+				break;
+			}
 			if (lscsi_status != SS_CHECK_CONDITION)
 				break;
 
@@ -1482,12 +1486,8 @@ qla24xx_intr_handler(int irq, void *dev_id)
 
 	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
 	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
-		spin_lock_irqsave(&ha->mbx_reg_lock, flags);
-
 		set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
 		up(&ha->mbx_intr_sem);
-
-		spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
 	}
 
 	return IRQ_HANDLED;
@@ -1536,3 +1536,216 @@ qla24xx_ms_entry(scsi_qla_host_t *ha, struct ct_entry_24xx *pkt)
 	qla2x00_sp_compl(ha, sp);
 }
 
+static irqreturn_t
+qla24xx_msix_rsp_q(int irq, void *dev_id)
+{
+	scsi_qla_host_t	*ha;
+	struct device_reg_24xx __iomem *reg;
+	unsigned long flags;
+
+	ha = dev_id;
+	reg = &ha->iobase->isp24;
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+
+	qla24xx_process_response_queue(ha);
+
+	WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
+	RD_REG_DWORD_RELAXED(&reg->hccr);
+
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
+qla24xx_msix_default(int irq, void *dev_id)
+{
+	scsi_qla_host_t	*ha;
+	struct device_reg_24xx __iomem *reg;
+	int		status;
+	unsigned long	flags;
+	unsigned long	iter;
+	uint32_t	stat;
+	uint32_t	hccr;
+	uint16_t	mb[4];
+
+	ha = dev_id;
+	reg = &ha->iobase->isp24;
+	status = 0;
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	for (iter = 50; iter--; ) {
+		stat = RD_REG_DWORD(&reg->host_status);
+		if (stat & HSRX_RISC_PAUSED) {
+			hccr = RD_REG_DWORD(&reg->hccr);
+
+			qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
+			    "Dumping firmware!\n", hccr);
+			ha->isp_ops.fw_dump(ha, 1);
+			set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+			break;
+		} else if ((stat & HSRX_RISC_INT) == 0)
+			break;
+
+		switch (stat & 0xff) {
+		case 0x1:
+		case 0x2:
+		case 0x10:
+		case 0x11:
+			qla24xx_mbx_completion(ha, MSW(stat));
+			status |= MBX_INTERRUPT;
+
+			break;
+		case 0x12:
+			mb[0] = MSW(stat);
+			mb[1] = RD_REG_WORD(&reg->mailbox1);
+			mb[2] = RD_REG_WORD(&reg->mailbox2);
+			mb[3] = RD_REG_WORD(&reg->mailbox3);
+			qla2x00_async_event(ha, mb);
+			break;
+		case 0x13:
+			qla24xx_process_response_queue(ha);
+			break;
+		default:
+			DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
+			    "(%d).\n",
+			    ha->host_no, stat & 0xff));
+			break;
+		}
+		WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
+		RD_REG_DWORD_RELAXED(&reg->hccr);
+	}
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
+	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
+		set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+		up(&ha->mbx_intr_sem);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/* Interrupt handling helpers. */
+
+struct qla_init_msix_entry {
+	uint16_t entry;
+	uint16_t index;
+	const char *name;
+	irqreturn_t (*handler)(int, void *);
+};
+
+static struct qla_init_msix_entry imsix_entries[QLA_MSIX_ENTRIES] = {
+	{ QLA_MSIX_DEFAULT, QLA_MIDX_DEFAULT,
+		"qla2xxx (default)", qla24xx_msix_default },
+
+	{ QLA_MSIX_RSP_Q, QLA_MIDX_RSP_Q,
+		"qla2xxx (rsp_q)", qla24xx_msix_rsp_q },
+};
+
+static void
+qla24xx_disable_msix(scsi_qla_host_t *ha)
+{
+	int i;
+	struct qla_msix_entry *qentry;
+
+	for (i = 0; i < QLA_MSIX_ENTRIES; i++) {
+		qentry = &ha->msix_entries[imsix_entries[i].index];
+		if (qentry->have_irq)
+			free_irq(qentry->msix_vector, ha);
+	}
+	pci_disable_msix(ha->pdev);
+}
+
+static int
+qla24xx_enable_msix(scsi_qla_host_t *ha)
+{
+	int i, ret;
+	struct msix_entry entries[QLA_MSIX_ENTRIES];
+	struct qla_msix_entry *qentry;
+
+	for (i = 0; i < QLA_MSIX_ENTRIES; i++)
+		entries[i].entry = imsix_entries[i].entry;
+
+	ret = pci_enable_msix(ha->pdev, entries, ARRAY_SIZE(entries));
+	if (ret) {
+		qla_printk(KERN_WARNING, ha,
+		    "MSI-X: Failed to enable support -- %d/%d\n",
+		    QLA_MSIX_ENTRIES, ret);
+		goto msix_out;
+	}
+	ha->flags.msix_enabled = 1;
+
+	for (i = 0; i < QLA_MSIX_ENTRIES; i++) {
+		qentry = &ha->msix_entries[imsix_entries[i].index];
+		qentry->msix_vector = entries[i].vector;
+		qentry->msix_entry = entries[i].entry;
+		qentry->have_irq = 0;
+		ret = request_irq(qentry->msix_vector,
+		    imsix_entries[i].handler, 0, imsix_entries[i].name, ha);
+		if (ret) {
+			qla_printk(KERN_WARNING, ha,
+			    "MSI-X: Unable to register handler -- %x/%d.\n",
+			    imsix_entries[i].index, ret);
+			qla24xx_disable_msix(ha);
+			goto msix_out;
+		}
+		qentry->have_irq = 1;
+	}
+
+msix_out:
+	return ret;
+}
+
+int
+qla2x00_request_irqs(scsi_qla_host_t *ha)
+{
+	int ret;
+
+	/* If possible, enable MSI-X. */
+	if (!IS_QLA2432(ha))
+		goto skip_msix;
+
+        if (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX ||
+	    !QLA_MSIX_FW_MODE_1(ha->fw_attributes)) {
+		DEBUG2(qla_printk(KERN_WARNING, ha,
+		    "MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n",
+		    ha->chip_revision, ha->fw_attributes));
+
+		goto skip_msix;
+	}
+
+	ret = qla24xx_enable_msix(ha);
+	if (!ret) {
+		DEBUG2(qla_printk(KERN_INFO, ha,
+		    "MSI-X: Enabled (0x%X, 0x%X).\n", ha->chip_revision,
+		    ha->fw_attributes));
+		return ret;
+	}
+	qla_printk(KERN_WARNING, ha,
+	    "MSI-X: Falling back-to INTa mode -- %d.\n", ret);
+skip_msix:
+	ret = request_irq(ha->pdev->irq, ha->isp_ops.intr_handler,
+	    IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha);
+	if (!ret) {
+		ha->flags.inta_enabled = 1;
+		ha->host->irq = ha->pdev->irq;
+	} else {
+		qla_printk(KERN_WARNING, ha,
+		    "Failed to reserve interrupt %d already in use.\n",
+		    ha->pdev->irq);
+	}
+
+	return ret;
+}
+
+void
+qla2x00_free_irqs(scsi_qla_host_t *ha)
+{
+
+	if (ha->flags.msix_enabled)
+		qla24xx_disable_msix(ha);
+	else if (ha->flags.inta_enabled)
+		free_irq(ha->host->irq, ha);
+}
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 077e5789beeb..83376f6ac3db 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -55,7 +55,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
 	uint16_t __iomem *optr;
 	uint32_t	cnt;
 	uint32_t	mboxes;
-	unsigned long	mbx_flags = 0;
 	unsigned long	wait_time;
 
 	rval = QLA_SUCCESS;
@@ -81,10 +80,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
 	/* Save mailbox command for debug */
 	ha->mcp = mcp;
 
-	/* Try to get mailbox register access */
-	if (!abort_active)
-		spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags);
-
 	DEBUG11(printk("scsi(%ld): prepare to issue mbox cmd=0x%x.\n",
 	    ha->host_no, mcp->mb[0]));
 
@@ -161,9 +156,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
 			WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT);
 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
-		if (!abort_active)
-			spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags);
-
 		/* Wait for either the timer to expire
 		 * or the mbox completion interrupt
 		 */
@@ -184,8 +176,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
 		else
 			WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT);
 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
-		if (!abort_active)
-			spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags);
 
 		wait_time = jiffies + mcp->tov * HZ; /* wait at most tov secs */
 		while (!ha->flags.mbox_int) {
@@ -201,9 +191,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
 		} /* while */
 	}
 
-	if (!abort_active)
-		spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags);
-
 	/* Check whether we timed out */
 	if (ha->flags.mbox_int) {
 		uint16_t *iptr2;
@@ -256,9 +243,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
 		rval = QLA_FUNCTION_TIMEOUT;
 	}
 
-	if (!abort_active)
-		spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags);
-
 	ha->flags.mbox_busy = 0;
 
 	/* Clean up */
@@ -1713,7 +1697,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
 	lg->entry_count = 1;
 	lg->nport_handle = cpu_to_le16(loop_id);
 	lg->control_flags =
-	    __constant_cpu_to_le16(LCF_COMMAND_LOGO|LCF_EXPL_LOGO);
+	    __constant_cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
 	lg->port_id[0] = al_pa;
 	lg->port_id[1] = area;
 	lg->port_id[2] = domain;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index d6445ae841ba..68f5d24b938b 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1485,6 +1485,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	ha->isp_ops.fw_dump		= qla2100_fw_dump;
 	ha->isp_ops.read_optrom		= qla2x00_read_optrom_data;
 	ha->isp_ops.write_optrom	= qla2x00_write_optrom_data;
+	ha->isp_ops.get_flash_version	= qla2x00_get_flash_version;
 	if (IS_QLA2100(ha)) {
 		host->max_id = MAX_TARGETS_2100;
 		ha->mbx_count = MAILBOX_REGISTER_COUNT_2100;
@@ -1550,6 +1551,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 		ha->isp_ops.beacon_on = qla24xx_beacon_on;
 		ha->isp_ops.beacon_off = qla24xx_beacon_off;
 		ha->isp_ops.beacon_blink = qla24xx_beacon_blink;
+		ha->isp_ops.get_flash_version = qla24xx_get_flash_version;
 		ha->gid_list_info_size = 8;
 		ha->optrom_size = OPTROM_SIZE_24XX;
 	}
@@ -1564,14 +1566,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	INIT_LIST_HEAD(&ha->list);
 	INIT_LIST_HEAD(&ha->fcports);
 
-	/*
-	 * These locks are used to prevent more than one CPU
-	 * from modifying the queue at the same time. The
-	 * higher level "host_lock" will reduce most
-	 * contention for these locks.
-	 */
-	spin_lock_init(&ha->mbx_reg_lock);
-
 	qla2x00_config_dma_addressing(ha);
 	if (qla2x00_mem_alloc(ha)) {
 		qla_printk(KERN_WARNING, ha,
@@ -1615,15 +1609,9 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	host->max_lun = MAX_LUNS;
 	host->transportt = qla2xxx_transport_template;
 
-	ret = request_irq(pdev->irq, ha->isp_ops.intr_handler,
-	    IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha);
-	if (ret) {
-		qla_printk(KERN_WARNING, ha,
-		    "Failed to reserve interrupt %d already in use.\n",
-		    pdev->irq);
+	ret = qla2x00_request_irqs(ha);
+	if (ret)
 		goto probe_failed;
-	}
-	host->irq = pdev->irq;
 
 	/* Initialized the timer */
 	qla2x00_start_timer(ha, qla2x00_timer, WATCH_INTERVAL);
@@ -1753,9 +1741,7 @@ qla2x00_free_device(scsi_qla_host_t *ha)
 
 	qla2x00_mem_free(ha);
 
-	/* Detach interrupts */
-	if (ha->host->irq)
-		free_irq(ha->host->irq, ha);
+	qla2x00_free_irqs(ha);
 
 	/* release io space registers  */
 	if (ha->iobase)
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 15390ad87456..ff1dd4175a7f 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -611,7 +611,6 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
 					    flash_conf_to_access_addr(0x0339),
 					    (fdata & 0xff00) | ((fdata << 16) &
 					    0xff0000) | ((fdata >> 16) & 0xff));
-				fdata = (faddr & sec_mask) << 2;
 				ret = qla24xx_write_flash_dword(ha, conf_addr,
 				    (fdata & 0xff00) |((fdata << 16) &
 				    0xff0000) | ((fdata >> 16) & 0xff));
@@ -1383,6 +1382,29 @@ qla2x00_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id,
 	qla2x00_write_flash_byte(ha, 0x5555, 0xf0);
 }
 
+static void
+qla2x00_read_flash_data(scsi_qla_host_t *ha, uint8_t *tmp_buf, uint32_t saddr,
+        uint32_t length)
+{
+	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+	uint32_t midpoint, ilength;
+	uint8_t data;
+
+	midpoint = length / 2;
+
+	WRT_REG_WORD(&reg->nvram, 0);
+	RD_REG_WORD(&reg->nvram);
+	for (ilength = 0; ilength < length; saddr++, ilength++, tmp_buf++) {
+		if (ilength == midpoint) {
+			WRT_REG_WORD(&reg->nvram, NVR_SELECT);
+			RD_REG_WORD(&reg->nvram);
+		}
+		data = qla2x00_read_flash_byte(ha, saddr);
+		if (saddr % 100)
+			udelay(10);
+		*tmp_buf = data;
+	}
+}
 
 static inline void
 qla2x00_suspend_hba(struct scsi_qla_host *ha)
@@ -1722,3 +1744,327 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
 
 	return rval;
 }
+
+/**
+ * qla2x00_get_fcode_version() - Determine an FCODE image's version.
+ * @ha: HA context
+ * @pcids: Pointer to the FCODE PCI data structure
+ *
+ * The process of retrieving the FCODE version information is at best
+ * described as interesting.
+ *
+ * Within the first 100h bytes of the image an ASCII string is present
+ * which contains several pieces of information including the FCODE
+ * version.  Unfortunately it seems the only reliable way to retrieve
+ * the version is by scanning for another sentinel within the string,
+ * the FCODE build date:
+ *
+ *	... 2.00.02 10/17/02 ...
+ *
+ * Returns QLA_SUCCESS on successful retrieval of version.
+ */
+static void
+qla2x00_get_fcode_version(scsi_qla_host_t *ha, uint32_t pcids)
+{
+	int ret = QLA_FUNCTION_FAILED;
+	uint32_t istart, iend, iter, vend;
+	uint8_t do_next, rbyte, *vbyte;
+
+	memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision));
+
+	/* Skip the PCI data structure. */
+	istart = pcids +
+	    ((qla2x00_read_flash_byte(ha, pcids + 0x0B) << 8) |
+		qla2x00_read_flash_byte(ha, pcids + 0x0A));
+	iend = istart + 0x100;
+	do {
+		/* Scan for the sentinel date string...eeewww. */
+		do_next = 0;
+		iter = istart;
+		while ((iter < iend) && !do_next) {
+			iter++;
+			if (qla2x00_read_flash_byte(ha, iter) == '/') {
+				if (qla2x00_read_flash_byte(ha, iter + 2) ==
+				    '/')
+					do_next++;
+				else if (qla2x00_read_flash_byte(ha,
+				    iter + 3) == '/')
+					do_next++;
+			}
+		}
+		if (!do_next)
+			break;
+
+		/* Backtrack to previous ' ' (space). */
+		do_next = 0;
+		while ((iter > istart) && !do_next) {
+			iter--;
+			if (qla2x00_read_flash_byte(ha, iter) == ' ')
+				do_next++;
+		}
+		if (!do_next)
+			break;
+
+		/*
+		 * Mark end of version tag, and find previous ' ' (space) or
+		 * string length (recent FCODE images -- major hack ahead!!!).
+		 */
+		vend = iter - 1;
+		do_next = 0;
+		while ((iter > istart) && !do_next) {
+			iter--;
+			rbyte = qla2x00_read_flash_byte(ha, iter);
+			if (rbyte == ' ' || rbyte == 0xd || rbyte == 0x10)
+				do_next++;
+		}
+		if (!do_next)
+			break;
+
+		/* Mark beginning of version tag, and copy data. */
+		iter++;
+		if ((vend - iter) &&
+		    ((vend - iter) < sizeof(ha->fcode_revision))) {
+			vbyte = ha->fcode_revision;
+			while (iter <= vend) {
+				*vbyte++ = qla2x00_read_flash_byte(ha, iter);
+				iter++;
+			}
+			ret = QLA_SUCCESS;
+		}
+	} while (0);
+
+	if (ret != QLA_SUCCESS)
+		memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision));
+}
+
+int
+qla2x00_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
+{
+	int ret = QLA_SUCCESS;
+	uint8_t code_type, last_image;
+	uint32_t pcihdr, pcids;
+	uint8_t *dbyte;
+	uint16_t *dcode;
+
+	if (!ha->pio_address || !mbuf)
+		return QLA_FUNCTION_FAILED;
+
+	memset(ha->bios_revision, 0, sizeof(ha->bios_revision));
+	memset(ha->efi_revision, 0, sizeof(ha->efi_revision));
+	memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision));
+	memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
+
+	qla2x00_flash_enable(ha);
+
+	/* Begin with first PCI expansion ROM header. */
+	pcihdr = 0;
+	last_image = 1;
+	do {
+		/* Verify PCI expansion ROM header. */
+		if (qla2x00_read_flash_byte(ha, pcihdr) != 0x55 ||
+		    qla2x00_read_flash_byte(ha, pcihdr + 0x01) != 0xaa) {
+			/* No signature */
+			DEBUG2(printk("scsi(%ld): No matching ROM "
+			    "signature.\n", ha->host_no));
+			ret = QLA_FUNCTION_FAILED;
+			break;
+		}
+
+		/* Locate PCI data structure. */
+		pcids = pcihdr +
+		    ((qla2x00_read_flash_byte(ha, pcihdr + 0x19) << 8) |
+			qla2x00_read_flash_byte(ha, pcihdr + 0x18));
+
+		/* Validate signature of PCI data structure. */
+		if (qla2x00_read_flash_byte(ha, pcids) != 'P' ||
+		    qla2x00_read_flash_byte(ha, pcids + 0x1) != 'C' ||
+		    qla2x00_read_flash_byte(ha, pcids + 0x2) != 'I' ||
+		    qla2x00_read_flash_byte(ha, pcids + 0x3) != 'R') {
+			/* Incorrect header. */
+			DEBUG2(printk("%s(): PCI data struct not found "
+			    "pcir_adr=%x.\n", __func__, pcids));
+			ret = QLA_FUNCTION_FAILED;
+			break;
+		}
+
+		/* Read version */
+		code_type = qla2x00_read_flash_byte(ha, pcids + 0x14);
+		switch (code_type) {
+		case ROM_CODE_TYPE_BIOS:
+			/* Intel x86, PC-AT compatible. */
+			ha->bios_revision[0] =
+			    qla2x00_read_flash_byte(ha, pcids + 0x12);
+			ha->bios_revision[1] =
+			    qla2x00_read_flash_byte(ha, pcids + 0x13);
+			DEBUG3(printk("%s(): read BIOS %d.%d.\n", __func__,
+			    ha->bios_revision[1], ha->bios_revision[0]));
+			break;
+		case ROM_CODE_TYPE_FCODE:
+			/* Open Firmware standard for PCI (FCode). */
+			/* Eeeewww... */
+			qla2x00_get_fcode_version(ha, pcids);
+			break;
+		case ROM_CODE_TYPE_EFI:
+			/* Extensible Firmware Interface (EFI). */
+			ha->efi_revision[0] =
+			    qla2x00_read_flash_byte(ha, pcids + 0x12);
+			ha->efi_revision[1] =
+			    qla2x00_read_flash_byte(ha, pcids + 0x13);
+			DEBUG3(printk("%s(): read EFI %d.%d.\n", __func__,
+			    ha->efi_revision[1], ha->efi_revision[0]));
+			break;
+		default:
+			DEBUG2(printk("%s(): Unrecognized code type %x at "
+			    "pcids %x.\n", __func__, code_type, pcids));
+			break;
+		}
+
+		last_image = qla2x00_read_flash_byte(ha, pcids + 0x15) & BIT_7;
+
+		/* Locate next PCI expansion ROM. */
+		pcihdr += ((qla2x00_read_flash_byte(ha, pcids + 0x11) << 8) |
+		    qla2x00_read_flash_byte(ha, pcids + 0x10)) * 512;
+	} while (!last_image);
+
+	if (IS_QLA2322(ha)) {
+		/* Read firmware image information. */
+		memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
+		dbyte = mbuf;
+		memset(dbyte, 0, 8);
+		dcode = (uint16_t *)dbyte;
+
+		qla2x00_read_flash_data(ha, dbyte, FA_RISC_CODE_ADDR * 4 + 10,
+		    8);
+		DEBUG3(printk("%s(%ld): dumping fw ver from flash:\n",
+		    __func__, ha->host_no));
+		DEBUG3(qla2x00_dump_buffer((uint8_t *)dbyte, 8));
+
+		if ((dcode[0] == 0xffff && dcode[1] == 0xffff &&
+		    dcode[2] == 0xffff && dcode[3] == 0xffff) ||
+		    (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
+		    dcode[3] == 0)) {
+			DEBUG2(printk("%s(): Unrecognized fw revision at "
+			    "%x.\n", __func__, FA_RISC_CODE_ADDR * 4));
+		} else {
+			/* values are in big endian */
+			ha->fw_revision[0] = dbyte[0] << 16 | dbyte[1];
+			ha->fw_revision[1] = dbyte[2] << 16 | dbyte[3];
+			ha->fw_revision[2] = dbyte[4] << 16 | dbyte[5];
+		}
+	}
+
+	qla2x00_flash_disable(ha);
+
+	return ret;
+}
+
+int
+qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
+{
+	int ret = QLA_SUCCESS;
+	uint32_t pcihdr, pcids;
+	uint32_t *dcode;
+	uint8_t *bcode;
+	uint8_t code_type, last_image;
+	int i;
+
+	if (!mbuf)
+		return QLA_FUNCTION_FAILED;
+
+	memset(ha->bios_revision, 0, sizeof(ha->bios_revision));
+	memset(ha->efi_revision, 0, sizeof(ha->efi_revision));
+	memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision));
+	memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
+
+	dcode = mbuf;
+
+	/* Begin with first PCI expansion ROM header. */
+	pcihdr = 0;
+	last_image = 1;
+	do {
+		/* Verify PCI expansion ROM header. */
+		qla24xx_read_flash_data(ha, dcode, pcihdr >> 2, 0x20);
+		bcode = mbuf + (pcihdr % 4);
+		if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) {
+			/* No signature */
+			DEBUG2(printk("scsi(%ld): No matching ROM "
+			    "signature.\n", ha->host_no));
+			ret = QLA_FUNCTION_FAILED;
+			break;
+		}
+
+		/* Locate PCI data structure. */
+		pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]);
+
+		qla24xx_read_flash_data(ha, dcode, pcids >> 2, 0x20);
+		bcode = mbuf + (pcihdr % 4);
+
+		/* Validate signature of PCI data structure. */
+		if (bcode[0x0] != 'P' || bcode[0x1] != 'C' ||
+		    bcode[0x2] != 'I' || bcode[0x3] != 'R') {
+			/* Incorrect header. */
+			DEBUG2(printk("%s(): PCI data struct not found "
+			    "pcir_adr=%x.\n", __func__, pcids));
+			ret = QLA_FUNCTION_FAILED;
+			break;
+		}
+
+		/* Read version */
+		code_type = bcode[0x14];
+		switch (code_type) {
+		case ROM_CODE_TYPE_BIOS:
+			/* Intel x86, PC-AT compatible. */
+			ha->bios_revision[0] = bcode[0x12];
+			ha->bios_revision[1] = bcode[0x13];
+			DEBUG3(printk("%s(): read BIOS %d.%d.\n", __func__,
+			    ha->bios_revision[1], ha->bios_revision[0]));
+			break;
+		case ROM_CODE_TYPE_FCODE:
+			/* Open Firmware standard for PCI (FCode). */
+			ha->fcode_revision[0] = bcode[0x12];
+			ha->fcode_revision[1] = bcode[0x13];
+			DEBUG3(printk("%s(): read FCODE %d.%d.\n", __func__,
+			    ha->fcode_revision[1], ha->fcode_revision[0]));
+			break;
+		case ROM_CODE_TYPE_EFI:
+			/* Extensible Firmware Interface (EFI). */
+			ha->efi_revision[0] = bcode[0x12];
+			ha->efi_revision[1] = bcode[0x13];
+			DEBUG3(printk("%s(): read EFI %d.%d.\n", __func__,
+			    ha->efi_revision[1], ha->efi_revision[0]));
+			break;
+		default:
+			DEBUG2(printk("%s(): Unrecognized code type %x at "
+			    "pcids %x.\n", __func__, code_type, pcids));
+			break;
+		}
+
+		last_image = bcode[0x15] & BIT_7;
+
+		/* Locate next PCI expansion ROM. */
+		pcihdr += ((bcode[0x11] << 8) | bcode[0x10]) * 512;
+	} while (!last_image);
+
+	/* Read firmware image information. */
+	memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
+	dcode = mbuf;
+
+	qla24xx_read_flash_data(ha, dcode, FA_RISC_CODE_ADDR + 4, 4);
+	for (i = 0; i < 4; i++)
+		dcode[i] = be32_to_cpu(dcode[i]);
+
+	if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff &&
+	    dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
+	    (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
+	    dcode[3] == 0)) {
+		DEBUG2(printk("%s(): Unrecognized fw version at %x.\n",
+		    __func__, FA_RISC_CODE_ADDR));
+	} else {
+		ha->fw_revision[0] = dcode[0];
+		ha->fw_revision[1] = dcode[1];
+		ha->fw_revision[2] = dcode[2];
+		ha->fw_revision[3] = dcode[3];
+	}
+
+	return ret;
+}
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 459e0d6bd2b4..61347aee55ce 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.01.07-k4"
+#define QLA2XXX_VERSION      "8.01.07-k5"
 
 #define QLA_DRIVER_MAJOR_VER	8
 #define QLA_DRIVER_MINOR_VER	1
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 24cffd98ee63..f33e2eb9f1b9 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -673,27 +673,6 @@ void __scsi_done(struct scsi_cmnd *cmd)
 }
 
 /*
- * Function:    scsi_retry_command
- *
- * Purpose:     Send a command back to the low level to be retried.
- *
- * Notes:       This command is always executed in the context of the
- *              bottom half handler, or the error handler thread. Low
- *              level drivers should not become re-entrant as a result of
- *              this.
- */
-int scsi_retry_command(struct scsi_cmnd *cmd)
-{
-        /*
-         * Zero the sense information from the last time we tried
-         * this command.
-         */
-	memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
-
-	return scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY);
-}
-
-/*
  * Function:    scsi_finish_command
  *
  * Purpose:     Pass command off to upper layer for finishing of I/O
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 30ee3d72c021..5adbbeedec38 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -51,10 +51,10 @@
 #include "scsi_logging.h"
 #include "scsi_debug.h"
 
-#define SCSI_DEBUG_VERSION "1.80"
-static const char * scsi_debug_version_date = "20061018";
+#define SCSI_DEBUG_VERSION "1.81"
+static const char * scsi_debug_version_date = "20070104";
 
-/* Additional Sense Code (ASC) used */
+/* Additional Sense Code (ASC) */
 #define NO_ADDITIONAL_SENSE 0x0
 #define LOGICAL_UNIT_NOT_READY 0x4
 #define UNRECOVERED_READ_ERR 0x11
@@ -65,9 +65,13 @@ static const char * scsi_debug_version_date = "20061018";
 #define INVALID_FIELD_IN_PARAM_LIST 0x26
 #define POWERON_RESET 0x29
 #define SAVING_PARAMS_UNSUP 0x39
+#define TRANSPORT_PROBLEM 0x4b
 #define THRESHOLD_EXCEEDED 0x5d
 #define LOW_POWER_COND_ON 0x5e
 
+/* Additional Sense Code Qualifier (ASCQ) */
+#define ACK_NAK_TO 0x3
+
 #define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */
 
 /* Default values for driver parameters */
@@ -95,15 +99,20 @@ static const char * scsi_debug_version_date = "20061018";
 #define SCSI_DEBUG_OPT_MEDIUM_ERR   2
 #define SCSI_DEBUG_OPT_TIMEOUT   4
 #define SCSI_DEBUG_OPT_RECOVERED_ERR   8
+#define SCSI_DEBUG_OPT_TRANSPORT_ERR   16
 /* When "every_nth" > 0 then modulo "every_nth" commands:
  *   - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
  *   - a RECOVERED_ERROR is simulated on successful read and write
  *     commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
+ *   - a TRANSPORT_ERROR is simulated on successful read and write
+ *     commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set.
  *
  * When "every_nth" < 0 then after "- every_nth" commands:
  *   - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
  *   - a RECOVERED_ERROR is simulated on successful read and write
  *     commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
+ *   - a TRANSPORT_ERROR is simulated on successful read and write
+ *     commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set.
  * This will continue until some other action occurs (e.g. the user
  * writing a new value (other than -1 or 1) to every_nth via sysfs).
  */
@@ -315,6 +324,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
 	int target = SCpnt->device->id;
 	struct sdebug_dev_info * devip = NULL;
 	int inj_recovered = 0;
+	int inj_transport = 0;
 	int delay_override = 0;
 
 	if (done == NULL)
@@ -352,6 +362,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
 			return 0; /* ignore command causing timeout */
 		else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts)
 			inj_recovered = 1; /* to reads and writes below */
+		else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts)
+			inj_transport = 1; /* to reads and writes below */
         }
 
 	if (devip->wlun) {
@@ -468,7 +480,11 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
 			mk_sense_buffer(devip, RECOVERED_ERROR,
 					THRESHOLD_EXCEEDED, 0);
 			errsts = check_condition_result;
-		}
+		} else if (inj_transport && (0 == errsts)) {
+                        mk_sense_buffer(devip, ABORTED_COMMAND,
+                                        TRANSPORT_PROBLEM, ACK_NAK_TO);
+                        errsts = check_condition_result;
+                }
 		break;
 	case REPORT_LUNS:	/* mandatory, ignore unit attention */
 		delay_override = 1;
@@ -531,6 +547,9 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
 		delay_override = 1;
 		errsts = check_readiness(SCpnt, 0, devip);
 		break;
+	case WRITE_BUFFER:
+		errsts = check_readiness(SCpnt, 1, devip);
+		break;
 	default:
 		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
 			printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "
@@ -954,7 +973,9 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
 	int alloc_len, n, ret;
 
 	alloc_len = (cmd[3] << 8) + cmd[4];
-	arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_KERNEL);
+	arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC);
+	if (! arr)
+		return DID_REQUEUE << 16;
 	if (devip->wlun)
 		pq_pdt = 0x1e;	/* present, wlun */
 	else if (scsi_debug_no_lun_0 && (0 == devip->lun))
@@ -1217,7 +1238,9 @@ static int resp_report_tgtpgs(struct scsi_cmnd * scp,
 	alen = ((cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8)
 		+ cmd[9]);
 
-	arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_KERNEL);
+	arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_ATOMIC);
+	if (! arr)
+		return DID_REQUEUE << 16;
 	/*
 	 * EVPD page 0x88 states we have two ports, one
 	 * real and a fake port with no device connected.
@@ -1996,6 +2019,8 @@ static int scsi_debug_slave_configure(struct scsi_device * sdp)
 	if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN)
 		sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN;
 	devip = devInfoReg(sdp);
+	if (NULL == devip)
+		return 1;	/* no resources, will be marked offline */
 	sdp->hostdata = devip;
 	if (sdp->host->cmd_per_lun)
 		scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING,
@@ -2044,7 +2069,7 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
 		}
 	}
 	if (NULL == open_devip) { /* try and make a new one */
-		open_devip = kzalloc(sizeof(*open_devip),GFP_KERNEL);
+		open_devip = kzalloc(sizeof(*open_devip),GFP_ATOMIC);
 		if (NULL == open_devip) {
 			printk(KERN_ERR "%s: out of memory at line %d\n",
 				__FUNCTION__, __LINE__);
@@ -2388,7 +2413,7 @@ MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
 MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
 MODULE_PARM_DESC(num_parts, "number of partitions(def=0)");
 MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)");
-MODULE_PARM_DESC(opts, "1->noise, 2->medium_error, 4->... (def=0)");
+MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)");
 MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
 MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])");
 MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)");
@@ -2943,7 +2968,6 @@ static int sdebug_add_adapter(void)
         struct list_head *lh, *lh_sf;
 
         sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL);
-
         if (NULL == sdbg_host) {
                 printk(KERN_ERR "%s: out of memory at line %d\n",
                        __FUNCTION__, __LINE__);
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 2ecb6ff42444..b8edcf5b5451 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -359,6 +359,11 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
 		return SUCCESS;
 
 	case MEDIUM_ERROR:
+		if (sshdr.asc == 0x11 || /* UNRECOVERED READ ERR */
+		    sshdr.asc == 0x13 || /* AMNF DATA FIELD */
+		    sshdr.asc == 0x14) { /* RECORD NOT FOUND */
+			return SUCCESS;
+		}
 		return NEEDS_RETRY;
 
 	case HARDWARE_ERROR:
@@ -453,6 +458,128 @@ static void scsi_eh_done(struct scsi_cmnd *scmd)
 }
 
 /**
+ * scsi_try_host_reset - ask host adapter to reset itself
+ * @scmd:	SCSI cmd to send hsot reset.
+ **/
+static int scsi_try_host_reset(struct scsi_cmnd *scmd)
+{
+	unsigned long flags;
+	int rtn;
+
+	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n",
+					  __FUNCTION__));
+
+	if (!scmd->device->host->hostt->eh_host_reset_handler)
+		return FAILED;
+
+	rtn = scmd->device->host->hostt->eh_host_reset_handler(scmd);
+
+	if (rtn == SUCCESS) {
+		if (!scmd->device->host->hostt->skip_settle_delay)
+			ssleep(HOST_RESET_SETTLE_TIME);
+		spin_lock_irqsave(scmd->device->host->host_lock, flags);
+		scsi_report_bus_reset(scmd->device->host,
+				      scmd_channel(scmd));
+		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
+	}
+
+	return rtn;
+}
+
+/**
+ * scsi_try_bus_reset - ask host to perform a bus reset
+ * @scmd:	SCSI cmd to send bus reset.
+ **/
+static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
+{
+	unsigned long flags;
+	int rtn;
+
+	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n",
+					  __FUNCTION__));
+
+	if (!scmd->device->host->hostt->eh_bus_reset_handler)
+		return FAILED;
+
+	rtn = scmd->device->host->hostt->eh_bus_reset_handler(scmd);
+
+	if (rtn == SUCCESS) {
+		if (!scmd->device->host->hostt->skip_settle_delay)
+			ssleep(BUS_RESET_SETTLE_TIME);
+		spin_lock_irqsave(scmd->device->host->host_lock, flags);
+		scsi_report_bus_reset(scmd->device->host,
+				      scmd_channel(scmd));
+		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
+	}
+
+	return rtn;
+}
+
+/**
+ * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev
+ * @scmd:	SCSI cmd used to send BDR
+ *
+ * Notes:
+ *    There is no timeout for this operation.  if this operation is
+ *    unreliable for a given host, then the host itself needs to put a
+ *    timer on it, and set the host back to a consistent state prior to
+ *    returning.
+ **/
+static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
+{
+	int rtn;
+
+	if (!scmd->device->host->hostt->eh_device_reset_handler)
+		return FAILED;
+
+	rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd);
+	if (rtn == SUCCESS) {
+		scmd->device->was_reset = 1;
+		scmd->device->expecting_cc_ua = 1;
+	}
+
+	return rtn;
+}
+
+static int __scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
+{
+	if (!scmd->device->host->hostt->eh_abort_handler)
+		return FAILED;
+
+	return scmd->device->host->hostt->eh_abort_handler(scmd);
+}
+
+/**
+ * scsi_try_to_abort_cmd - Ask host to abort a running command.
+ * @scmd:	SCSI cmd to abort from Lower Level.
+ *
+ * Notes:
+ *    This function will not return until the user's completion function
+ *    has been called.  there is no timeout on this operation.  if the
+ *    author of the low-level driver wishes this operation to be timed,
+ *    they can provide this facility themselves.  helper functions in
+ *    scsi_error.c can be supplied to make this easier to do.
+ **/
+static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
+{
+	/*
+	 * scsi_done was called just after the command timed out and before
+	 * we had a chance to process it. (db)
+	 */
+	if (scmd->serial_number == 0)
+		return SUCCESS;
+	return __scsi_try_to_abort_cmd(scmd);
+}
+
+static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
+{
+	if (__scsi_try_to_abort_cmd(scmd) != SUCCESS)
+		if (scsi_try_bus_device_reset(scmd) != SUCCESS)
+			if (scsi_try_bus_reset(scmd) != SUCCESS)
+				scsi_try_host_reset(scmd);
+}
+
+/**
  * scsi_send_eh_cmnd  - submit a scsi command as part of error recory
  * @scmd:       SCSI command structure to hijack
  * @cmnd:       CDB to send
@@ -579,13 +706,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
 			break;
 		}
 	} else {
-		/*
-		 * FIXME(eric) - we are not tracking whether we could
-		 * abort a timed out command or not.  not sure how
-		 * we should treat them differently anyways.
-		 */
-		if (shost->hostt->eh_abort_handler)
-			shost->hostt->eh_abort_handler(scmd);
+		scsi_abort_eh_cmnd(scmd);
 		rtn = FAILED;
 	}
 
@@ -672,8 +793,8 @@ EXPORT_SYMBOL(scsi_eh_finish_cmd);
  *    XXX: Long term this code should go away, but that needs an audit of
  *         all LLDDs first.
  **/
-static int scsi_eh_get_sense(struct list_head *work_q,
-			     struct list_head *done_q)
+int scsi_eh_get_sense(struct list_head *work_q,
+		      struct list_head *done_q)
 {
 	struct scsi_cmnd *scmd, *next;
 	int rtn;
@@ -715,31 +836,7 @@ static int scsi_eh_get_sense(struct list_head *work_q,
 
 	return list_empty(work_q);
 }
-
-/**
- * scsi_try_to_abort_cmd - Ask host to abort a running command.
- * @scmd:	SCSI cmd to abort from Lower Level.
- *
- * Notes:
- *    This function will not return until the user's completion function
- *    has been called.  there is no timeout on this operation.  if the
- *    author of the low-level driver wishes this operation to be timed,
- *    they can provide this facility themselves.  helper functions in
- *    scsi_error.c can be supplied to make this easier to do.
- **/
-static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
-{
-	if (!scmd->device->host->hostt->eh_abort_handler)
-		return FAILED;
-
-	/*
-	 * scsi_done was called just after the command timed out and before
-	 * we had a chance to process it. (db)
-	 */
-	if (scmd->serial_number == 0)
-		return SUCCESS;
-	return scmd->device->host->hostt->eh_abort_handler(scmd);
-}
+EXPORT_SYMBOL_GPL(scsi_eh_get_sense);
 
 /**
  * scsi_eh_tur - Send TUR to device.
@@ -815,32 +912,6 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,
 }
 
 /**
- * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev
- * @scmd:	SCSI cmd used to send BDR	
- *
- * Notes:
- *    There is no timeout for this operation.  if this operation is
- *    unreliable for a given host, then the host itself needs to put a
- *    timer on it, and set the host back to a consistent state prior to
- *    returning.
- **/
-static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
-{
-	int rtn;
-
-	if (!scmd->device->host->hostt->eh_device_reset_handler)
-		return FAILED;
-
-	rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd);
-	if (rtn == SUCCESS) {
-		scmd->device->was_reset = 1;
-		scmd->device->expecting_cc_ua = 1;
-	}
-
-	return rtn;
-}
-
-/**
  * scsi_eh_try_stu - Send START_UNIT to device.
  * @scmd:	Scsi cmd to send START_UNIT
  *
@@ -971,64 +1042,6 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
 }
 
 /**
- * scsi_try_bus_reset - ask host to perform a bus reset
- * @scmd:	SCSI cmd to send bus reset.
- **/
-static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
-{
-	unsigned long flags;
-	int rtn;
-
-	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n",
-					  __FUNCTION__));
-
-	if (!scmd->device->host->hostt->eh_bus_reset_handler)
-		return FAILED;
-
-	rtn = scmd->device->host->hostt->eh_bus_reset_handler(scmd);
-
-	if (rtn == SUCCESS) {
-		if (!scmd->device->host->hostt->skip_settle_delay)
-			ssleep(BUS_RESET_SETTLE_TIME);
-		spin_lock_irqsave(scmd->device->host->host_lock, flags);
-		scsi_report_bus_reset(scmd->device->host,
-				      scmd_channel(scmd));
-		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
-	}
-
-	return rtn;
-}
-
-/**
- * scsi_try_host_reset - ask host adapter to reset itself
- * @scmd:	SCSI cmd to send hsot reset.
- **/
-static int scsi_try_host_reset(struct scsi_cmnd *scmd)
-{
-	unsigned long flags;
-	int rtn;
-
-	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n",
-					  __FUNCTION__));
-
-	if (!scmd->device->host->hostt->eh_host_reset_handler)
-		return FAILED;
-
-	rtn = scmd->device->host->hostt->eh_host_reset_handler(scmd);
-
-	if (rtn == SUCCESS) {
-		if (!scmd->device->host->hostt->skip_settle_delay)
-			ssleep(HOST_RESET_SETTLE_TIME);
-		spin_lock_irqsave(scmd->device->host->host_lock, flags);
-		scsi_report_bus_reset(scmd->device->host,
-				      scmd_channel(scmd));
-		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
-	}
-
-	return rtn;
-}
-
-/**
  * scsi_eh_bus_reset - send a bus reset 
  * @shost:	scsi host being recovered.
  * @eh_done_q:	list_head for processed commands.
@@ -1411,9 +1424,9 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
  * @eh_done_q:	list_head for processed commands.
  *
  **/
-static void scsi_eh_ready_devs(struct Scsi_Host *shost,
-			       struct list_head *work_q,
-			       struct list_head *done_q)
+void scsi_eh_ready_devs(struct Scsi_Host *shost,
+			struct list_head *work_q,
+			struct list_head *done_q)
 {
 	if (!scsi_eh_stu(shost, work_q, done_q))
 		if (!scsi_eh_bus_device_reset(shost, work_q, done_q))
@@ -1421,6 +1434,7 @@ static void scsi_eh_ready_devs(struct Scsi_Host *shost,
 				if (!scsi_eh_host_reset(work_q, done_q))
 					scsi_eh_offline_sdevs(work_q, done_q);
 }
+EXPORT_SYMBOL_GPL(scsi_eh_ready_devs);
 
 /**
  * scsi_eh_flush_done_q - finish processed commands or retry them.
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index a1cd6e6a292a..9f7482d0b594 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1399,7 +1399,7 @@ static void scsi_softirq_done(struct request *rq)
 			scsi_finish_command(cmd);
 			break;
 		case NEEDS_RETRY:
-			scsi_retry_command(cmd);
+			scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY);
 			break;
 		case ADD_TO_MLQUEUE:
 			scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
@@ -2249,6 +2249,8 @@ void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count,
 	size_t sg_len = 0, len_complete = 0;
 	struct page *page;
 
+	WARN_ON(!irqs_disabled());
+
 	for (i = 0; i < sg_count; i++) {
 		len_complete = sg_len; /* Complete sg-entries */
 		sg_len += sg[i].length;
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index f458c2f686d2..ee8efe849bf4 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -28,7 +28,6 @@ extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd);
 extern int scsi_setup_command_freelist(struct Scsi_Host *shost);
 extern void scsi_destroy_command_freelist(struct Scsi_Host *shost);
 extern void __scsi_done(struct scsi_cmnd *cmd);
-extern int scsi_retry_command(struct scsi_cmnd *cmd);
 #ifdef CONFIG_SCSI_LOGGING
 void scsi_log_send(struct scsi_cmnd *cmd);
 void scsi_log_completion(struct scsi_cmnd *cmd, int disposition);
@@ -58,6 +57,11 @@ extern int scsi_error_handler(void *host);
 extern int scsi_decide_disposition(struct scsi_cmnd *cmd);
 extern void scsi_eh_wakeup(struct Scsi_Host *shost);
 extern int scsi_eh_scmd_add(struct scsi_cmnd *, int);
+void scsi_eh_ready_devs(struct Scsi_Host *shost,
+			struct list_head *work_q,
+			struct list_head *done_q);
+int scsi_eh_get_sense(struct list_head *work_q,
+		      struct list_head *done_q);
 
 /* scsi_lib.c */
 extern int scsi_maybe_unblock_host(struct scsi_device *sdev);
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 96b7cbd746a8..a43b9ec3aefd 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -1029,7 +1029,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
 
 				sdev_printk(KERN_INFO, sdev,
 					"scsi scan: consider passing scsi_mod."
-					"dev_flags=%s:%s:0x240 or 0x800240\n",
+					"dev_flags=%s:%s:0x240 or 0x1000240\n",
 					scsi_inq_str(vend, result, 8, 16),
 					scsi_inq_str(mod, result, 16, 32));
 			});
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index 5c0b75bbfa10..6d39150e205b 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -336,6 +336,51 @@ show_sas_device_type(struct class_device *cdev, char *buf)
 }
 static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL);
 
+static ssize_t do_sas_phy_enable(struct class_device *cdev,
+		size_t count, int enable)
+{
+	struct sas_phy *phy = transport_class_to_phy(cdev);
+	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+	struct sas_internal *i = to_sas_internal(shost->transportt);
+	int error;
+
+	error = i->f->phy_enable(phy, enable);
+	if (error)
+		return error;
+	phy->enabled = enable;
+	return count;
+};
+
+static ssize_t store_sas_phy_enable(struct class_device *cdev,
+		const char *buf, size_t count)
+{
+	if (count < 1)
+		return -EINVAL;
+
+	switch (buf[0]) {
+	case '0':
+		do_sas_phy_enable(cdev, count, 0);
+		break;
+	case '1':
+		do_sas_phy_enable(cdev, count, 1);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+static ssize_t show_sas_phy_enable(struct class_device *cdev, char *buf)
+{
+	struct sas_phy *phy = transport_class_to_phy(cdev);
+
+	return snprintf(buf, 20, "%d", phy->enabled);
+}
+
+static CLASS_DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable,
+			 store_sas_phy_enable);
+
 static ssize_t do_sas_phy_reset(struct class_device *cdev,
 		size_t count, int hard_reset)
 {
@@ -435,6 +480,7 @@ struct sas_phy *sas_phy_alloc(struct device *parent, int number)
 		return NULL;
 
 	phy->number = number;
+	phy->enabled = 1;
 
 	device_initialize(&phy->dev);
 	phy->dev.parent = get_device(parent);
@@ -579,8 +625,19 @@ static void sas_port_release(struct device *dev)
 static void sas_port_create_link(struct sas_port *port,
 				 struct sas_phy *phy)
 {
-	sysfs_create_link(&port->dev.kobj, &phy->dev.kobj, phy->dev.bus_id);
-	sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port");
+	int res;
+
+	res = sysfs_create_link(&port->dev.kobj, &phy->dev.kobj,
+				phy->dev.bus_id);
+	if (res)
+		goto err;
+	res = sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port");
+	if (res)
+		goto err;
+	return;
+err:
+	printk(KERN_ERR "%s: Cannot create port links, err=%d\n",
+	       __FUNCTION__, res);
 }
 
 static void sas_port_delete_link(struct sas_port *port,
@@ -818,13 +875,20 @@ EXPORT_SYMBOL(sas_port_delete_phy);
 
 void sas_port_mark_backlink(struct sas_port *port)
 {
+	int res;
 	struct device *parent = port->dev.parent->parent->parent;
 
 	if (port->is_backlink)
 		return;
 	port->is_backlink = 1;
-	sysfs_create_link(&port->dev.kobj, &parent->kobj,
-			  parent->bus_id);
+	res = sysfs_create_link(&port->dev.kobj, &parent->kobj,
+				parent->bus_id);
+	if (res)
+		goto err;
+	return;
+err:
+	printk(KERN_ERR "%s: Cannot create port backlink, err=%d\n",
+	       __FUNCTION__, res);
 
 }
 EXPORT_SYMBOL(sas_port_mark_backlink);
@@ -1237,7 +1301,7 @@ int sas_rphy_add(struct sas_rphy *rphy)
 	if (identify->device_type == SAS_END_DEVICE &&
 	    rphy->scsi_target_id != -1) {
 		scsi_scan_target(&rphy->dev, 0,
-				rphy->scsi_target_id, ~0, 0);
+				rphy->scsi_target_id, SCAN_WILD_CARD, 0);
 	}
 
 	return 0;
@@ -1253,7 +1317,7 @@ EXPORT_SYMBOL(sas_rphy_add);
  * Note:
  *   This function must only be called on a remote
  *   PHY that has not sucessfully been added using
- *   sas_rphy_add().
+ *   sas_rphy_add() (or has been sas_rphy_remove()'d)
  */
 void sas_rphy_free(struct sas_rphy *rphy)
 {
@@ -1272,18 +1336,30 @@ void sas_rphy_free(struct sas_rphy *rphy)
 EXPORT_SYMBOL(sas_rphy_free);
 
 /**
- * sas_rphy_delete  --  remove SAS remote PHY
- * @rphy:	SAS remote PHY to remove
+ * sas_rphy_delete  --  remove and free SAS remote PHY
+ * @rphy:	SAS remote PHY to remove and free
  *
- * Removes the specified SAS remote PHY.
+ * Removes the specified SAS remote PHY and frees it.
  */
 void
 sas_rphy_delete(struct sas_rphy *rphy)
 {
+	sas_rphy_remove(rphy);
+	sas_rphy_free(rphy);
+}
+EXPORT_SYMBOL(sas_rphy_delete);
+
+/**
+ * sas_rphy_remove  --  remove SAS remote PHY
+ * @rphy:	SAS remote phy to remove
+ *
+ * Removes the specified SAS remote PHY.
+ */
+void
+sas_rphy_remove(struct sas_rphy *rphy)
+{
 	struct device *dev = &rphy->dev;
 	struct sas_port *parent = dev_to_sas_port(dev->parent);
-	struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);
-	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
 
 	switch (rphy->identify.device_type) {
 	case SAS_END_DEVICE:
@@ -1299,17 +1375,10 @@ sas_rphy_delete(struct sas_rphy *rphy)
 
 	transport_remove_device(dev);
 	device_del(dev);
-	transport_destroy_device(dev);
-
-	mutex_lock(&sas_host->lock);
-	list_del(&rphy->list);
-	mutex_unlock(&sas_host->lock);
 
 	parent->rphy = NULL;
-
-	put_device(dev);
 }
-EXPORT_SYMBOL(sas_rphy_delete);
+EXPORT_SYMBOL(sas_rphy_remove);
 
 /**
  * scsi_is_sas_rphy  --  check if a struct device represents a SAS remote PHY
@@ -1389,6 +1458,10 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
 	SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1,	\
 			!i->f->set_phy_speed, S_IRUGO)
 
+#define SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(field, func)			\
+	SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1,	\
+			  !i->f->func, S_IRUGO)
+
 #define SETUP_PORT_ATTRIBUTE(field)					\
 	SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1)
 
@@ -1396,10 +1469,10 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
 	SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func)
 
 #define SETUP_PHY_ATTRIBUTE_WRONLY(field)				\
-	SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, 1)
+	SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, 1)
 
 #define SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(field, func)		\
-	SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, i->f->func)
+	SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, i->f->func)
 
 #define SETUP_END_DEV_ATTRIBUTE(field)					\
 	SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1)
@@ -1479,6 +1552,7 @@ sas_attach_transport(struct sas_function_template *ft)
 	SETUP_PHY_ATTRIBUTE(phy_reset_problem_count);
 	SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(link_reset, phy_reset);
 	SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(hard_reset, phy_reset);
+	SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(enable, phy_enable);
 	i->phy_attrs[count] = NULL;
 
 	count = 0;
@@ -1587,7 +1661,7 @@ static void __exit sas_transport_exit(void)
 }
 
 MODULE_AUTHOR("Christoph Hellwig");
-MODULE_DESCRIPTION("SAS Transphy Attributes");
+MODULE_DESCRIPTION("SAS Transport Attributes");
 MODULE_LICENSE("GPL");
 
 module_init(sas_transport_init);
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 014d7fea1ff3..6f56f8750635 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -46,7 +46,6 @@
 				 * two cc/ua clears */
 
 /* Private data accessors (keep these out of the header file) */
-#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending)
 #define spi_dv_in_progress(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_in_progress)
 #define spi_dv_mutex(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_mutex)
 
diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c
index 551baccec523..018c65f73ac4 100644
--- a/drivers/scsi/sim710.c
+++ b/drivers/scsi/sim710.c
@@ -123,6 +123,7 @@ sim710_probe_common(struct device *dev, unsigned long base_addr,
 	hostdata->differential = differential;
 	hostdata->clock = clock;
 	hostdata->chip710 = 1;
+	hostdata->burst_length = 8;
 
 	/* and register the chip */
 	if((host = NCR_700_detect(&sim710_driver_template, hostdata, dev))
diff --git a/drivers/scsi/sni_53c710.c b/drivers/scsi/sni_53c710.c
new file mode 100644
index 000000000000..6bc505115841
--- /dev/null
+++ b/drivers/scsi/sni_53c710.c
@@ -0,0 +1,159 @@
+/* -*- mode: c; c-basic-offset: 8 -*- */
+
+/* SNI RM driver
+ *
+ * Copyright (C) 2001 by James.Bottomley@HansenPartnership.com
+**-----------------------------------------------------------------------------
+**
+**  This program is free software; you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License as published by
+**  the Free Software Foundation; either version 2 of the License, or
+**  (at your option) any later version.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**-----------------------------------------------------------------------------
+ */
+
+/*
+ * Based on lasi700.c
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/stat.h>
+#include <linux/mm.h>
+#include <linux/blkdev.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/delay.h>
+
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_spi.h>
+
+#include "53c700.h"
+
+MODULE_AUTHOR("Thomas Bogendörfer");
+MODULE_DESCRIPTION("SNI RM 53c710 SCSI Driver");
+MODULE_LICENSE("GPL");
+
+#define SNIRM710_CLOCK	32
+
+static struct scsi_host_template snirm710_template = {
+	.name		= "SNI RM SCSI 53c710",
+	.proc_name	= "snirm_53c710",
+	.this_id	= 7,
+	.module		= THIS_MODULE,
+};
+
+static int __init snirm710_probe(struct platform_device *dev)
+{
+	unsigned long base;
+	struct NCR_700_Host_Parameters *hostdata;
+	struct Scsi_Host *host;
+	struct  resource *res;
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	base = res->start;
+	hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL);
+	if (!hostdata) {
+		printk(KERN_ERR "%s: Failed to allocate host data\n",
+		       dev->dev.bus_id);
+		return -ENOMEM;
+	}
+
+	hostdata->dev = &dev->dev;
+	dma_set_mask(&dev->dev, DMA_32BIT_MASK);
+	hostdata->base = ioremap_nocache(CPHYSADDR(base), 0x100);
+	hostdata->differential = 0;
+
+	hostdata->clock = SNIRM710_CLOCK;
+	hostdata->force_le_on_be = 1;
+	hostdata->chip710 = 1;
+	hostdata->burst_length = 4;
+
+	host = NCR_700_detect(&snirm710_template, hostdata, &dev->dev);
+	if (!host)
+		goto out_kfree;
+	host->this_id = 7;
+	host->base = base;
+	host->irq = platform_get_irq(dev, 0);
+	if(request_irq(host->irq, NCR_700_intr, SA_SHIRQ, "snirm710", host)) {
+		printk(KERN_ERR "snirm710: request_irq failed!\n");
+		goto out_put_host;
+	}
+
+	dev_set_drvdata(&dev->dev, host);
+	scsi_scan_host(host);
+
+	return 0;
+
+ out_put_host:
+	scsi_host_put(host);
+ out_kfree:
+	iounmap(hostdata->base);
+	kfree(hostdata);
+	return -ENODEV;
+}
+
+static int __exit snirm710_driver_remove(struct platform_device *dev)
+{
+	struct Scsi_Host *host = dev_get_drvdata(&dev->dev);
+	struct NCR_700_Host_Parameters *hostdata =
+		(struct NCR_700_Host_Parameters *)host->hostdata[0];
+
+	scsi_remove_host(host);
+	NCR_700_release(host);
+	free_irq(host->irq, host);
+	iounmap(hostdata->base);
+	kfree(hostdata);
+
+	return 0;
+}
+
+static struct platform_driver snirm710_driver = {
+	.probe	= snirm710_probe,
+	.remove	= __devexit_p(snirm710_driver_remove),
+	.driver	= {
+		.name	= "snirm_53c710",
+	},
+};
+
+static int __init snirm710_init(void)
+{
+	int err;
+
+	if ((err = platform_driver_register(&snirm710_driver))) {
+		printk(KERN_ERR "Driver registration failed\n");
+		return err;
+	}
+	return 0;
+}
+
+static void __exit snirm710_exit(void)
+{
+	platform_driver_unregister(&snirm710_driver);
+}
+
+module_init(snirm710_init);
+module_exit(snirm710_exit);
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 488ec7948a57..16e279be4a3e 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -9,7 +9,7 @@
    Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky,
    Michael Schaefer, J"org Weule, and Eric Youngdale.
 
-   Copyright 1992 - 2006 Kai Makisara
+   Copyright 1992 - 2007 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 const char *verstr = "20061107";
+static const char *verstr = "20070203";
 
 #include <linux/module.h>
 
@@ -1168,6 +1168,7 @@ static int st_open(struct inode *inode, struct file *filp)
 		STps = &(STp->ps[i]);
 		STps->rw = ST_IDLE;
 	}
+	STp->try_dio_now = STp->try_dio;
 	STp->recover_count = 0;
 	DEB( STp->nbr_waits = STp->nbr_finished = 0;
 	     STp->nbr_requests = STp->nbr_dio = STp->nbr_pages = STp->nbr_combinable = 0; )
@@ -1400,9 +1401,9 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf,
 	struct st_buffer *STbp = STp->buffer;
 
 	if (is_read)
-		i = STp->try_dio && try_rdio;
+		i = STp->try_dio_now && try_rdio;
 	else
-		i = STp->try_dio && try_wdio;
+		i = STp->try_dio_now && try_wdio;
 
 	if (i && ((unsigned long)buf & queue_dma_alignment(
 					STp->device->request_queue)) == 0) {
@@ -1599,7 +1600,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
 			STm->do_async_writes && STps->eof < ST_EOM_OK;
 
 		if (STp->block_size != 0 && STm->do_buffer_writes &&
-		    !(STp->try_dio && try_wdio) && STps->eof < ST_EOM_OK &&
+		    !(STp->try_dio_now && try_wdio) && STps->eof < ST_EOM_OK &&
 		    STbp->buffer_bytes < STbp->buffer_size) {
 			STp->dirty = 1;
 			/* Don't write a buffer that is not full enough. */
@@ -1769,7 +1770,7 @@ static long read_tape(struct scsi_tape *STp, long count,
 	if (STp->block_size == 0)
 		blks = bytes = count;
 	else {
-		if (!(STp->try_dio && try_rdio) && STm->do_read_ahead) {
+		if (!(STp->try_dio_now && try_rdio) && STm->do_read_ahead) {
 			blks = (STp->buffer)->buffer_blocks;
 			bytes = blks * STp->block_size;
 		} else {
@@ -1948,10 +1949,12 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
 		goto out;
 
 	STm = &(STp->modes[STp->current_mode]);
-	if (!(STm->do_read_ahead) && STp->block_size != 0 &&
-	    (count % STp->block_size) != 0) {
-		retval = (-EINVAL);	/* Read must be integral number of blocks */
-		goto out;
+	if (STp->block_size != 0 && (count % STp->block_size) != 0) {
+		if (!STm->do_read_ahead) {
+			retval = (-EINVAL);	/* Read must be integral number of blocks */
+			goto out;
+		}
+		STp->try_dio_now = 0;  /* Direct i/o can't handle split blocks */
 	}
 
 	STps = &(STp->ps[STp->partition]);
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index 05a5cae126ec..50f3deb1f9ed 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -117,7 +117,8 @@ struct scsi_tape {
 	unsigned char cln_sense_value;
 	unsigned char cln_sense_mask;
 	unsigned char use_pf;			/* Set Page Format bit in all mode selects? */
-	unsigned char try_dio;			/* try direct i/o? */
+	unsigned char try_dio;			/* try direct i/o in general? */
+	unsigned char try_dio_now;		/* try direct i/o before next close? */
 	unsigned char c_algo;			/* compression algorithm */
 	unsigned char pos_unknown;			/* after reset position unknown */
 	int tape_type;
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 0689e004a281..ad0182ef7809 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -323,12 +323,20 @@ struct sas_ha_event {
 	struct sas_ha_struct *ha;
 };
 
+enum sas_ha_state {
+	SAS_HA_REGISTERED,
+	SAS_HA_UNREGISTERED
+};
+
 struct sas_ha_struct {
 /* private: */
 	spinlock_t       event_lock;
 	struct sas_ha_event ha_events[HA_NUM_EVENTS];
 	unsigned long	 pending;
 
+	enum sas_ha_state state;
+	spinlock_t 	  state_lock;
+
 	struct scsi_core core;
 
 /* public: */
@@ -553,7 +561,8 @@ struct sas_task {
 #define SAS_TASK_STATE_PENDING      1
 #define SAS_TASK_STATE_DONE         2
 #define SAS_TASK_STATE_ABORTED      4
-#define SAS_TASK_INITIATOR_ABORTED  8
+#define SAS_TASK_NEED_DEV_RESET     8
+#define SAS_TASK_AT_INITIATOR       16
 
 static inline struct sas_task *sas_alloc_task(gfp_t flags)
 {
@@ -612,6 +621,9 @@ struct sas_domain_function_template {
 extern int sas_register_ha(struct sas_ha_struct *);
 extern int sas_unregister_ha(struct sas_ha_struct *);
 
+int sas_set_phy_speed(struct sas_phy *phy,
+		      struct sas_phy_linkrates *rates);
+int sas_phy_enable(struct sas_phy *phy, int enabled);
 int sas_phy_reset(struct sas_phy *phy, int hard_reset);
 extern int sas_queuecommand(struct scsi_cmnd *,
 		     void (*scsi_done)(struct scsi_cmnd *));
@@ -645,6 +657,9 @@ void sas_unregister_dev(struct domain_device *);
 
 void sas_init_dev(struct domain_device *);
 
-void sas_task_abort(struct work_struct *);
+void sas_task_abort(struct sas_task *);
+int __sas_task_abort(struct sas_task *);
+int sas_eh_device_reset_handler(struct scsi_cmnd *cmd);
+int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd);
 
 #endif /* _SASLIB_H_ */
diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h
index 59633a82de47..9aedc19820b0 100644
--- a/include/scsi/scsi_transport_sas.h
+++ b/include/scsi/scsi_transport_sas.h
@@ -54,6 +54,7 @@ struct sas_identify {
 struct sas_phy {
 	struct device		dev;
 	int			number;
+	int			enabled;
 
 	/* phy identification */
 	struct sas_identify	identify;
@@ -163,6 +164,7 @@ struct sas_function_template {
 	int (*get_enclosure_identifier)(struct sas_rphy *, u64 *);
 	int (*get_bay_identifier)(struct sas_rphy *);
 	int (*phy_reset)(struct sas_phy *, int);
+	int (*phy_enable)(struct sas_phy *, int);
 	int (*set_phy_speed)(struct sas_phy *, struct sas_phy_linkrates *);
 };
 
@@ -180,6 +182,7 @@ extern struct sas_rphy *sas_end_device_alloc(struct sas_port *);
 extern struct sas_rphy *sas_expander_alloc(struct sas_port *, enum sas_device_type);
 void sas_rphy_free(struct sas_rphy *);
 extern int sas_rphy_add(struct sas_rphy *);
+extern void sas_rphy_remove(struct sas_rphy *);
 extern void sas_rphy_delete(struct sas_rphy *);
 extern int scsi_is_sas_rphy(const struct device *);
 
diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h
index da180f738477..286e9628ed8b 100644
--- a/include/scsi/scsi_transport_spi.h
+++ b/include/scsi/scsi_transport_spi.h
@@ -85,6 +85,7 @@ struct spi_host_attrs {
 #define spi_pcomp_en(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->pcomp_en)
 #define spi_hold_mcs(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->hold_mcs)
 #define spi_initial_dv(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->initial_dv)
+#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending)
 
 #define spi_support_sync(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->support_sync)
 #define spi_support_wide(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->support_wide)