Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Sun, 11 Feb 2007 19:44:25 +0000 (11:44 -0800)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Sun, 11 Feb 2007 19:44:25 +0000 (11:44 -0800)
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (97 commits)
  [SCSI] zfcp: removed wrong comment
  [SCSI] zfcp: use of uninitialized variable
  [SCSI] zfcp: Invalid locking order
  [SCSI] aic79xx: use dma_get_required_mask()
  [SCSI] aic79xx: fix bracket mismatch in unused macro
  [SCSI] BusLogic: Replace 'boolean' by 'bool'
  [SCSI] advansys: clean up warnings
  [SCSI] 53c7xx: brackets fix in uncompiled code
  [SCSI] nsp_cs: remove old scsi code
  [SCSI] aic79xx: make ahd_match_scb() static
  [SCSI] DAC960: kmalloc->kzalloc/Casting cleanups
  [SCSI] scsi_kmap_atomic_sg(): check that local irqs are disabled
  [SCSI] Buslogic: local_irq_disable() is redundant after local_irq_save()
  [SCSI] aic94xx: update for v28 firmware
  [SCSI] scsi_error: Fix lost EH commands
  [SCSI] aic94xx: Add default bus reset handler
  [SCSI] aic94xx: Remove TMF result code munging
  [SCSI] libsas: Add an LU reset mechanism to the error handler
  [SCSI] libsas: Don't BUG when connecting two expanders via wide port
  [SCSI] st: fix Tape dies if wrong block size used, bug 7919
  ...

104 files changed:
Documentation/scsi/ChangeLog.megaraid
drivers/block/DAC960.c
drivers/message/fusion/Kconfig
drivers/message/fusion/Makefile
drivers/message/fusion/lsi/mpi.h
drivers/message/fusion/lsi/mpi_cnfg.h
drivers/message/fusion/lsi/mpi_history.txt
drivers/message/fusion/lsi/mpi_init.h
drivers/message/fusion/lsi/mpi_ioc.h
drivers/message/fusion/lsi/mpi_log_sas.h
drivers/message/fusion/lsi/mpi_sas.h
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptbase.h
drivers/message/fusion/mptctl.c
drivers/message/fusion/mptctl.h
drivers/message/fusion/mptfc.c
drivers/message/fusion/mptlan.c
drivers/message/fusion/mptlan.h
drivers/message/fusion/mptsas.c
drivers/message/fusion/mptscsih.c
drivers/message/fusion/mptscsih.h
drivers/message/fusion/mptspi.c
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_ext.h
drivers/s390/scsi/zfcp_fsf.c
drivers/scsi/53c700.c
drivers/scsi/53c700.h
drivers/scsi/53c7xx.c
drivers/scsi/BusLogic.c
drivers/scsi/BusLogic.h
drivers/scsi/FlashPoint.c
drivers/scsi/Kconfig
drivers/scsi/Makefile
drivers/scsi/NCR_D700.c
drivers/scsi/aacraid/Makefile
drivers/scsi/aacraid/aachba.c
drivers/scsi/aacraid/aacraid.h
drivers/scsi/aacraid/comminit.c
drivers/scsi/aacraid/commsup.c
drivers/scsi/aacraid/linit.c
drivers/scsi/aacraid/nark.c [new file with mode: 0644]
drivers/scsi/aacraid/rkt.c
drivers/scsi/aacraid/rx.c
drivers/scsi/aacraid/sa.c
drivers/scsi/advansys.c
drivers/scsi/aic7xxx/aic79xx.h
drivers/scsi/aic7xxx/aic79xx_core.c
drivers/scsi/aic7xxx/aic79xx_osm.c
drivers/scsi/aic7xxx/aic79xx_osm.h
drivers/scsi/aic7xxx/aic79xx_osm_pci.c
drivers/scsi/aic7xxx/aic79xx_pci.c
drivers/scsi/aic94xx/aic94xx_dev.c
drivers/scsi/aic94xx/aic94xx_dump.c
drivers/scsi/aic94xx/aic94xx_init.c
drivers/scsi/aic94xx/aic94xx_reg_def.h
drivers/scsi/aic94xx/aic94xx_sas.h
drivers/scsi/aic94xx/aic94xx_scb.c
drivers/scsi/aic94xx/aic94xx_sds.c
drivers/scsi/aic94xx/aic94xx_seq.c
drivers/scsi/aic94xx/aic94xx_seq.h
drivers/scsi/aic94xx/aic94xx_task.c
drivers/scsi/aic94xx/aic94xx_tmf.c
drivers/scsi/ipr.c
drivers/scsi/ipr.h
drivers/scsi/lasi700.c
drivers/scsi/libsas/sas_discover.c
drivers/scsi/libsas/sas_event.c
drivers/scsi/libsas/sas_expander.c
drivers/scsi/libsas/sas_init.c
drivers/scsi/libsas/sas_internal.h
drivers/scsi/libsas/sas_port.c
drivers/scsi/libsas/sas_scsi_host.c
drivers/scsi/megaraid/mbox_defs.h
drivers/scsi/megaraid/mega_common.h
drivers/scsi/megaraid/megaraid_ioctl.h
drivers/scsi/megaraid/megaraid_mbox.c
drivers/scsi/megaraid/megaraid_mbox.h
drivers/scsi/megaraid/megaraid_mm.c
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/pcmcia/nsp_cs.h
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_sup.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/scsi.c
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_priv.h
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_transport_sas.c
drivers/scsi/scsi_transport_spi.c
drivers/scsi/sim710.c
drivers/scsi/sni_53c710.c [new file with mode: 0644]
drivers/scsi/st.c
drivers/scsi/st.h
include/scsi/libsas.h
include/scsi/scsi_transport_sas.h
include/scsi/scsi_transport_spi.h

index a056bbe67c7ea22627b044b02bf19ed3426421d9..37796fe45bd00a0a31fa9bc4a3a6a12decbe1606 100644 (file)
@@ -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)
index 6ad28dfb146908ec490b1c3657e70dcca75604b8..7b2fa3d8f61c0522b0bb6ff07c2e4de6199b31c3 100644 (file)
@@ -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",
index ea31d84705107ca361d7cc0d59992a0aca3e97a3..71037f91c222611e8d9933d441fb29a4337f4096 100644 (file)
@@ -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
index 341691390e86370bec5ccfd37b73b8aa9266c92d..6003b46c8438163367695238695171c3d59cb8e7 100644 (file)
@@ -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...
 #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
index 81ad77622dacee63e3b0aa23054d12eadd087812..75223bf24ae86fa8449e19976d09518ba51f7deb 100644 (file)
@@ -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.
  *  --------------------------------------------------------------------------
  */
 
 /* 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)
index 47e13e360c10aea30975a44c18e4f9ca36319288..0e4c8e77a81dc7efcc8dbf39f1cd4bf0282a57a1 100644 (file)
@@ -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
  *  ---------------
  *                      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 */
 
index 582cfe7c2aa10a81b823aeda0d025e0bd7687431..d6b4c607453bdde0cd1179e40cab7786e52ee231 100644 (file)
@@ -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
 ----------  --------   --------   --------   --------   --------   --------
index c1c678989a2370335d548d2facd15d70970446df..ec9dff2249a7f429e12bbbedb22f45dc7f7f70d3 100644 (file)
@@ -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)
index 18ba407fd3998093694c58c5b2f313aba6cbe008..6c33e335337557c65c452e26abaec840449e254c 100644 (file)
@@ -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
  *  ---------------
  *                      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
 {
index 871ebc08b706133de56ea0ef96f5b248dda12aff..635bbe04513e44ac04893c5b0a3609fdd63d3e9c 100644 (file)
@@ -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                            */
 /****************************************************************************/
 /* 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 */
 
 
 /****************************************************************************/
index 50b8f0a8f4560d5e222209cb43c2d856e8fa56c2..8e990a0fa7a214287e17eef7ad60adc79739cadd 100644 (file)
@@ -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)
index b3f28a03b6a99f247648c9f12dc19f348d26213f..083acfd91d8bff0dad61188a8195c7b8aa1893e2 100644 (file)
@@ -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);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
index e316708f76bd90e8777df1cda033ecb060834353..e3a39272aad6e2f5a059dce85ab9e87b3f5e620b 100644 (file)
@@ -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)  \
 #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...
index 504632da43470fdbbca038e9d7dc46e3f91fdde2..b0b80428d1107bdc082894106660225ea11a6260 100644 (file)
@@ -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",
index e65a1cf5eb0b776f26b265641c729aaa80948563..f7e72c5e47de28bbff0263ae1ecb8930bef1aa58 100644 (file)
@@ -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)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
index c819c23b55b1aeb3ca477fd6c689c9cbc0134ff3..b7d4c7265ec66ec226b04e5b6120b6b1c48e316c 100644 (file)
@@ -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;
index 2936204d8ad629f367cbdc00af8156ffd14bf5a5..b691292ff59969fcafc3607ad7f426cc289d1ec9 100644 (file)
@@ -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)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
index 70ab75e7c263174a3a45020d7c503d21d3c1aa89..fe438bf119f61204b86bc17dc577e86991acfbb7 100644 (file)
@@ -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)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
index 09e9a9d96410942dcfe21bb2d0484ee8f0956693..84b8b485e95bd8b57b6a11685a2cf64cd317d704 100644 (file)
@@ -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;
+       u                     channel;
+       u                     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"));
        }
index f0cca3ea93b20b8d4f72279480ac56e81e681b13..c417ae0b5fe61c017da74fd45d4cd593cc49cd45 100644 (file)
@@ -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
@@ -2681,285 +2672,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
        return 1;               /* currently means nothing really */
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *     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);
index 187c8af0890b3e6590b61aa9783d0b3238fd2ad9..843c01a6aa0ecc817571629e49dd7bf28ec21ce6 100644 (file)
@@ -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)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  *     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
 
 #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);
index 203c661d2c79c782324b849fa57589289da95e09..c31a9e3c8a26c91bb6ca48e0db622212bc173eff 100644 (file)
@@ -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;
index 88642dec080c086e36023dcd6ffc877032d3e63e..421da1e7c0ead283aaf6046ef108e981017c6887 100644 (file)
@@ -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;
 }
 
 /**
index cda0cc095ad1bb9b862d7c9049a17d76dc38807b..01386ac688a27887e32cd75dfa336a2c4611f5d9 100644 (file)
@@ -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 **);
index 4b3ae3f22e78c448c21d28318adf3726e95c8c28..ef16f7ca4bb1cf1001010cf2c41854391edc6b09 100644 (file)
@@ -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++;
+       }
 }
 
 /*
index 68103e508db7077455dd437db6eae86797d63c0c..88e061d13d0bd69355e6f060b7a8b9c5e5e331fb 100644 (file)
@@ -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);
index f38822db4210886f8654c33bd03a3e2dd15635b9..841e1bb27d57eb54ae0142c2c64e4009fdb1cc51 100644 (file)
@@ -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
index 9c37943108792af5723ff0a394dee6888ea26571..93b41f45638a92411e7719c6c368bbcc7a0d86cf 100644 (file)
@@ -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
index 3075204915c867b532509788e18668393840dd0b..e874b8944875c77cb1d41df5004fbfa5eae08e9f 100644 (file)
@@ -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') {
index cca6d45eee4da90a13e6b8dba1210f4fcf38accc..bfbfb5c3a8f65281a42db90626925ce94da92f4f 100644 (file)
@@ -233,12 +233,6 @@ enum BusLogic_BIOS_DiskGeometryTranslation {
 } PACKED;
 
 
-/*
-  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 *);
 
index 7c00680495867d0a81a2f81d379a270fb1ff846a..a7f916c0c9cdcc618476eecf3dcca083065d8d9c 100644 (file)
@@ -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);
 
index 7869c34a4a3eed46f82c281adc238aa48e5591df..5bf3f07870ba14f86a5805e3e9f13260420ba564 100644 (file)
@@ -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
index bd7c9888f7f40ca31052e1fa62796fbb08fb9e37..79ecf4ebe6ebea59b3b662f88ae6fae2d15a526c 100644 (file)
@@ -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
index 9859cd17fc574ffe4d7791ab7369039f07241f14..f12864abed2f1c99cf52803a989178bee09df122 100644 (file)
@@ -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);
index 28d133a3094f85ca11824311660561d1f488154b..f1cca4ee541006c6767b5242f124dfcefcc6d6a0 100644 (file)
@@ -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
index 426cd6f49f5db6ad1ddcd01de7bbd2e7850d3b47..ddb33b06e0efffcbaf27b43b13c5102c34b1e7f2 100644 (file)
@@ -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
         */
index 4f8b4c53d435867da99381898093ab5cc393dec5..39ecd0d22eb0dcc5e1b6397ec98ee84903a0c8da 100644 (file)
@@ -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);
index 6d305b2f854e2fad06e869ac05c996351cb21c7e..df67ba686023d891a234c3ed9e577a632847e1db 100644 (file)
@@ -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");
index 4893a6d06a332ac6f32500f3e0ebc3a1a7183838..1b97f60652ba2cacdcf9bc9c4d3170c4d6f92adf 100644 (file)
@@ -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;
index d2cf875af59b6139fa99f63257b1e189fc22551a..a9734e08fe28a7cf35d01727a0ab509c0aff7da3 100644 (file)
@@ -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 (file)
index 0000000..c76b611
--- /dev/null
@@ -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);
+}
index 643f23b5ded884a2e11b79df58e36eaa27d66dc0..d953c3fe998aa99c159bca641903c5e48a7e9d8f 100644 (file)
 
 #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);
 }
index dcc8b0ea7a9d213b4605857c574702a059cbb869..c632d9354a261a5af10e9407f38d04bfcabd9bd3 100644 (file)
 
 #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;
 }
@@ -114,6 +114,26 @@ static void aac_rx_disable_interrupt(struct aac_dev *dev)
        rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
 }
 
+/**
+ *     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
@@ -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;
 }
 
@@ -429,6 +480,31 @@ static int aac_rx_restart_adapter(struct aac_dev *dev)
        return 0;
 }
 
+/**
+ *     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);
 }
index 511b0a938fb18b4ebcd488b1fe5087e385bc0cdd..8535db068c2f7de3dcd51a824a2ad47064083414 100644 (file)
@@ -91,6 +91,17 @@ static void aac_sa_disable_interrupt (struct aac_dev *dev)
        sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
 }
 
+/**
+ *     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
@@ -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:
index 306bec355e45c9abc80b03631c23c64616983346..9b3303b64113780b6eff7abfc296b30036fb2b84 100644 (file)
@@ -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);
         }
index 170a4344cbb2a62ee9446dd57e40339a1b7d98ff..27adbb294ac1db21cc0b962714f29020a89805bb 100644 (file)
@@ -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);
index 07a86a30f676c4d2c64afec835ce44f01201a697..9ddc6e4a74b040d497620675f0cd5dfcf7256078 100644 (file)
@@ -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)
 {
index 9bfcca5ede088c0c78a8645525376e3b1cf0eb45..c7fe478f481377d4b7add47574c6c3463dbd7b7a 100644 (file)
@@ -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
index 3a67fc578d78051f6f43b4643e26e54eb4b356b2..147c83c456a57cdfbd20206dba14c50b8c68daa3 100644 (file)
@@ -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;
index 1a3ab6aa856bb158e79574a4856e8374bbeb5127..c62ce41f2793750627130b0367547e3cf6fab736 100644 (file)
@@ -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);
index 2cf7bb3123f099c732ba665c514b085ee0eb60e1..8d72bbae96ad1a59a3777b662d8e47b640abc0c1 100644 (file)
@@ -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
 
index 6f8901b748f737c676d0c22226f06117e09a545e..c520e5b41fb52288982d73ac2ce46362407938d5 100644 (file)
 
 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);
 }
index e6ade5996d9592ebaf5ab6454d59aac8cfb965a9..6bd8e3059d27d8a551b823c7dc54007f956d3380 100644 (file)
@@ -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);
index fbc82b00a418cf8ff6d43603a36ca75f2a83fa81..bc7744e35ad0369a27d7e3b38a3e0048bf047ce2 100644 (file)
@@ -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);
index a11f4e6d8bd93698260a7c574deda49bfb325d5e..a43e8cdf4ee4fce658899fc5713a1d77219412b4 100644 (file)
 #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)
index 9050e93bfd5e9be8bf9dbe49843b71315058c1d3..fa7c5290257d708f52ba5b1053bd3d8412c2a21b 100644 (file)
@@ -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 */
index 75ed6b0569d1ad9243e8be51e265f7df144abbd6..8f43ff772f2378290d99af151a409b7dd19d6792 100644 (file)
@@ -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:
index e5a0ec37e9544caf9703be97d618e7ab2a7c23be..5b0932f6147389c5c0919a799036b75b2b69b3ed 100644 (file)
@@ -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;
index 845112539d05bd02617e3abae81e83a80ab75a35..eae7a247becebf8d6f512dcd7fba384aa5aa7957 100644 (file)
@@ -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);
index 9e715e5496af93b4a585b9764a645d7dcbd2db86..9437ff0ae3a4f6ce9852c8c08a2b48588db3ea2b 100644 (file)
@@ -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
index d202ed5a6709560b5793bcb53c6314b1ea3b967d..e2ad5bed94035c0dd594c237e0c59a8dba3dd1c1 100644 (file)
@@ -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:
index 61234384503b6ac28bb82216d26cd474a84009e1..9a14a6d9727548039051e3999f0a8817e076cfce 100644 (file)
@@ -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:
index 821386c7b57639e8c1ad5098a3de4635a6a57429..95045e33710d488b758374d17956f0f4074b837a 100644 (file)
@@ -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) {
@@ -6354,6 +6347,24 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
        return IPR_RC_JOB_CONTINUE;
 }
 
+/**
+ * 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);
index 9f62a1d4d5118b0e197d15ea44d2ba07ff5f9424..88f285de97bb22ab45c607c8026da1dd0438830e 100644 (file)
@@ -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
index f0871c3ac3d98d279a7d465c487b3b7bd70da65d..2aae1b081fcf405ee864f0284effe43ff3e45aec 100644 (file)
@@ -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);
index fb7df7b758112b59359e6bc2d37b8afe11f18c66..a65598b1e5363b386c6a235f8d7c3e61ffe834bb 100644 (file)
@@ -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;
 }
index d83392ee6823f09dab380b1008d2e2bbbf0031ba..9db30fb5caf2e1be01aa27b5433aa78d63889eb4 100644 (file)
@@ -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)
index d31e6fa466f79668f151c0d0c301bbccf27c848f..dc70c180e1155ee98c88ab0e7b03975190145d87 100644 (file)
@@ -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 ---------- */
index 2f0c07fc3f48c1da732c37e4862727b976595432..965698c8b7bff407cf2157922b93e7895ede92e7 100644 (file)
@@ -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,
index 137d7e496b6d99ab6d1f6c8cbac094e27d072760..a78638df2018dd50cb8fb420076052252f130ffc 100644 (file)
@@ -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,
index 971c37ceecb4a517fbba785e35b951545d4f8208..e1e2d085c920918dc508d4ec8d67dfad98095450 100644 (file)
@@ -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;
 }
index 22672d54aa2742d7c515f6c89f818b4159b49a22..897a5e2c55e438a806c6e93072547a7386922832 100644 (file)
@@ -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);
index 3052869f51f4fadf9eda7c923db07115748664cb..170399ef06f4ac3e7bcd5de6e343765588c6e419 100644 (file)
@@ -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
index b50e27e660244ebf6e11a79adb8543557981742b..26e1e6c55654e0a71b4e272eac98ec6a43ec90fd 100644 (file)
 
 /**
  * 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
index b8aa34202ec334cd296dc911dac9c754a27875bc..706fa05a187af715c9abc50fbf47cac4f8fcd2f2 100644 (file)
 
 #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
index 7bac86dda88f9fdc053105ae149e9c9753125421..04d0b6918c6167749dcac06d8ab9e8152f031995 100644 (file)
  *        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)
@@ -3379,14 +3384,92 @@ 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)
index 2b5a3285f799829b840baf04d603e03dc8835ec9..9de803cebd4badec858161d679a0b85905b9026a 100644 (file)
@@ -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
index d85b9a8f1b8d94e5040e598b35b957f9a90ff1a7..c1ff20c4747d960351561c8a954f46ece69cd94c 100644 (file)
@@ -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)
index 55eddcf8eb156896138d07e75ce79f362e65aadf..cacb3ad92527cd44eac2a31a7b4007fdaac4ee17 100644 (file)
@@ -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
 #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
 #define MR_DCMD_CLUSTER_RESET_ALL              0x08010100
 #define MR_DCMD_CLUSTER_RESET_LD               0x08010200
 
-/**
+/*
  * MFI command completion codes
  */
 enum MFI_STAT {
index 625ca97da52d526893e690a85c805b88f5d2817c..9102cbdf13594321724195fba9f80b907b4d9ca0 100644 (file)
@@ -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 */
index 7b18a6c7b7eb0de125e2cd7bfb2581c786378de5..8081b637d97e06550253eb0ddb12bfba0ef27ba5 100644 (file)
@@ -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;
 }
 
index 2c10130d9e03fe2a037f361ed80ef80963aa8f8b..05f4f2a378eb6d14635f2e8e7ee5f0db904565d4 100644 (file)
@@ -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;
 
 
index e4dd12f4b80eaf014d84f9e837a9cc8c3901ab12..74544ae4b0e270128de9976c4397b31703802dad 100644 (file)
@@ -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.
  */
index b3dac26ddba3e50767c852aecaf07921bf4f363a..98c01cd5e1a82a954eef3822ecde52689459d84d 100644 (file)
@@ -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
index 39fd17b05be5ada3d3da55515c2d89bba857cd71..d4885616cd39c19077e72b2f083f563ec5cb2ad9 100644 (file)
@@ -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);
+}
index 077e5789beeb0870742c5720e8d13e5a5d58c9bf..83376f6ac3dbb0c108e9ed5fd986dcc879d06739 100644 (file)
@@ -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;
index d6445ae841ba965896c8993fce3ab38ae899f0e4..68f5d24b938b06c28ecf177c6ad6ae71a55a257a 100644 (file)
@@ -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)
index 15390ad87456399a774ac65e25a5f519216adf15..ff1dd4175a7f1deb2a8e320e64d98055feca39ef 100644 (file)
@@ -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;
+}
index 459e0d6bd2b4d67757a57abd435afa5500dfa94d..61347aee55ce3da85fb49bee3db60a11a5f706ea 100644 (file)
@@ -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
index 24cffd98ee63546ce716e0277812dda9bafd08d2..f33e2eb9f1b9b657ce0ea582a6007681c53f5b86 100644 (file)
@@ -672,27 +672,6 @@ void __scsi_done(struct scsi_cmnd *cmd)
        blk_complete_request(rq);
 }
 
-/*
- * 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
  *
index 30ee3d72c02151f0b56ca9b69b9c7d10aff7bbff..5adbbeedec38ce485d9f7269a4e2efb1320976f9 100644 (file)
 #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__);
index 2ecb6ff42444697d9aa866de4bb00c0d707880b5..b8edcf5b54511be2f10fc9690fd01fbdd4dfb99e 100644 (file)
@@ -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:
@@ -452,6 +457,128 @@ static void scsi_eh_done(struct scsi_cmnd *scmd)
                complete(eh_action);
 }
 
+/**
+ * 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
@@ -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.
@@ -814,32 +911,6 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,
        return list_empty(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
@@ -970,64 +1041,6 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
        return list_empty(work_q);
 }
 
-/**
- * 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.
@@ -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.
index a1cd6e6a292aa887216837b77b6f2dc744b1a12f..9f7482d0b59489e7efccc347a8b7ce33208b4cdb 100644 (file)
@@ -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;
index f458c2f686d2364d4387ea0bc8b4d0afec6f8d4c..ee8efe849bf41c0c906c5a9f0769e9a054d483a2 100644 (file)
@@ -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);
index 96b7cbd746a84ac323d92bf6c72d0333515b3fd3..a43b9ec3aefd66f2953841c964cb2fd2c5746106 100644 (file)
@@ -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));
                        });
index 5c0b75bbfa10c9a78e2a9536ce3d12b83f789441..6d39150e205be19593e71406f672bee539ca9368 100644 (file)
@@ -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);
index 014d7fea1ff375d5a5c982c8d5c2f2d67d3be28b..6f56f8750635eca0e44ec6af2914a40f54b7c123 100644 (file)
@@ -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)
 
index 551baccec5230c57ec2fb3bcdf714d7969fe1fab..018c65f73ac48e8fef3350e17f346fab8cfff2d1 100644 (file)
@@ -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 (file)
index 0000000..6bc5051
--- /dev/null
@@ -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);
index 488ec7948a570766856436970a40aa2fd3813528..16e279be4a3e17dd4422192ffa473b9b285d15a1 100644 (file)
@@ -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]);
index 05a5cae126ec06e8c75c632821f8a6d8548236eb..50f3deb1f9ed92fcaf06bcc8c62329e966db8750 100644 (file)
@@ -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;
index 0689e004a281e3b2fdcc7f8e1d5d6770b9b63180..ad0182ef7809bba62450e4788dfb658fd601ce8d 100644 (file)
@@ -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_ */
index 59633a82de47cd54dc6fa2cb6fcf09b9a1e270d4..9aedc19820b0df1d007b0d8e7150de5e3c07e5fd 100644 (file)
@@ -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 *);
 
index da180f738477ef23040d68549c953969e7c524ff..286e9628ed8ba077f997e4105f6954e10d0d6c13 100644 (file)
@@ -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)