Merge ../linux-2.6/
authorJames Bottomley <jejb@mulgrave.il.steeleye.com>
Wed, 28 Jun 2006 18:06:39 +0000 (14:06 -0400)
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>
Wed, 28 Jun 2006 18:06:39 +0000 (14:06 -0400)
Conflicts:

drivers/scsi/aacraid/comminit.c

Fixed up by removing the now renamed CONFIG_IOMMU option from
aacraid

Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
61 files changed:
Documentation/scsi/ChangeLog.megaraid_sas
drivers/message/fusion/Makefile
drivers/message/fusion/lsi/fc_log.h [deleted file]
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/lsi/mpi_targ.h
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptbase.h
drivers/message/fusion/mptfc.c
drivers/message/fusion/mptsas.c
drivers/message/fusion/mptspi.c
drivers/scsi/53c700.c
drivers/scsi/aacraid/comminit.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_proc.c
drivers/scsi/atp870u.c
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/ibmvscsi/rpa_vscsi.c
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/megaraid/megaraid_sas.c
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/nsp32.c
drivers/scsi/pcmcia/nsp_cs.c
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_dbg.h
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_devtbl.h
drivers/scsi/qla2xxx/qla_fw.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_version.h
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_devinfo.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_priv.h
drivers/scsi/scsi_sas_internal.h
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_transport_fc.c
drivers/scsi/scsi_transport_sas.c
drivers/scsi/scsicam.c
drivers/scsi/sd.c
drivers/scsi/sr.c
include/scsi/scsi_cmnd.h
include/scsi/scsi_host.h
include/scsi/scsi_transport_sas.h

index 0a85a7e..d9e5960 100644 (file)
@@ -1,4 +1,20 @@
 
+1 Release Date    : Sun May 14 22:49:52 PDT 2006 - Sumant Patro <Sumant.Patro@lsil.com>
+2 Current Version : 00.00.03.01
+3 Older Version   : 00.00.02.04
+
+i.     Added support for ZCR controller.
+
+               New device id 0x413 added.
+
+ii.    Bug fix : Disable controller interrupt before firing INIT cmd to FW.
+
+               Interrupt is enabled after required initialization is over.
+               This is done to ensure that driver is ready to handle interrupts when
+               it is generated by the controller.
+
+               -Sumant Patro <Sumant.Patro@lsil.com>
+
 1 Release Date    : Wed Feb 03 14:31:44 PST 2006 - Sumant Patro <Sumant.Patro@lsil.com>
 2 Current Version : 00.00.02.04
 3 Older Version   : 00.00.02.04 
index 51740b3..b114236 100644 (file)
 #  For mptfc:
 #CFLAGS_mptfc.o += -DMPT_DEBUG_FC
 
+#  For mptsas:
+#CFLAGS_mptsas.o += -DMPT_DEBUG_SAS
+#CFLAGS_mptsas.o += -DMPT_DEBUG_SAS_WIDE
+
+
 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
 
 obj-$(CONFIG_FUSION_SPI)       += mptbase.o mptscsih.o mptspi.o
diff --git a/drivers/message/fusion/lsi/fc_log.h b/drivers/message/fusion/lsi/fc_log.h
deleted file mode 100644 (file)
index dc98d46..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *  Copyright (c) 2000-2001 LSI Logic Corporation. All rights reserved.
- *
- *  NAME:           fc_log.h
- *  SUMMARY:        MPI IocLogInfo definitions for the SYMFC9xx chips
- *  DESCRIPTION:    Contains the enumerated list of values that may be returned
- *                  in the IOCLogInfo field of a MPI Default Reply Message.
- *
- *  CREATION DATE:  6/02/2000
- *  ID:             $Id: fc_log.h,v 4.6 2001/07/26 14:41:33 sschremm Exp $
- */
-
-
-/*
- * MpiIocLogInfo_t enum
- *
- * These 32 bit values are used in the IOCLogInfo field of the MPI reply
- * messages.
- * The value is 0xabcccccc where
- *          a = The type of log info as per the MPI spec. Since these codes are
- *              all for Fibre Channel this value will always be 2.
- *          b = Specifies a subclass of the firmware where
- *                  0 = FCP Initiator
- *                  1 = FCP Target
- *                  2 = LAN
- *                  3 = MPI Message Layer
- *                  4 = FC Link
- *                  5 = Context Manager
- *                  6 = Invalid Field Offset
- *                  7 = State Change Info
- *                  all others are reserved for future use
- *          c = A specific value within the subclass.
- *
- * NOTE: Any new values should be added to the end of each subclass so that the
- *       codes remain consistent across firmware releases.
- */
-typedef enum _MpiIocLogInfoFc
-{
-    MPI_IOCLOGINFO_FC_INIT_BASE                     = 0x20000000,
-    MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME = 0x20000001, /* received an out of order frame - unsupported */
-    MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primative */
-    MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME   = 0x20000003, /* Bad Rx Frame, bad end of frame primative */
-    MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN           = 0x20000004, /* Bad Rx Frame, overrun */
-    MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER           = 0x20000005, /* Other errors caught by IOC which require retries */
-    MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD       = 0x20000006, /* Main processor could not initialize sub-processor */
-    MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OVERRUN         = 0x20000007, /* Scatter Gather overrun  */
-    MPI_IOCLOGINFO_FC_INIT_ERROR_RX_BAD_STATUS      = 0x20000008, /* Receiver detected context mismatch via invalid header */
-    MPI_IOCLOGINFO_FC_INIT_ERROR_RX_UNEXPECTED_FRAME= 0x20000009, /* CtxMgr detected unsupported frame type  */
-    MPI_IOCLOGINFO_FC_INIT_ERROR_LINK_FAILURE       = 0x2000000A, /* Link failure occurred  */
-    MPI_IOCLOGINFO_FC_INIT_ERROR_TX_TIMEOUT         = 0x2000000B, /* Transmitter timeout error */
-
-    MPI_IOCLOGINFO_FC_TARGET_BASE                   = 0x21000000,
-    MPI_IOCLOGINFO_FC_TARGET_NO_PDISC               = 0x21000001, /* not sent because we are waiting for a PDISC from the initiator */
-    MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN               = 0x21000002, /* not sent because we are not logged in to the remote node */
-    MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP     = 0x21000003, /* Data Out, Auto Response, not sent due to a LIP */
-    MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP     = 0x21000004, /* Data In, Auto Response, not sent due to a LIP */
-    MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA      = 0x21000005, /* Data In, Auto Response, missing data frames */
-    MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP     = 0x21000006, /* Data Out, No Response, not sent due to a LIP */
-    MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP     = 0x21000007, /* Auto-response after a write not sent due to a LIP */
-    MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP     = 0x21000008, /* Data In, No Response, not completed due to a LIP */
-    MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA      = 0x21000009, /* Data In, No Response, missing data frames */
-    MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP     = 0x2100000a, /* Manual Response not sent due to a LIP */
-    MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3             = 0x2100000b, /* not sent because remote node does not support Class 3 */
-    MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID        = 0x2100000c, /* not sent because login to remote node not validated */
-    MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND          = 0x2100000e, /* cleared from the outbound queue after a logout */
-    MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN    = 0x2100000f, /* cleared waiting for data after a logout */
-
-    MPI_IOCLOGINFO_FC_LAN_BASE                      = 0x22000000,
-    MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING         = 0x22000001, /* Transaction Context Sgl Missing */
-    MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE         = 0x22000002, /* Transaction Context found before an EOB */
-    MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET        = 0x22000003, /* Transaction Context value has reserved bits set */
-    MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG            = 0x22000004, /* Invalid SGL Flags */
-
-    MPI_IOCLOGINFO_FC_MSG_BASE                      = 0x23000000,
-
-    MPI_IOCLOGINFO_FC_LINK_BASE                     = 0x24000000,
-    MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT        = 0x24000001, /* Loop initialization timed out */
-    MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED      = 0x24000002, /* Another system controller already initialized the loop */
-    MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED     = 0x24000003, /* Not synchronized to signal or still negotiating (possible cable problem) */
-    MPI_IOCLOGINFO_FC_LINK_CRC_ERROR                = 0x24000004, /* CRC check detected error on received frame */
-
-    MPI_IOCLOGINFO_FC_CTX_BASE                      = 0x25000000,
-
-    MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET     = 0x26000000, /* The lower 24 bits give the byte offset of the field in the request message that is invalid */
-    MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET      = 0x26ffffff,
-
-    MPI_IOCLOGINFO_FC_STATE_CHANGE                  = 0x27000000  /* The lower 24 bits give additional information concerning state change */
-
-} MpiIocLogInfoFc_t;
index 02cdc84..81ad776 100644 (file)
@@ -6,7 +6,7 @@
  *          Title:  MPI Message independent structures and definitions
  *  Creation Date:  July 27, 2000
  *
- *    mpi.h Version:  01.05.10
+ *    mpi.h Version:  01.05.11
  *
  *  Version History
  *  ---------------
@@ -76,6 +76,7 @@
  *                      Added EEDP IOCStatus codes.
  *  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.
  *  --------------------------------------------------------------------------
  */
 
 /* Note: The major versions of 0xe0 through 0xff are reserved */
 
 /* versioning for this MPI header set */
-#define MPI_HEADER_VERSION_UNIT             (0x0C)
+#define MPI_HEADER_VERSION_UNIT             (0x0D)
 #define MPI_HEADER_VERSION_DEV              (0x00)
 #define MPI_HEADER_VERSION_UNIT_MASK        (0xFF00)
 #define MPI_HEADER_VERSION_UNIT_SHIFT       (8)
index b1becec..47e13e3 100644 (file)
@@ -6,7 +6,7 @@
  *          Title:  MPI Config message, structures, and Pages
  *  Creation Date:  July 27, 2000
  *
- *    mpi_cnfg.h Version:  01.05.11
+ *    mpi_cnfg.h Version:  01.05.12
  *
  *  Version History
  *  ---------------
  *                      Added postpone SATA Init bit to SAS IO Unit Page 1
  *                      ControlFlags.
  *                      Changed LogEntry format for Log Page 0.
+ *  03-27-06  01.05.12  Added two new Flags defines for Manufacturing Page 4.
+ *                      Added Manufacturing Page 7.
+ *                      Added MPI_IOCPAGE2_CAP_FLAGS_RAID_64_BIT_ADDRESSING.
+ *                      Added IOC Page 6.
+ *                      Added PrevBootDeviceForm field to CONFIG_PAGE_BIOS_2.
+ *                      Added MaxLBAHigh field to RAID Volume Page 0.
+ *                      Added Nvdata version fields to SAS IO Unit Page 0.
+ *                      Added AdditionalControlFlags, MaxTargetPortConnectTime,
+ *                      ReportDeviceMissingDelay, and IODeviceMissingDelay
+ *                      fields to SAS IO Unit Page 1.
  *  --------------------------------------------------------------------------
  */
 
@@ -631,9 +641,11 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4
 } CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4,
   ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t;
 
-#define MPI_MANUFACTURING4_PAGEVERSION                  (0x03)
+#define MPI_MANUFACTURING4_PAGEVERSION                  (0x04)
 
 /* defines for the Flags field */
+#define MPI_MANPAGE4_FORCE_BAD_BLOCK_TABLE              (0x80)
+#define MPI_MANPAGE4_FORCE_OFFLINE_FAILOVER             (0x40)
 #define MPI_MANPAGE4_IME_DISABLE                        (0x20)
 #define MPI_MANPAGE4_IM_DISABLE                         (0x10)
 #define MPI_MANPAGE4_IS_DISABLE                         (0x08)
@@ -668,6 +680,66 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_6
 #define MPI_MANUFACTURING6_PAGEVERSION                  (0x00)
 
 
+typedef struct _MPI_MANPAGE7_CONNECTOR_INFO
+{
+    U32                         Pinout;                 /* 00h */
+    U8                          Connector[16];          /* 04h */
+    U8                          Location;               /* 14h */
+    U8                          Reserved1;              /* 15h */
+    U16                         Slot;                   /* 16h */
+    U32                         Reserved2;              /* 18h */
+} MPI_MANPAGE7_CONNECTOR_INFO, MPI_POINTER PTR_MPI_MANPAGE7_CONNECTOR_INFO,
+  MpiManPage7ConnectorInfo_t, MPI_POINTER pMpiManPage7ConnectorInfo_t;
+
+/* defines for the Pinout field */
+#define MPI_MANPAGE7_PINOUT_SFF_8484_L4                 (0x00080000)
+#define MPI_MANPAGE7_PINOUT_SFF_8484_L3                 (0x00040000)
+#define MPI_MANPAGE7_PINOUT_SFF_8484_L2                 (0x00020000)
+#define MPI_MANPAGE7_PINOUT_SFF_8484_L1                 (0x00010000)
+#define MPI_MANPAGE7_PINOUT_SFF_8470_L4                 (0x00000800)
+#define MPI_MANPAGE7_PINOUT_SFF_8470_L3                 (0x00000400)
+#define MPI_MANPAGE7_PINOUT_SFF_8470_L2                 (0x00000200)
+#define MPI_MANPAGE7_PINOUT_SFF_8470_L1                 (0x00000100)
+#define MPI_MANPAGE7_PINOUT_SFF_8482                    (0x00000002)
+#define MPI_MANPAGE7_PINOUT_CONNECTION_UNKNOWN          (0x00000001)
+
+/* defines for the Location field */
+#define MPI_MANPAGE7_LOCATION_UNKNOWN                   (0x01)
+#define MPI_MANPAGE7_LOCATION_INTERNAL                  (0x02)
+#define MPI_MANPAGE7_LOCATION_EXTERNAL                  (0x04)
+#define MPI_MANPAGE7_LOCATION_SWITCHABLE                (0x08)
+#define MPI_MANPAGE7_LOCATION_AUTO                      (0x10)
+#define MPI_MANPAGE7_LOCATION_NOT_PRESENT               (0x20)
+#define MPI_MANPAGE7_LOCATION_NOT_CONNECTED             (0x80)
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check NumPhys at runtime.
+ */
+#ifndef MPI_MANPAGE7_CONNECTOR_INFO_MAX
+#define MPI_MANPAGE7_CONNECTOR_INFO_MAX   (1)
+#endif
+
+typedef struct _CONFIG_PAGE_MANUFACTURING_7
+{
+    CONFIG_PAGE_HEADER          Header;                 /* 00h */
+    U32                         Reserved1;              /* 04h */
+    U32                         Reserved2;              /* 08h */
+    U32                         Flags;                  /* 0Ch */
+    U8                          EnclosureName[16];      /* 10h */
+    U8                          NumPhys;                /* 20h */
+    U8                          Reserved3;              /* 21h */
+    U16                         Reserved4;              /* 22h */
+    MPI_MANPAGE7_CONNECTOR_INFO ConnectorInfo[MPI_MANPAGE7_CONNECTOR_INFO_MAX]; /* 24h */
+} CONFIG_PAGE_MANUFACTURING_7, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_7,
+  ManufacturingPage7_t, MPI_POINTER pManufacturingPage7_t;
+
+#define MPI_MANUFACTURING7_PAGEVERSION                  (0x00)
+
+/* defines for the Flags field */
+#define MPI_MANPAGE7_FLAG_USE_SLOT_INFO                 (0x00000001)
+
+
 /****************************************************************************
 *   IO Unit Config Pages
 ****************************************************************************/
@@ -867,7 +939,7 @@ typedef struct _CONFIG_PAGE_IOC_2
 } CONFIG_PAGE_IOC_2, MPI_POINTER PTR_CONFIG_PAGE_IOC_2,
   IOCPage2_t, MPI_POINTER pIOCPage2_t;
 
-#define MPI_IOCPAGE2_PAGEVERSION                        (0x03)
+#define MPI_IOCPAGE2_PAGEVERSION                        (0x04)
 
 /* IOC Page 2 Capabilities flags */
 
@@ -878,6 +950,7 @@ typedef struct _CONFIG_PAGE_IOC_2
 #define MPI_IOCPAGE2_CAP_FLAGS_RAID_6_SUPPORT           (0x00000010)
 #define MPI_IOCPAGE2_CAP_FLAGS_RAID_10_SUPPORT          (0x00000020)
 #define MPI_IOCPAGE2_CAP_FLAGS_RAID_50_SUPPORT          (0x00000040)
+#define MPI_IOCPAGE2_CAP_FLAGS_RAID_64_BIT_ADDRESSING   (0x10000000)
 #define MPI_IOCPAGE2_CAP_FLAGS_SES_SUPPORT              (0x20000000)
 #define MPI_IOCPAGE2_CAP_FLAGS_SAFTE_SUPPORT            (0x40000000)
 #define MPI_IOCPAGE2_CAP_FLAGS_CROSS_CHANNEL_SUPPORT    (0x80000000)
@@ -975,6 +1048,44 @@ typedef struct _CONFIG_PAGE_IOC_5
 
 #define MPI_IOCPAGE5_PAGEVERSION                        (0x00)
 
+typedef struct _CONFIG_PAGE_IOC_6
+{
+    CONFIG_PAGE_HEADER          Header;                         /* 00h */
+    U32                         CapabilitiesFlags;              /* 04h */
+    U8                          MaxDrivesIS;                    /* 08h */
+    U8                          MaxDrivesIM;                    /* 09h */
+    U8                          MaxDrivesIME;                   /* 0Ah */
+    U8                          Reserved1;                      /* 0Bh */
+    U8                          MinDrivesIS;                    /* 0Ch */
+    U8                          MinDrivesIM;                    /* 0Dh */
+    U8                          MinDrivesIME;                   /* 0Eh */
+    U8                          Reserved2;                      /* 0Fh */
+    U8                          MaxGlobalHotSpares;             /* 10h */
+    U8                          Reserved3;                      /* 11h */
+    U16                         Reserved4;                      /* 12h */
+    U32                         Reserved5;                      /* 14h */
+    U32                         SupportedStripeSizeMapIS;       /* 18h */
+    U32                         SupportedStripeSizeMapIME;      /* 1Ch */
+    U32                         Reserved6;                      /* 20h */
+    U8                          MetadataSize;                   /* 24h */
+    U8                          Reserved7;                      /* 25h */
+    U16                         Reserved8;                      /* 26h */
+    U16                         MaxBadBlockTableEntries;        /* 28h */
+    U16                         Reserved9;                      /* 2Ah */
+    U16                         IRNvsramUsage;                  /* 2Ch */
+    U16                         Reserved10;                     /* 2Eh */
+    U32                         IRNvsramVersion;                /* 30h */
+    U32                         Reserved11;                     /* 34h */
+    U32                         Reserved12;                     /* 38h */
+} CONFIG_PAGE_IOC_6, MPI_POINTER PTR_CONFIG_PAGE_IOC_6,
+  IOCPage6_t, MPI_POINTER pIOCPage6_t;
+
+#define MPI_IOCPAGE6_PAGEVERSION                        (0x00)
+
+/* IOC Page 6 Capabilities Flags */
+
+#define MPI_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE         (0x00000001)
+
 
 /****************************************************************************
 *   BIOS Config Pages
@@ -1218,13 +1329,13 @@ typedef struct _CONFIG_PAGE_BIOS_2
     U32                         Reserved5;              /* 14h */
     U32                         Reserved6;              /* 18h */
     U8                          BootDeviceForm;         /* 1Ch */
-    U8                          Reserved7;              /* 1Dh */
+    U8                          PrevBootDeviceForm;     /* 1Ch */
     U16                         Reserved8;              /* 1Eh */
     MPI_BIOSPAGE2_BOOT_DEVICE   BootDevice;             /* 20h */
 } CONFIG_PAGE_BIOS_2, MPI_POINTER PTR_CONFIG_PAGE_BIOS_2,
   BIOSPage2_t, MPI_POINTER pBIOSPage2_t;
 
-#define MPI_BIOSPAGE2_PAGEVERSION                       (0x01)
+#define MPI_BIOSPAGE2_PAGEVERSION                       (0x02)
 
 #define MPI_BIOSPAGE2_FORM_MASK                         (0x0F)
 #define MPI_BIOSPAGE2_FORM_ADAPTER_ORDER                (0x00)
@@ -2080,7 +2191,7 @@ typedef struct _CONFIG_PAGE_RAID_VOL_0
     RAID_VOL0_STATUS        VolumeStatus;   /* 08h */
     RAID_VOL0_SETTINGS      VolumeSettings; /* 0Ch */
     U32                     MaxLBA;         /* 10h */
-    U32                     Reserved1;      /* 14h */
+    U32                     MaxLBAHigh;     /* 14h */
     U32                     StripeSize;     /* 18h */
     U32                     Reserved2;      /* 1Ch */
     U32                     Reserved3;      /* 20h */
@@ -2092,7 +2203,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                    (0x05)
+#define MPI_RAIDVOLPAGE0_PAGEVERSION                    (0x06)
 
 /* values for RAID Volume Page 0 InactiveStatus field */
 #define MPI_RAIDVOLPAGE0_UNKNOWN_INACTIVE               (0x00)
@@ -2324,7 +2435,8 @@ typedef struct _MPI_SAS_IO_UNIT0_PHY_DATA
 typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0
 {
     CONFIG_EXTENDED_PAGE_HEADER     Header;                             /* 00h */
-    U32                             Reserved1;                          /* 08h */
+    U16                             NvdataVersionDefault;               /* 08h */
+    U16                             NvdataVersionPersistent;            /* 0Ah */
     U8                              NumPhys;                            /* 0Ch */
     U8                              Reserved2;                          /* 0Dh */
     U16                             Reserved3;                          /* 0Eh */
@@ -2332,7 +2444,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0
 } CONFIG_PAGE_SAS_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_0,
   SasIOUnitPage0_t, MPI_POINTER pSasIOUnitPage0_t;
 
-#define MPI_SASIOUNITPAGE0_PAGEVERSION      (0x03)
+#define MPI_SASIOUNITPAGE0_PAGEVERSION      (0x04)
 
 /* values for SAS IO Unit Page 0 PortFlags */
 #define MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS    (0x08)
@@ -2373,12 +2485,13 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0
 
 typedef struct _MPI_SAS_IO_UNIT1_PHY_DATA
 {
-    U8          Port;                   /* 00h */
-    U8          PortFlags;              /* 01h */
-    U8          PhyFlags;               /* 02h */
-    U8          MaxMinLinkRate;         /* 03h */
-    U32         ControllerPhyDeviceInfo;/* 04h */
-    U32         Reserved1;              /* 08h */
+    U8          Port;                       /* 00h */
+    U8          PortFlags;                  /* 01h */
+    U8          PhyFlags;                   /* 02h */
+    U8          MaxMinLinkRate;             /* 03h */
+    U32         ControllerPhyDeviceInfo;    /* 04h */
+    U16         MaxTargetPortConnectTime;   /* 08h */
+    U16         Reserved1;                  /* 0Ah */
 } MPI_SAS_IO_UNIT1_PHY_DATA, MPI_POINTER PTR_MPI_SAS_IO_UNIT1_PHY_DATA,
   SasIOUnit1PhyData, MPI_POINTER pSasIOUnit1PhyData;
 
@@ -2395,15 +2508,17 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
     CONFIG_EXTENDED_PAGE_HEADER Header;                             /* 00h */
     U16                         ControlFlags;                       /* 08h */
     U16                         MaxNumSATATargets;                  /* 0Ah */
-    U32                         Reserved1;                          /* 0Ch */
+    U16                         AdditionalControlFlags;             /* 0Ch */
+    U16                         Reserved1;                          /* 0Eh */
     U8                          NumPhys;                            /* 10h */
     U8                          SATAMaxQDepth;                      /* 11h */
-    U16                         Reserved2;                          /* 12h */
+    U8                          ReportDeviceMissingDelay;           /* 12h */
+    U8                          IODeviceMissingDelay;               /* 13h */
     MPI_SAS_IO_UNIT1_PHY_DATA   PhyData[MPI_SAS_IOUNIT1_PHY_MAX];   /* 14h */
 } 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      (0x05)
+#define MPI_SASIOUNITPAGE1_PAGEVERSION      (0x06)
 
 /* values for SAS IO Unit Page 1 ControlFlags */
 #define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST            (0x8000)
@@ -2428,6 +2543,13 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
 #define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY         (0x0002)
 #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)
+
+/* defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */
+#define MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK         (0x7F)
+#define MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16              (0x80)
+
 /* values for SAS IO Unit Page 1 PortFlags */
 #define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM         (0x00)
 #define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM         (0x04)
index 4a5f8dd..582cfe7 100644 (file)
@@ -6,25 +6,25 @@
  Copyright (c) 2000-2005 LSI Logic Corporation.
 
  ---------------------------------------
- Header Set Release Version:    01.05.12
- Header Set Release Date:       08-30-05
+ Header Set Release Version:    01.05.13
+ Header Set Release Date:       03-27-06
  ---------------------------------------
 
  Filename               Current version     Prior version
  ----------             ---------------     -------------
- mpi.h                  01.05.10            01.05.09
- mpi_ioc.h              01.05.10            01.05.09
- mpi_cnfg.h             01.05.11            01.05.10
- mpi_init.h             01.05.06            01.05.06
- mpi_targ.h             01.05.05            01.05.05
+ 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_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.02            01.05.01
- mpi_type.h             01.05.02            01.05.01
- mpi_history.txt        01.05.12            01.05.11
+ mpi_sas.h              01.05.03            01.05.02
+ mpi_type.h             01.05.02            01.05.02
+ mpi_history.txt        01.05.13            01.05.12
 
 
  *  Date      Version   Description
@@ -93,6 +93,7 @@ mpi.h
  *                      Added EEDP IOCStatus codes.
  *  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.
  *  --------------------------------------------------------------------------
 
 mpi_ioc.h
@@ -170,6 +171,17 @@ mpi_ioc.h
  *                      Added new ReasonCode value for SAS Device Status Change
  *                      event.
  *                      Added new family code for FC949E.
+ *  03-27-06  01.05.11  Added MPI_IOCFACTS_CAPABILITY_TLR.
+ *                      Added additional Reason Codes and more event data fields
+ *                      to EVENT_DATA_SAS_DEVICE_STATUS_CHANGE.
+ *                      Added EVENT_DATA_SAS_BROADCAST_PRIMITIVE structure and
+ *                      new event.
+ *                      Added MPI_EVENT_SAS_SMP_ERROR and event data structure.
+ *                      Added MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE and event
+ *                      data structure.
+ *                      Added MPI_EVENT_SAS_INIT_TABLE_OVERFLOW and event
+ *                      data structure.
+ *                      Added MPI_EXT_IMAGE_TYPE_INITIALIZATION.
  *  --------------------------------------------------------------------------
 
 mpi_cnfg.h
@@ -425,6 +437,16 @@ mpi_cnfg.h
  *                      Added postpone SATA Init bit to SAS IO Unit Page 1
  *                      ControlFlags.
  *                      Changed LogEntry format for Log Page 0.
+ *  03-27-06  01.05.12  Added two new Flags defines for Manufacturing Page 4.
+ *                      Added Manufacturing Page 7.
+ *                      Added MPI_IOCPAGE2_CAP_FLAGS_RAID_64_BIT_ADDRESSING.
+ *                      Added IOC Page 6.
+ *                      Added PrevBootDeviceForm field to CONFIG_PAGE_BIOS_2.
+ *                      Added MaxLBAHigh field to RAID Volume Page 0.
+ *                      Added Nvdata version fields to SAS IO Unit Page 0.
+ *                      Added AdditionalControlFlags, MaxTargetPortConnectTime,
+ *                      ReportDeviceMissingDelay, and IODeviceMissingDelay
+ *                      fields to SAS IO Unit Page 1.
  *  --------------------------------------------------------------------------
 
 mpi_init.h
@@ -467,6 +489,7 @@ mpi_init.h
  *                      Added four new defines for SEP SlotStatus.
  *  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.
  *  --------------------------------------------------------------------------
 
 mpi_targ.h
@@ -511,6 +534,7 @@ mpi_targ.h
  *  02-22-05  01.05.03  Changed a comment.
  *  03-11-05  01.05.04  Removed TargetAssistExtended Request.
  *  06-24-05  01.05.05  Added TargetAssistExtended structures and defines.
+ *  03-27-06  01.05.06  Added a comment.
  *  --------------------------------------------------------------------------
 
 mpi_fc.h
@@ -610,6 +634,10 @@ mpi_sas.h
  *  08-30-05  01.05.02  Added DeviceInfo bit for SEP.
  *                      Added PrimFlags and Primitive field to SAS IO Unit
  *                      Control request, and added a new operation code.
+ *  03-27-06  01.05.03  Added Force Full Discovery, Transmit Port Select Signal,
+ *                      and Remove Device operations to SAS IO Unit Control.
+ *                      Added DevHandle field to SAS IO Unit Control request and
+ *                      reply.
  *  --------------------------------------------------------------------------
 
 mpi_type.h
@@ -625,20 +653,20 @@ mpi_type.h
 
 mpi_history.txt         Parts list history
 
-Filename    01.05.12  01.05.11  01.05.10  01.05.09
-----------  --------  --------  --------  --------
-mpi.h       01.05.10  01.05.09  01.05.08  01.05.07
-mpi_ioc.h   01.05.10  01.05.09  01.05.09  01.05.08
-mpi_cnfg.h  01.05.11  01.05.10  01.05.09  01.05.08
-mpi_init.h  01.05.06  01.05.06  01.05.05  01.05.04
-mpi_targ.h  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
-mpi_lan.h   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
-mpi_tool.h  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
-mpi_sas.h   01.05.02  01.05.01  01.05.01  01.05.01
-mpi_type.h  01.05.02  01.05.01  01.05.01  01.05.01
+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.08   01.05.07   01.05.06   01.05.05   01.05.04   01.05.03
 ----------  --------   --------   --------   --------   --------   --------
index 68941f4..c1c6789 100644 (file)
@@ -6,7 +6,7 @@
  *          Title:  MPI initiator mode messages and structures
  *  Creation Date:  June 8, 2000
  *
- *    mpi_init.h Version:  01.05.06
+ *    mpi_init.h Version:  01.05.07
  *
  *  Version History
  *  ---------------
@@ -52,6 +52,7 @@
  *                      Added four new defines for SEP SlotStatus.
  *  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.
  *  --------------------------------------------------------------------------
  */
 
@@ -427,6 +428,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)
 
 /* MsgFlags bits */
 #define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION   (0x00)
index 2c5f43f..18ba407 100644 (file)
@@ -6,7 +6,7 @@
  *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
  *  Creation Date:  August 11, 2000
  *
- *    mpi_ioc.h Version:  01.05.10
+ *    mpi_ioc.h Version:  01.05.11
  *
  *  Version History
  *  ---------------
  *                      Added new ReasonCode value for SAS Device Status Change
  *                      event.
  *                      Added new family code for FC949E.
+ *  03-27-06  01.05.11  Added MPI_IOCFACTS_CAPABILITY_TLR.
+ *                      Added additional Reason Codes and more event data fields
+ *                      to EVENT_DATA_SAS_DEVICE_STATUS_CHANGE.
+ *                      Added EVENT_DATA_SAS_BROADCAST_PRIMITIVE structure and
+ *                      new event.
+ *                      Added MPI_EVENT_SAS_SMP_ERROR and event data structure.
+ *                      Added MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE and event
+ *                      data structure.
+ *                      Added MPI_EVENT_SAS_INIT_TABLE_OVERFLOW and event
+ *                      data structure.
+ *                      Added MPI_EXT_IMAGE_TYPE_INITIALIZATION.
  *  --------------------------------------------------------------------------
  */
 
@@ -272,6 +283,7 @@ typedef struct _MSG_IOC_FACTS_REPLY
 #define MPI_IOCFACTS_CAPABILITY_MULTICAST               (0x00000100)
 #define MPI_IOCFACTS_CAPABILITY_SCSIIO32                (0x00000200)
 #define MPI_IOCFACTS_CAPABILITY_NO_SCSIIO16             (0x00000400)
+#define MPI_IOCFACTS_CAPABILITY_TLR                     (0x00000800)
 
 
 /*****************************************************************************
@@ -448,30 +460,34 @@ typedef struct _MSG_EVENT_ACK_REPLY
 
 /* Event */
 
-#define MPI_EVENT_NONE                      (0x00000000)
-#define MPI_EVENT_LOG_DATA                  (0x00000001)
-#define MPI_EVENT_STATE_CHANGE              (0x00000002)
-#define MPI_EVENT_UNIT_ATTENTION            (0x00000003)
-#define MPI_EVENT_IOC_BUS_RESET             (0x00000004)
-#define MPI_EVENT_EXT_BUS_RESET             (0x00000005)
-#define MPI_EVENT_RESCAN                    (0x00000006)
-#define MPI_EVENT_LINK_STATUS_CHANGE        (0x00000007)
-#define MPI_EVENT_LOOP_STATE_CHANGE         (0x00000008)
-#define MPI_EVENT_LOGOUT                    (0x00000009)
-#define MPI_EVENT_EVENT_CHANGE              (0x0000000A)
-#define MPI_EVENT_INTEGRATED_RAID           (0x0000000B)
-#define MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE (0x0000000C)
-#define MPI_EVENT_ON_BUS_TIMER_EXPIRED      (0x0000000D)
-#define MPI_EVENT_QUEUE_FULL                (0x0000000E)
-#define MPI_EVENT_SAS_DEVICE_STATUS_CHANGE  (0x0000000F)
-#define MPI_EVENT_SAS_SES                   (0x00000010)
-#define MPI_EVENT_PERSISTENT_TABLE_FULL     (0x00000011)
-#define MPI_EVENT_SAS_PHY_LINK_STATUS       (0x00000012)
-#define MPI_EVENT_SAS_DISCOVERY_ERROR       (0x00000013)
-#define MPI_EVENT_IR_RESYNC_UPDATE          (0x00000014)
-#define MPI_EVENT_IR2                       (0x00000015)
-#define MPI_EVENT_SAS_DISCOVERY             (0x00000016)
-#define MPI_EVENT_LOG_ENTRY_ADDED           (0x00000021)
+#define MPI_EVENT_NONE                          (0x00000000)
+#define MPI_EVENT_LOG_DATA                      (0x00000001)
+#define MPI_EVENT_STATE_CHANGE                  (0x00000002)
+#define MPI_EVENT_UNIT_ATTENTION                (0x00000003)
+#define MPI_EVENT_IOC_BUS_RESET                 (0x00000004)
+#define MPI_EVENT_EXT_BUS_RESET                 (0x00000005)
+#define MPI_EVENT_RESCAN                        (0x00000006)
+#define MPI_EVENT_LINK_STATUS_CHANGE            (0x00000007)
+#define MPI_EVENT_LOOP_STATE_CHANGE             (0x00000008)
+#define MPI_EVENT_LOGOUT                        (0x00000009)
+#define MPI_EVENT_EVENT_CHANGE                  (0x0000000A)
+#define MPI_EVENT_INTEGRATED_RAID               (0x0000000B)
+#define MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE     (0x0000000C)
+#define MPI_EVENT_ON_BUS_TIMER_EXPIRED          (0x0000000D)
+#define MPI_EVENT_QUEUE_FULL                    (0x0000000E)
+#define MPI_EVENT_SAS_DEVICE_STATUS_CHANGE      (0x0000000F)
+#define MPI_EVENT_SAS_SES                       (0x00000010)
+#define MPI_EVENT_PERSISTENT_TABLE_FULL         (0x00000011)
+#define MPI_EVENT_SAS_PHY_LINK_STATUS           (0x00000012)
+#define MPI_EVENT_SAS_DISCOVERY_ERROR           (0x00000013)
+#define MPI_EVENT_IR_RESYNC_UPDATE              (0x00000014)
+#define MPI_EVENT_IR2                           (0x00000015)
+#define MPI_EVENT_SAS_DISCOVERY                 (0x00000016)
+#define MPI_EVENT_SAS_BROADCAST_PRIMITIVE       (0x00000017)
+#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_LOG_ENTRY_ADDED               (0x00000021)
 
 /* AckRequired field values */
 
@@ -558,18 +574,25 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
     U8                      PhyNum;                     /* 0Eh */
     U8                      Reserved1;                  /* 0Fh */
     U64                     SASAddress;                 /* 10h */
+    U8                      LUN[8];                     /* 18h */
+    U16                     TaskTag;                    /* 20h */
+    U16                     Reserved2;                  /* 22h */
 } EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
   MPI_POINTER PTR_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
   MpiEventDataSasDeviceStatusChange_t,
   MPI_POINTER pMpiEventDataSasDeviceStatusChange_t;
 
 /* MPI SAS Device Status Change Event data ReasonCode values */
-#define MPI_EVENT_SAS_DEV_STAT_RC_ADDED                 (0x03)
-#define MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING        (0x04)
-#define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA            (0x05)
-#define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED      (0x06)
-#define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED           (0x07)
-#define MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08)
+#define MPI_EVENT_SAS_DEV_STAT_RC_ADDED                     (0x03)
+#define MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING            (0x04)
+#define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA                (0x05)
+#define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED          (0x06)
+#define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED               (0x07)
+#define MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET     (0x08)
+#define MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL       (0x09)
+#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)
 
 
 /* SCSI Event data for Queue Full event */
@@ -742,6 +765,27 @@ typedef struct _EVENT_DATA_SAS_SES
 } EVENT_DATA_SAS_SES, MPI_POINTER PTR_EVENT_DATA_SAS_SES,
   MpiEventDataSasSes_t, MPI_POINTER pMpiEventDataSasSes_t;
 
+/* SAS Broadcast Primitive Event data */
+
+typedef struct _EVENT_DATA_SAS_BROADCAST_PRIMITIVE
+{
+    U8                      PhyNum;                     /* 00h */
+    U8                      Port;                       /* 01h */
+    U8                      PortWidth;                  /* 02h */
+    U8                      Primitive;                  /* 04h */
+} EVENT_DATA_SAS_BROADCAST_PRIMITIVE,
+  MPI_POINTER PTR_EVENT_DATA_SAS_BROADCAST_PRIMITIVE,
+  MpiEventDataSasBroadcastPrimitive_t,
+  MPI_POINTER pMpiEventDataSasBroadcastPrimitive_t;
+
+#define MPI_EVENT_PRIMITIVE_CHANGE              (0x01)
+#define MPI_EVENT_PRIMITIVE_EXPANDER            (0x03)
+#define MPI_EVENT_PRIMITIVE_RESERVED2           (0x04)
+#define MPI_EVENT_PRIMITIVE_RESERVED3           (0x05)
+#define MPI_EVENT_PRIMITIVE_RESERVED4           (0x06)
+#define MPI_EVENT_PRIMITIVE_CHANGE0_RESERVED    (0x07)
+#define MPI_EVENT_PRIMITIVE_CHANGE1_RESERVED    (0x08)
+
 /* SAS Phy Link Status Event data */
 
 typedef struct _EVENT_DATA_SAS_PHY_LINK_STATUS
@@ -804,6 +848,53 @@ typedef struct _EVENT_DATA_DISCOVERY_ERROR
 #define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_PATHS                (0x00000800)
 #define MPI_EVENT_DSCVRY_ERR_DS_MAX_SATA_TARGETS            (0x00001000)
 
+/* SAS SMP Error Event data */
+
+typedef struct _EVENT_DATA_SAS_SMP_ERROR
+{
+    U8                      Status;                     /* 00h */
+    U8                      Port;                       /* 01h */
+    U8                      SMPFunctionResult;          /* 02h */
+    U8                      Reserved1;                  /* 03h */
+    U64                     SASAddress;                 /* 04h */
+} EVENT_DATA_SAS_SMP_ERROR, MPI_POINTER PTR_EVENT_DATA_SAS_SMP_ERROR,
+  MpiEventDataSasSmpError_t, MPI_POINTER pMpiEventDataSasSmpError_t;
+
+/* defines for the Status field of the SAS SMP Error event */
+#define MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID         (0x00)
+#define MPI_EVENT_SAS_SMP_CRC_ERROR                     (0x01)
+#define MPI_EVENT_SAS_SMP_TIMEOUT                       (0x02)
+#define MPI_EVENT_SAS_SMP_NO_DESTINATION                (0x03)
+#define MPI_EVENT_SAS_SMP_BAD_DESTINATION               (0x04)
+
+/* SAS Initiator Device Status Change Event data */
+
+typedef struct _EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE
+{
+    U8                      ReasonCode;                 /* 00h */
+    U8                      Port;                       /* 01h */
+    U16                     DevHandle;                  /* 02h */
+    U64                     SASAddress;                 /* 04h */
+} EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE,
+  MPI_POINTER PTR_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE,
+  MpiEventDataSasInitDevStatusChange_t,
+  MPI_POINTER pMpiEventDataSasInitDevStatusChange_t;
+
+/* defines for the ReasonCode field of the SAS Initiator Device Status Change event */
+#define MPI_EVENT_SAS_INIT_RC_ADDED                 (0x01)
+
+/* SAS Initiator Device Table Overflow Event data */
+
+typedef struct _EVENT_DATA_SAS_INIT_TABLE_OVERFLOW
+{
+    U8                      MaxInit;                    /* 00h */
+    U8                      CurrentInit;                /* 01h */
+    U16                     Reserved1;                  /* 02h */
+} EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
+  MPI_POINTER PTR_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
+  MpiEventDataSasInitTableOverflow_t,
+  MPI_POINTER pMpiEventDataSasInitTableOverflow_t;
+
 
 /*****************************************************************************
 *
@@ -1013,5 +1104,6 @@ typedef struct _MPI_EXT_IMAGE_HEADER
 #define MPI_EXT_IMAGE_TYPE_FW                   (0x01)
 #define MPI_EXT_IMAGE_TYPE_NVDATA               (0x03)
 #define MPI_EXT_IMAGE_TYPE_BOOTLOADER           (0x04)
+#define MPI_EXT_IMAGE_TYPE_INITIALIZATION       (0x05)
 
 #endif
index a9c14ad..871ebc0 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef IOPI_IOCLOGINFO_H_INCLUDED
 #define IOPI_IOCLOGINFO_H_INCLUDED
 
+#define SAS_LOGINFO_NEXUS_LOSS         0x31170000
+#define SAS_LOGINFO_MASK                       0xFFFF0000
 
 /****************************************************************************/
 /*  IOC LOGINFO defines, 0x00000000 - 0x0FFFFFFF                            */
@@ -51,6 +53,9 @@
 #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 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 */
 /****************************************************************************/
 /* IR LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IR            */
 /****************************************************************************/
-#define IR_LOGINFO_CODE_UNUSED1                         (0x00010000)
-#define IR_LOGINFO_CODE_UNUSED2                         (0x00020000)
+#define IR_LOGINFO_RAID_ACTION_ERROR                           (0x00010000)
+#define IR_LOGINFO_CODE_UNUSED2                                (0x00020000)
+
+/* Amount of information passed down for Create Volume is too large */
+#define IR_LOGINFO_VOLUME_CREATE_INVALID_LENGTH                (0x00010001)
+/* Creation of duplicate volume attempted (Bus/Target ID checked) */
+#define IR_LOGINFO_VOLUME_CREATE_DUPLICATE                     (0x00010002)
+/* Creation failed due to maximum number of supported volumes exceeded */
+#define IR_LOGINFO_VOLUME_CREATE_NO_SLOTS                      (0x00010003)
+/* Creation failed due to DMA error in trying to read from host */
+#define IR_LOGINFO_VOLUME_CREATE_DMA_ERROR                     (0x00010004)
+/* Creation failed due to invalid volume type passed down */
+#define IR_LOGINFO_VOLUME_CREATE_INVALID_VOLUME_TYPE           (0x00010005)
+/* Creation failed due to error reading MFG Page 4 */
+#define IR_LOGINFO_VOLUME_MFG_PAGE4_ERROR                      (0x00010006)
+/* Creation failed when trying to create internal structures */
+#define IR_LOGINFO_VOLUME_INTERNAL_CONFIG_STRUCTURE_ERROR      (0x00010007)
+
+/* Activation failed due to trying to activate an already active volume */
+#define IR_LOGINFO_VOLUME_ACTIVATING_AN_ACTIVE_VOLUME          (0x00010010)
+/* Activation failed due to trying to active unsupported volume type  */
+#define IR_LOGINFO_VOLUME_ACTIVATING_INVALID_VOLUME_TYPE       (0x00010011)
+/* Activation failed due to trying to active too many volumes  */
+#define IR_LOGINFO_VOLUME_ACTIVATING_TOO_MANY_VOLUMES          (0x00010012)
+/* Activation failed due to Volume ID in use already */
+#define IR_LOGINFO_VOLUME_ACTIVATING_VOLUME_ID_IN_USE          (0x00010013)
+/* Activation failed call to activateVolume returned failure */
+#define IR_LOGINFO_VOLUME_ACTIVATE_VOLUME_FAILED               (0x00010014)
+/* Activation failed trying to import the volume */
+#define IR_LOGINFO_VOLUME_ACTIVATING_IMPORT_VOLUME_FAILED      (0x00010015)
+
+/* Phys Disk failed, too many phys disks */
+#define IR_LOGINFO_PHYSDISK_CREATE_TOO_MANY_DISKS              (0x00010020)
+/* Amount of information passed down for Create Pnysdisk is too large */
+#define IR_LOGINFO_PHYSDISK_CREATE_INVALID_LENGTH              (0x00010021)
+/* Creation failed due to DMA error in trying to read from host */
+#define IR_LOGINFO_PHYSDISK_CREATE_DMA_ERROR                   (0x00010022)
+/* Creation failed due to invalid Bus TargetID passed down */
+#define IR_LOGINFO_PHYSDISK_CREATE_BUS_TID_INVALID             (0x00010023)
+/* Creation failed due to error in creating RAID Phys Disk Config Page */
+#define IR_LOGINFO_PHYSDISK_CREATE_CONFIG_PAGE_ERROR           (0x00010024)
+
+
+/* Compatibility Error : IR Disabled */
+#define IR_LOGINFO_COMPAT_ERROR_RAID_DISABLED                  (0x00010030)
+/* Compatibility Error : Inquiry Comand failed */
+#define IR_LOGINFO_COMPAT_ERROR_INQUIRY_FAILED                 (0x00010031)
+/* Compatibility Error : Device not direct access device */
+#define IR_LOGINFO_COMPAT_ERROR_NOT_DIRECT_ACCESS              (0x00010032)
+/* Compatibility Error : Removable device found */
+#define IR_LOGINFO_COMPAT_ERROR_REMOVABLE_FOUND                (0x00010033)
+/* Compatibility Error : Device SCSI Version not 2 or higher */
+#define IR_LOGINFO_COMPAT_ERROR_NEED_SCSI_2_OR_HIGHER          (0x00010034)
+/* Compatibility Error : SATA device, 48 BIT LBA not supported */
+#define IR_LOGINFO_COMPAT_ERROR_SATA_48BIT_LBA_NOT_SUPPORTED   (0x00010035)
+/* Compatibility Error : Device does not have 512 byte block sizes */
+#define IR_LOGINFO_COMPAT_ERROR_DEVICE_NOT_512_BYTE_BLOCK      (0x00010036)
+/* Compatibility Error : Volume Type check failed */
+#define IR_LOGINFO_COMPAT_ERROR_VOLUME_TYPE_CHECK_FAILED       (0x00010037)
+/* Compatibility Error : Volume Type is unsupported by FW */
+#define IR_LOGINFO_COMPAT_ERROR_UNSUPPORTED_VOLUME_TYPE        (0x00010038)
+/* Compatibility Error : Disk drive too small for use in volume */
+#define IR_LOGINFO_COMPAT_ERROR_DISK_TOO_SMALL                 (0x00010039)
+/* Compatibility Error : Phys disk for Create Volume not found */
+#define IR_LOGINFO_COMPAT_ERROR_PHYS_DISK_NOT_FOUND            (0x0001003A)
+/* Compatibility Error : membership count error, too many or too few disks for volume type */
+#define IR_LOGINFO_COMPAT_ERROR_MEMBERSHIP_COUNT               (0x0001003B)
+/* Compatibility Error : Disk stripe sizes must be 64KB */
+#define IR_LOGINFO_COMPAT_ERROR_NON_64K_STRIPE_SIZE            (0x0001003C)
+/* Compatibility Error : IME size limited to < 2TB */
+#define IR_LOGINFO_COMPAT_ERROR_IME_VOL_NOT_CURRENTLY_SUPPORTED (0x0001003D)
+
 
 /****************************************************************************/
-/* Defines for convienence                                                  */
+/* Defines for convenience                                                  */
 /****************************************************************************/
 #define IOC_LOGINFO_PREFIX_IOP                          ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IOP)
 #define IOC_LOGINFO_PREFIX_PL                           ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_PL)
index 7051486..50b8f0a 100644 (file)
@@ -6,7 +6,7 @@
  *          Title:  MPI Serial Attached SCSI structures and definitions
  *  Creation Date:  August 19, 2004
  *
- *    mpi_sas.h Version:  01.05.02
+ *    mpi_sas.h Version:  01.05.03
  *
  *  Version History
  *  ---------------
  *  08-30-05  01.05.02  Added DeviceInfo bit for SEP.
  *                      Added PrimFlags and Primitive field to SAS IO Unit
  *                      Control request, and added a new operation code.
+ *  03-27-06  01.05.03  Added Force Full Discovery, Transmit Port Select Signal,
+ *                      and Remove Device operations to SAS IO Unit Control.
+ *                      Added DevHandle field to SAS IO Unit Control request and
+ *                      reply.
  *  --------------------------------------------------------------------------
  */
 
@@ -209,7 +213,7 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST
     U8                      Reserved1;          /* 01h */
     U8                      ChainOffset;        /* 02h */
     U8                      Function;           /* 03h */
-    U16                     Reserved2;          /* 04h */
+    U16                     DevHandle;          /* 04h */
     U8                      Reserved3;          /* 06h */
     U8                      MsgFlags;           /* 07h */
     U32                     MsgContext;         /* 08h */
@@ -231,6 +235,9 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST
 #define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG          (0x08)
 #define MPI_SAS_OP_MAP_CURRENT                  (0x09)
 #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)
 
 /* values for the PrimFlags field */
 #define MPI_SAS_PRIMFLAGS_SINGLE                (0x08)
@@ -245,7 +252,7 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REPLY
     U8                      Reserved1;          /* 01h */
     U8                      MsgLength;          /* 02h */
     U8                      Function;           /* 03h */
-    U16                     Reserved2;          /* 04h */
+    U16                     DevHandle;          /* 04h */
     U8                      Reserved3;          /* 06h */
     U8                      MsgFlags;           /* 07h */
     U32                     MsgContext;         /* 08h */
index 3f46285..20b6673 100644 (file)
@@ -6,7 +6,7 @@
  *          Title:  MPI Target mode messages and structures
  *  Creation Date:  June 22, 2000
  *
- *    mpi_targ.h Version:  01.05.05
+ *    mpi_targ.h Version:  01.05.06
  *
  *  Version History
  *  ---------------
@@ -54,6 +54,7 @@
  *  02-22-05  01.05.03  Changed a comment.
  *  03-11-05  01.05.04  Removed TargetAssistExtended Request.
  *  06-24-05  01.05.05  Added TargetAssistExtended structures and defines.
+ *  03-27-06  01.05.06  Added a comment.
  *  --------------------------------------------------------------------------
  */
 
@@ -351,7 +352,7 @@ typedef struct _MSG_TARGET_ASSIST_REQUEST
 #define TARGET_ASSIST_FLAGS_CONFIRMED               (0x08)
 #define TARGET_ASSIST_FLAGS_REPOST_CMD_BUFFER       (0x80)
 
-
+/* Standard Target Mode Reply message */
 typedef struct _MSG_TARGET_ERROR_REPLY
 {
     U16                     Reserved;                   /* 00h */
index 12dd8d4..8ac77ca 100644 (file)
@@ -1220,31 +1220,25 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
        port = psize = 0;
        for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
                if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
+                       if (psize)
+                               continue;
                        /* Get I/O space! */
                        port = pci_resource_start(pdev, ii);
                        psize = pci_resource_len(pdev,ii);
                } else {
+                       if (msize)
+                               continue;
                        /* Get memmap */
                        mem_phys = pci_resource_start(pdev, ii);
                        msize = pci_resource_len(pdev,ii);
-                       break;
                }
        }
        ioc->mem_size = msize;
 
-       if (ii == DEVICE_COUNT_RESOURCE) {
-               printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n");
-               kfree(ioc);
-               return -EINVAL;
-       }
-
-       dinitprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
-       dinitprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
-
        mem = NULL;
        /* Get logical ptr for PciMem0 space */
        /*mem = ioremap(mem_phys, msize);*/
-       mem = ioremap(mem_phys, 0x100);
+       mem = ioremap(mem_phys, msize);
        if (mem == NULL) {
                printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
                kfree(ioc);
@@ -1344,11 +1338,6 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
                ioc->bus_type = SAS;
                ioc->errata_flag_1064 = 1;
        }
-       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066) {
-               ioc->prod_name = "LSISAS1066";
-               ioc->bus_type = SAS;
-               ioc->errata_flag_1064 = 1;
-       }
        else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
                ioc->prod_name = "LSISAS1068";
                ioc->bus_type = SAS;
@@ -1358,14 +1347,14 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
                ioc->prod_name = "LSISAS1064E";
                ioc->bus_type = SAS;
        }
-       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) {
-               ioc->prod_name = "LSISAS1066E";
-               ioc->bus_type = SAS;
-       }
        else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
                ioc->prod_name = "LSISAS1068E";
                ioc->bus_type = SAS;
        }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
+               ioc->prod_name = "LSISAS1078";
+               ioc->bus_type = SAS;
+       }
 
        if (ioc->errata_flag_1064)
                pci_disable_io_access(pdev);
@@ -3185,6 +3174,37 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
        u32 diag1val = 0;
 #endif
 
+       if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
+               drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
+                       "address=%p\n",  ioc->name, __FUNCTION__,
+                       &ioc->chip->Doorbell, &ioc->chip->Reset_1078));
+               CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07);
+               if (sleepFlag == CAN_SLEEP)
+                       msleep(1);
+               else
+                       mdelay(1);
+
+               for (count = 0; count < 60; count ++) {
+                       doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
+                       doorbell &= MPI_IOC_STATE_MASK;
+
+                       drsprintk((MYIOC_s_INFO_FMT
+                               "looking for READY STATE: doorbell=%x"
+                               " count=%d\n",
+                               ioc->name, doorbell, count));
+                       if (doorbell == MPI_IOC_STATE_READY) {
+                               return 0;
+                       }
+
+                       /* wait 1 sec */
+                       if (sleepFlag == CAN_SLEEP)
+                               msleep(1000);
+                       else
+                               mdelay(1000);
+               }
+               return -1;
+       }
+
        /* Clear any existing interrupts */
        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 
index 4720f9a..7bf0855 100644 (file)
@@ -76,8 +76,8 @@
 #define COPYRIGHT      "Copyright (c) 1999-2005 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON       "3.03.10"
-#define MPT_LINUX_PACKAGE_NAME         "@(#)mptlinux-3.03.10"
+#define MPT_LINUX_VERSION_COMMON       "3.04.00"
+#define MPT_LINUX_PACKAGE_NAME         "@(#)mptlinux-3.04.00"
 #define WHAT_MAGIC_STRING              "@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -308,7 +308,8 @@ typedef struct _SYSIF_REGS
        u32     HostIndex;      /* 50     Host Index register        */
        u32     Reserved4[15];  /* 54-8F                             */
        u32     Fubar;          /* 90     For Fubar usage            */
-       u32     Reserved5[27];  /* 94-FF                             */
+       u32     Reserved5[1050];/* 94-10F8                           */
+       u32     Reset_1078;     /* 10FC   Reset 1078                 */
 } SYSIF_REGS;
 
 /*
@@ -342,6 +343,7 @@ typedef struct _VirtTarget {
        u8                       negoFlags;     /* bit field, see above */
        u8                       raidVolume;    /* set, if RAID Volume */
        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;
@@ -633,7 +635,7 @@ typedef struct _MPT_ADAPTER
        int                      sas_index; /* index refrencing */
        MPT_SAS_MGMT             sas_mgmt;
        int                      num_ports;
-       struct work_struct       mptscsih_persistTask;
+       struct work_struct       sas_persist_task;
 
        struct work_struct       fc_setup_reset_work;
        struct list_head         fc_rports;
@@ -642,6 +644,7 @@ typedef struct _MPT_ADAPTER
        struct work_struct       fc_rescan_work;
        char                     fc_rescan_work_q_name[KOBJ_NAME_LEN];
        struct workqueue_struct *fc_rescan_work_q;
+       u8              port_serial_number;
 } MPT_ADAPTER;
 
 /*
@@ -893,6 +896,13 @@ typedef struct _mpt_sge {
 #define DBG_DUMP_REQUEST_FRAME_HDR(mfp)
 #endif
 
+// debug sas wide ports
+#ifdef MPT_DEBUG_SAS_WIDE
+#define dsaswideprintk(x) printk x
+#else
+#define dsaswideprintk(x)
+#endif
+
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
index 3ff8378..a8f2fa9 100644 (file)
@@ -132,21 +132,21 @@ static struct scsi_host_template mptfc_driver_template = {
  */
 
 static struct pci_device_id mptfc_pci_table[] = {
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
+       { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC909,
                PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
+       { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919,
                PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
+       { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929,
                PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
+       { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919X,
                PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
+       { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929X,
                PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC939X,
+       { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC939X,
                PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,
+       { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949X,
                PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949ES,
+       { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E,
                PCI_ANY_ID, PCI_ANY_ID },
        {0}     /* Terminating entry */
 };
index 85689ab..bc36f5f 100644 (file)
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/workqueue.h>
+#include <linux/delay.h>       /* for mdelay */
 
+#include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_transport_sas.h>
+#include <scsi/scsi_dbg.h>
 
 #include "mptbase.h"
 #include "mptscsih.h"
@@ -137,23 +140,37 @@ struct mptsas_devinfo {
        u32     device_info;    /* bitfield detailed info about this device */
 };
 
+/*
+ * Specific details on ports, wide/narrow
+ */
+struct mptsas_portinfo_details{
+       u8      port_id;        /* port number provided to transport */
+       u16     num_phys;       /* number of phys belong to this port */
+       u64     phy_bitmask;    /* TODO, extend support for 255 phys */
+       struct sas_rphy *rphy;  /* transport layer rphy object */
+       struct sas_port *port;  /* transport layer port object */
+       struct scsi_target *starget;
+       struct mptsas_portinfo *port_info;
+};
+
 struct mptsas_phyinfo {
        u8      phy_id;                 /* phy index */
-       u8      port_id;                /* port number this phy is part of */
+       u8      port_id;                /* firmware port identifier */
        u8      negotiated_link_rate;   /* nego'd link rate for this phy */
        u8      hw_link_rate;           /* hardware max/min phys link rate */
        u8      programmed_link_rate;   /* programmed max/min phy link rate */
+       u8      sas_port_add_phy;       /* flag to request sas_port_add_phy*/
        struct mptsas_devinfo identify; /* point to phy device info */
        struct mptsas_devinfo attached; /* point to attached device info */
-       struct sas_phy *phy;
-       struct sas_rphy *rphy;
-       struct scsi_target *starget;
+       struct sas_phy *phy;            /* transport layer phy object */
+       struct mptsas_portinfo *portinfo;
+       struct mptsas_portinfo_details * port_details;
 };
 
 struct mptsas_portinfo {
        struct list_head list;
        u16             handle;         /* unique id to address this */
-       u             num_phys;       /* number of phys */
+       u16             num_phys;       /* number of phys */
        struct mptsas_phyinfo *phy_info;
 };
 
@@ -169,7 +186,7 @@ struct mptsas_enclosure {
        u8      sep_channel;            /* SEP channel logical channel id */
 };
 
-#ifdef SASDEBUG
+#ifdef MPT_DEBUG_SAS
 static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
 {
        printk("---- IO UNIT PAGE 0 ------------\n");
@@ -305,7 +322,7 @@ mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
 static inline int
 mptsas_is_end_device(struct mptsas_devinfo * attached)
 {
-       if ((attached->handle) &&
+       if ((attached->sas_address) &&
            (attached->device_info &
            MPI_SAS_DEVICE_INFO_END_DEVICE) &&
            ((attached->device_info &
@@ -319,6 +336,253 @@ mptsas_is_end_device(struct mptsas_devinfo * attached)
                return 0;
 }
 
+/* no mutex */
+void
+mptsas_port_delete(struct mptsas_portinfo_details * port_details)
+{
+       struct mptsas_portinfo *port_info;
+       struct mptsas_phyinfo *phy_info;
+       u8      i;
+
+       if (!port_details)
+               return;
+
+       port_info = port_details->port_info;
+       phy_info = port_info->phy_info;
+
+       dsaswideprintk((KERN_DEBUG "%s: [%p]: port=%02d num_phys=%02d "
+               "bitmask=0x%016llX\n",
+               __FUNCTION__, port_details, port_details->port_id,
+               port_details->num_phys, port_details->phy_bitmask));
+
+       for (i = 0; i < port_info->num_phys; i++, phy_info++) {
+               if(phy_info->port_details != port_details)
+                       continue;
+               memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
+               phy_info->port_details = NULL;
+       }
+       kfree(port_details);
+}
+
+static inline struct sas_rphy *
+mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
+{
+       if (phy_info->port_details)
+               return phy_info->port_details->rphy;
+       else
+               return NULL;
+}
+
+static inline void
+mptsas_set_rphy(struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
+{
+       if (phy_info->port_details) {
+               phy_info->port_details->rphy = rphy;
+               dsaswideprintk((KERN_DEBUG "sas_rphy_add: rphy=%p\n", rphy));
+       }
+
+#ifdef MPT_DEBUG_SAS_WIDE
+       if (rphy) {
+               dev_printk(KERN_DEBUG, &rphy->dev, "add:");
+               printk("rphy=%p release=%p\n",
+                       rphy, rphy->dev.release);
+       }
+#endif
+}
+
+static inline struct sas_port *
+mptsas_get_port(struct mptsas_phyinfo *phy_info)
+{
+       if (phy_info->port_details)
+               return phy_info->port_details->port;
+       else
+               return NULL;
+}
+
+static inline void
+mptsas_set_port(struct mptsas_phyinfo *phy_info, struct sas_port *port)
+{
+       if (phy_info->port_details)
+               phy_info->port_details->port = port;
+
+#ifdef MPT_DEBUG_SAS_WIDE
+       if (port) {
+               dev_printk(KERN_DEBUG, &port->dev, "add: ");
+               printk("port=%p release=%p\n",
+                       port, port->dev.release);
+       }
+#endif
+}
+
+static inline struct scsi_target *
+mptsas_get_starget(struct mptsas_phyinfo *phy_info)
+{
+       if (phy_info->port_details)
+               return phy_info->port_details->starget;
+       else
+               return NULL;
+}
+
+static inline void
+mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
+starget)
+{
+       if (phy_info->port_details)
+               phy_info->port_details->starget = starget;
+}
+
+
+/*
+ * mptsas_setup_wide_ports
+ *
+ * Updates for new and existing narrow/wide port configuration
+ * in the sas_topology
+ */
+void
+mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
+{
+       struct mptsas_portinfo_details * port_details;
+       struct mptsas_phyinfo *phy_info, *phy_info_cmp;
+       u64     sas_address;
+       int     i, j;
+
+       mutex_lock(&ioc->sas_topology_mutex);
+
+       phy_info = port_info->phy_info;
+       for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
+               if (phy_info->attached.handle)
+                       continue;
+               port_details = phy_info->port_details;
+               if (!port_details)
+                       continue;
+               if (port_details->num_phys < 2)
+                       continue;
+               /*
+                * Removing a phy from a port, letting the last
+                * phy be removed by firmware events.
+                */
+               dsaswideprintk((KERN_DEBUG
+                       "%s: [%p]: port=%d deleting phy = %d\n",
+                       __FUNCTION__, port_details,
+                       port_details->port_id, i));
+               port_details->num_phys--;
+               port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
+               memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
+               sas_port_delete_phy(port_details->port, phy_info->phy);
+               phy_info->port_details = NULL;
+       }
+
+       /*
+        * Populate and refresh the tree
+        */
+       phy_info = port_info->phy_info;
+       for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
+               sas_address = phy_info->attached.sas_address;
+               dsaswideprintk((KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n",
+                       i, sas_address));
+               if (!sas_address)
+                       continue;
+               port_details = phy_info->port_details;
+               /*
+                * Forming a port
+                */
+               if (!port_details) {
+                       port_details = kzalloc(sizeof(*port_details),
+                               GFP_KERNEL);
+                       if (!port_details)
+                               goto out;
+                       port_details->num_phys = 1;
+                       port_details->port_info = port_info;
+                       port_details->port_id = ioc->port_serial_number++;
+                       if (phy_info->phy_id < 64 )
+                               port_details->phy_bitmask |=
+                                   (1 << phy_info->phy_id);
+                       phy_info->sas_port_add_phy=1;
+                       dsaswideprintk((KERN_DEBUG "\t\tForming port\n\t\t"
+                               "phy_id=%d sas_address=0x%018llX\n",
+                               i, sas_address));
+                       phy_info->port_details = port_details;
+               }
+
+               if (i == port_info->num_phys - 1)
+                       continue;
+               phy_info_cmp = &port_info->phy_info[i + 1];
+               for (j = i + 1 ; j < port_info->num_phys ; j++,
+                   phy_info_cmp++) {
+                       if (!phy_info_cmp->attached.sas_address)
+                               continue;
+                       if (sas_address != phy_info_cmp->attached.sas_address)
+                               continue;
+                       if (phy_info_cmp->port_details == port_details )
+                               continue;
+                       dsaswideprintk((KERN_DEBUG
+                               "\t\tphy_id=%d sas_address=0x%018llX\n",
+                               j, phy_info_cmp->attached.sas_address));
+                       if (phy_info_cmp->port_details) {
+                               port_details->rphy =
+                                   mptsas_get_rphy(phy_info_cmp);
+                               port_details->port =
+                                   mptsas_get_port(phy_info_cmp);
+                               port_details->starget =
+                                   mptsas_get_starget(phy_info_cmp);
+                               port_details->port_id =
+                                       phy_info_cmp->port_details->port_id;
+                               port_details->num_phys =
+                                       phy_info_cmp->port_details->num_phys;
+//                             port_info->port_serial_number--;
+                               ioc->port_serial_number--;
+                               if (!phy_info_cmp->port_details->num_phys)
+                                       kfree(phy_info_cmp->port_details);
+                       } else
+                               phy_info_cmp->sas_port_add_phy=1;
+                       /*
+                        * Adding a phy to a port
+                        */
+                       phy_info_cmp->port_details = port_details;
+                       if (phy_info_cmp->phy_id < 64 )
+                               port_details->phy_bitmask |=
+                               (1 << phy_info_cmp->phy_id);
+                       port_details->num_phys++;
+               }
+       }
+
+ out:
+
+#ifdef MPT_DEBUG_SAS_WIDE
+       for (i = 0; i < port_info->num_phys; i++) {
+               port_details = port_info->phy_info[i].port_details;
+               if (!port_details)
+                       continue;
+               dsaswideprintk((KERN_DEBUG
+                       "%s: [%p]: phy_id=%02d port_id=%02d num_phys=%02d "
+                       "bitmask=0x%016llX\n",
+                       __FUNCTION__,
+                       port_details, i, port_details->port_id,
+                       port_details->num_phys, port_details->phy_bitmask));
+               dsaswideprintk((KERN_DEBUG"\t\tport = %p rphy=%p\n",
+                       port_details->port, port_details->rphy));
+       }
+       dsaswideprintk((KERN_DEBUG"\n"));
+#endif
+       mutex_unlock(&ioc->sas_topology_mutex);
+}
+
+static void
+mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget)
+{
+       MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+
+       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);
+       }
+}
+
 static int
 mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
                u32 form, u32 form_specific)
@@ -400,11 +664,105 @@ mptsas_slave_configure(struct scsi_device *sdev)
        return mptscsih_slave_configure(sdev);
 }
 
-/*
- * This is pretty ugly.  We will be able to seriously clean it up
- * once the DV code in mptscsih goes away and we can properly
- * implement ->target_alloc.
- */
+static int
+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;
+       struct sas_rphy         *rphy;
+       struct mptsas_portinfo  *p;
+       int                      i;
+
+       vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
+       if (!vtarget)
+               return -ENOMEM;
+
+       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;
+       channel = 0;
+
+       hd->Targets[target_id] = vtarget;
+
+       /*
+        * RAID volumes placed beyond the last expected port.
+        */
+       if (starget->channel == hd->ioc->num_ports)
+               goto out;
+
+       rphy = dev_to_rphy(starget->dev.parent);
+       mutex_lock(&hd->ioc->sas_topology_mutex);
+       list_for_each_entry(p, &hd->ioc->sas_topology, list) {
+               for (i = 0; i < p->num_phys; i++) {
+                       if (p->phy_info[i].attached.sas_address !=
+                                       rphy->identify.sas_address)
+                               continue;
+                       target_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);
+                               vtarget->tflags |=
+                                   MPT_TARGET_FLAGS_RAID_COMPONENT;
+                       }
+                       mutex_unlock(&hd->ioc->sas_topology_mutex);
+                       goto out;
+               }
+       }
+       mutex_unlock(&hd->ioc->sas_topology_mutex);
+
+       kfree(vtarget);
+       return -ENXIO;
+
+ out:
+       vtarget->target_id = target_id;
+       vtarget->bus_id = channel;
+       starget->hostdata = vtarget;
+       return 0;
+}
+
+static void
+mptsas_target_destroy(struct scsi_target *starget)
+{
+       struct Scsi_Host *host = dev_to_shost(&starget->dev);
+       MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)host->hostdata;
+       struct sas_rphy         *rphy;
+       struct mptsas_portinfo  *p;
+       int                      i;
+
+       if (!starget->hostdata)
+               return;
+
+       if (starget->channel == hd->ioc->num_ports)
+               goto out;
+
+       rphy = dev_to_rphy(starget->dev.parent);
+       list_for_each_entry(p, &hd->ioc->sas_topology, list) {
+               for (i = 0; i < p->num_phys; i++) {
+                       if (p->phy_info[i].attached.sas_address !=
+                                       rphy->identify.sas_address)
+                               continue;
+                       mptsas_set_starget(&p->phy_info[i], NULL);
+                       goto out;
+               }
+       }
+
+ out:
+       kfree(starget->hostdata);
+       starget->hostdata = NULL;
+}
+
+
 static int
 mptsas_slave_alloc(struct scsi_device *sdev)
 {
@@ -412,61 +770,41 @@ mptsas_slave_alloc(struct scsi_device *sdev)
        MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)host->hostdata;
        struct sas_rphy         *rphy;
        struct mptsas_portinfo  *p;
-       VirtTarget              *vtarget;
        VirtDevice              *vdev;
        struct scsi_target      *starget;
-       u32                     target_id;
-       int i;
+       int                     i;
 
        vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
        if (!vdev) {
-               printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
+               printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
                                hd->ioc->name, sizeof(VirtDevice));
                return -ENOMEM;
        }
-       sdev->hostdata = vdev;
        starget = scsi_target(sdev);
-       vtarget = starget->hostdata;
-       vtarget->ioc_id = hd->ioc->id;
-       vdev->vtarget = vtarget;
-       if (vtarget->num_luns == 0) {
-               vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
-               hd->Targets[sdev->id] = vtarget;
-       }
+       vdev->vtarget = starget->hostdata;
 
        /*
-         RAID volumes placed beyond the last expected port.
-       */
-       if (sdev->channel == hd->ioc->num_ports) {
-               target_id = sdev->id;
-               vtarget->bus_id = 0;
-               vdev->lun = 0;
+        * RAID volumes placed beyond the last expected port.
+        */
+       if (sdev->channel == hd->ioc->num_ports)
                goto out;
-       }
 
        rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
        mutex_lock(&hd->ioc->sas_topology_mutex);
        list_for_each_entry(p, &hd->ioc->sas_topology, list) {
                for (i = 0; i < p->num_phys; i++) {
-                       if (p->phy_info[i].attached.sas_address ==
-                                       rphy->identify.sas_address) {
-                               target_id = p->phy_info[i].attached.id;
-                               vtarget->bus_id = p->phy_info[i].attached.channel;
-                               vdev->lun = sdev->lun;
-                               p->phy_info[i].starget = sdev->sdev_target;
-                               /*
-                                * Exposing hidden disk (RAID)
-                                */
-                               if (mptscsih_is_phys_disk(hd->ioc, target_id)) {
-                                       target_id = mptscsih_raid_id_to_num(hd,
-                                                       target_id);
-                                       vdev->vtarget->tflags |=
-                                           MPT_TARGET_FLAGS_RAID_COMPONENT;
-                                       sdev->no_uld_attach = 1;
-                               }
-                               mutex_unlock(&hd->ioc->sas_topology_mutex);
-                               goto out;
-                       }
+                       if (p->phy_info[i].attached.sas_address !=
+                                       rphy->identify.sas_address)
+                               continue;
+                       vdev->lun = sdev->lun;
+                       /*
+                        * Exposing hidden raid components
+                        */
+                       if (mptscsih_is_phys_disk(hd->ioc,
+                                       p->phy_info[i].attached.id))
+                               sdev->no_uld_attach = 1;
+                       mutex_unlock(&hd->ioc->sas_topology_mutex);
+                       goto out;
                }
        }
        mutex_unlock(&hd->ioc->sas_topology_mutex);
@@ -475,57 +813,39 @@ mptsas_slave_alloc(struct scsi_device *sdev)
        return -ENXIO;
 
  out:
-       vtarget->target_id = target_id;
-       vtarget->num_luns++;
+       vdev->vtarget->num_luns++;
+       sdev->hostdata = vdev;
        return 0;
 }
 
-static void
-mptsas_slave_destroy(struct scsi_device *sdev)
+static int
+mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 {
-       struct Scsi_Host *host = sdev->host;
-       MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
-       VirtDevice *vdev;
+       VirtDevice      *vdev = SCpnt->device->hostdata;
 
-       /*
-        * Issue target reset to flush firmware outstanding commands.
-        */
-       vdev = sdev->hostdata;
-       if (vdev->configured_lun){
-               if (mptscsih_TMHandler(hd,
-                    MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
-                    vdev->vtarget->bus_id,
-                    vdev->vtarget->target_id,
-                    0, 0, 5 /* 5 second timeout */)
-                    < 0){
-
-                       /* The TM request failed!
-                        * Fatal error case.
-                        */
-                       printk(MYIOC_s_WARN_FMT
-                      "Error processing TaskMgmt id=%d TARGET_RESET\n",
-                               hd->ioc->name,
-                               vdev->vtarget->target_id);
-
-                       hd->tmPending = 0;
-                       hd->tmState = TM_STATE_NONE;
-               }
+//     scsi_print_command(SCpnt);
+       if (vdev->vtarget->deleted) {
+               SCpnt->result = DID_NO_CONNECT << 16;
+               done(SCpnt);
+               return 0;
        }
-       mptscsih_slave_destroy(sdev);
+
+       return mptscsih_qcmd(SCpnt,done);
 }
 
+
 static struct scsi_host_template mptsas_driver_template = {
        .module                         = THIS_MODULE,
        .proc_name                      = "mptsas",
        .proc_info                      = mptscsih_proc_info,
        .name                           = "MPT SPI Host",
        .info                           = mptscsih_info,
-       .queuecommand                   = mptscsih_qcmd,
-       .target_alloc                   = mptscsih_target_alloc,
+       .queuecommand                   = mptsas_qcmd,
+       .target_alloc                   = mptsas_target_alloc,
        .slave_alloc                    = mptsas_slave_alloc,
        .slave_configure                = mptsas_slave_configure,
-       .target_destroy                 = mptscsih_target_destroy,
-       .slave_destroy                  = mptsas_slave_destroy,
+       .target_destroy                 = mptsas_target_destroy,
+       .slave_destroy                  = mptscsih_slave_destroy,
        .change_queue_depth             = mptscsih_change_queue_depth,
        .eh_abort_handler               = mptscsih_abort,
        .eh_device_reset_handler        = mptscsih_dev_reset,
@@ -795,7 +1115,7 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
 
        port_info->num_phys = buffer->NumPhys;
        port_info->phy_info = kcalloc(port_info->num_phys,
-               sizeof(struct mptsas_phyinfo),GFP_KERNEL);
+               sizeof(*port_info->phy_info),GFP_KERNEL);
        if (!port_info->phy_info) {
                error = -ENOMEM;
                goto out_free_consistent;
@@ -811,6 +1131,7 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
                    buffer->PhyData[i].Port;
                port_info->phy_info[i].negotiated_link_rate =
                    buffer->PhyData[i].NegotiatedLinkRate;
+               port_info->phy_info[i].portinfo = port_info;
        }
 
  out_free_consistent:
@@ -968,7 +1289,7 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
        CONFIGPARMS cfg;
        SasExpanderPage0_t *buffer;
        dma_addr_t dma_handle;
-       int error;
+       int i, error;
 
        hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
        hdr.ExtPageLength = 0;
@@ -1013,12 +1334,15 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
        port_info->num_phys = buffer->NumPhys;
        port_info->handle = le16_to_cpu(buffer->DevHandle);
        port_info->phy_info = kcalloc(port_info->num_phys,
-               sizeof(struct mptsas_phyinfo),GFP_KERNEL);
+               sizeof(*port_info->phy_info),GFP_KERNEL);
        if (!port_info->phy_info) {
                error = -ENOMEM;
                goto out_free_consistent;
        }
 
+       for (i = 0; i < port_info->num_phys; i++)
+               port_info->phy_info[i].portinfo = port_info;
+
  out_free_consistent:
        pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
                            buffer, dma_handle);
@@ -1161,19 +1485,23 @@ static int mptsas_probe_one_phy(struct device *dev,
 {
        MPT_ADAPTER *ioc;
        struct sas_phy *phy;
-       int error;
+       struct sas_port *port;
+       int error = 0;
 
-       if (!dev)
-               return -ENODEV;
+       if (!dev) {
+               error = -ENODEV;
+               goto out;
+       }
 
        if (!phy_info->phy) {
                phy = sas_phy_alloc(dev, index);
-               if (!phy)
-                       return -ENOMEM;
+               if (!phy) {
+                       error = -ENOMEM;
+                       goto out;
+               }
        } else
                phy = phy_info->phy;
 
-       phy->port_identifier = phy_info->port_id;
        mptsas_parse_device_info(&phy->identify, &phy_info->identify);
 
        /*
@@ -1265,19 +1593,50 @@ static int mptsas_probe_one_phy(struct device *dev,
                error = sas_phy_add(phy);
                if (error) {
                        sas_phy_free(phy);
-                       return error;
+                       goto out;
                }
                phy_info->phy = phy;
        }
 
-       if ((phy_info->attached.handle) &&
-           (!phy_info->rphy)) {
+       if (!phy_info->attached.handle ||
+                       !phy_info->port_details)
+               goto out;
+
+       port = mptsas_get_port(phy_info);
+       ioc = phy_to_ioc(phy_info->phy);
+
+       if (phy_info->sas_port_add_phy) {
+
+               if (!port) {
+                       port = sas_port_alloc(dev,
+                           phy_info->port_details->port_id);
+                       dsaswideprintk((KERN_DEBUG
+                           "sas_port_alloc: port=%p dev=%p port_id=%d\n",
+                           port, dev, phy_info->port_details->port_id));
+                       if (!port) {
+                               error = -ENOMEM;
+                               goto out;
+                       }
+                       error = sas_port_add(port);
+                       if (error) {
+                               dfailprintk((MYIOC_s_ERR_FMT
+                                       "%s: exit at line=%d\n", ioc->name,
+                                       __FUNCTION__, __LINE__));
+                               goto out;
+                       }
+                       mptsas_set_port(phy_info, port);
+               }
+               dsaswideprintk((KERN_DEBUG "sas_port_add_phy: phy_id=%d\n",
+                   phy_info->phy_id));
+               sas_port_add_phy(port, phy_info->phy);
+               phy_info->sas_port_add_phy = 0;
+       }
+
+       if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
 
                struct sas_rphy *rphy;
                struct sas_identify identify;
 
-               ioc = phy_to_ioc(phy_info->phy);
-
                /*
                 * Let the hotplug_work thread handle processing
                 * the adding/removing of devices that occur
@@ -1285,36 +1644,42 @@ static int mptsas_probe_one_phy(struct device *dev,
                 */
                if (ioc->sas_discovery_runtime &&
                        mptsas_is_end_device(&phy_info->attached))
-                       return 0;
+                               goto out;
 
                mptsas_parse_device_info(&identify, &phy_info->attached);
                switch (identify.device_type) {
                case SAS_END_DEVICE:
-                       rphy = sas_end_device_alloc(phy);
+                       rphy = sas_end_device_alloc(port);
                        break;
                case SAS_EDGE_EXPANDER_DEVICE:
                case SAS_FANOUT_EXPANDER_DEVICE:
-                       rphy = sas_expander_alloc(phy, identify.device_type);
+                       rphy = sas_expander_alloc(port, identify.device_type);
                        break;
                default:
                        rphy = NULL;
                        break;
                }
-               if (!rphy)
-                       return 0; /* non-fatal: an rphy can be added later */
+               if (!rphy) {
+                       dfailprintk((MYIOC_s_ERR_FMT
+                               "%s: exit at line=%d\n", ioc->name,
+                               __FUNCTION__, __LINE__));
+                       goto out;
+               }
 
                rphy->identify = identify;
-
                error = sas_rphy_add(rphy);
                if (error) {
+                       dfailprintk((MYIOC_s_ERR_FMT
+                               "%s: exit at line=%d\n", ioc->name,
+                               __FUNCTION__, __LINE__));
                        sas_rphy_free(rphy);
-                       return error;
+                       goto out;
                }
-
-               phy_info->rphy = rphy;
+               mptsas_set_rphy(phy_info, rphy);
        }
 
-       return 0;
+ out:
+       return error;
 }
 
 static int
@@ -1342,8 +1707,7 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
                for (i = 0; i < hba->num_phys; i++)
                        port_info->phy_info[i].negotiated_link_rate =
                                hba->phy_info[i].negotiated_link_rate;
-               if (hba->phy_info)
-                       kfree(hba->phy_info);
+               kfree(hba->phy_info);
                kfree(hba);
                hba = NULL;
        }
@@ -1362,18 +1726,19 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
                    port_info->phy_info[i].phy_id;
                handle = port_info->phy_info[i].identify.handle;
 
-               if (port_info->phy_info[i].attached.handle) {
+               if (port_info->phy_info[i].attached.handle)
                        mptsas_sas_device_pg0(ioc,
                                &port_info->phy_info[i].attached,
                                (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
                                 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
                                port_info->phy_info[i].attached.handle);
-               }
+       }
 
+       mptsas_setup_wide_ports(ioc, port_info);
+
+       for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
                mptsas_probe_one_phy(&ioc->sh->shost_gendev,
                    &port_info->phy_info[i], ioc->sas_index, 1);
-               ioc->sas_index++;
-       }
 
        return 0;
 
@@ -1387,6 +1752,8 @@ static int
 mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
 {
        struct mptsas_portinfo *port_info, *p, *ex;
+       struct device *parent;
+       struct sas_rphy *rphy;
        int error = -ENOMEM, i, j;
 
        ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
@@ -1408,16 +1775,13 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
                list_add_tail(&port_info->list, &ioc->sas_topology);
        } else {
                port_info->handle = ex->handle;
-               if (ex->phy_info)
-                       kfree(ex->phy_info);
+               kfree(ex->phy_info);
                kfree(ex);
                ex = NULL;
        }
        mutex_unlock(&ioc->sas_topology_mutex);
 
        for (i = 0; i < port_info->num_phys; i++) {
-               struct device *parent;
-
                mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
                        (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
                         MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
@@ -1441,34 +1805,34 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
                        port_info->phy_info[i].attached.phy_id =
                            port_info->phy_info[i].phy_id;
                }
+       }
 
-               /*
-                * If we find a parent port handle this expander is
-                * attached to another expander, else it hangs of the
-                * HBA phys.
-                */
-               parent = &ioc->sh->shost_gendev;
+       parent = &ioc->sh->shost_gendev;
+       for (i = 0; i < port_info->num_phys; i++) {
                mutex_lock(&ioc->sas_topology_mutex);
                list_for_each_entry(p, &ioc->sas_topology, list) {
                        for (j = 0; j < p->num_phys; j++) {
-                               if (port_info->phy_info[i].identify.handle ==
+                               if (port_info->phy_info[i].identify.handle !=
                                                p->phy_info[j].attached.handle)
-                                       parent = &p->phy_info[j].rphy->dev;
+                                       continue;
+                               rphy = mptsas_get_rphy(&p->phy_info[j]);
+                               parent = &rphy->dev;
                        }
                }
                mutex_unlock(&ioc->sas_topology_mutex);
+       }
 
+       mptsas_setup_wide_ports(ioc, port_info);
+
+       for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
                mptsas_probe_one_phy(parent, &port_info->phy_info[i],
                    ioc->sas_index, 0);
-               ioc->sas_index++;
-       }
 
        return 0;
 
  out_free_port_info:
        if (ex) {
-               if (ex->phy_info)
-                       kfree(ex->phy_info);
+               kfree(ex->phy_info);
                kfree(ex);
        }
  out:
@@ -1487,7 +1851,12 @@ 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;
 
        mutex_lock(&ioc->sas_topology_mutex);
        list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
@@ -1501,6 +1870,25 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
                     (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);
+                       }
+
                        /*
                         * Obtain the port_info instance to the parent port
                         */
@@ -1510,34 +1898,43 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
                        if (!parent)
                                goto next_port;
 
+                       expander_sas_address =
+                               port_info->phy_info[0].identify.sas_address;
+
                        /*
                         * Delete rphys in the parent that point
                         * to this expander.  The transport layer will
                         * cleanup all the children.
                         */
-                       for (i = 0; i < parent->num_phys; i++) {
-                               if ((!parent->phy_info[i].rphy) ||
-                                   (parent->phy_info[i].attached.sas_address !=
-                                  port_info->phy_info[i].identify.sas_address))
+                       phy_info = parent->phy_info;
+                       for (i = 0; i < parent->num_phys; i++, phy_info++) {
+                               port = mptsas_get_port(phy_info);
+                               if (!port)
                                        continue;
-                               sas_rphy_delete(parent->phy_info[i].rphy);
-                               memset(&parent->phy_info[i].attached, 0,
-                                   sizeof(struct mptsas_devinfo));
-                               parent->phy_info[i].rphy = NULL;
-                               parent->phy_info[i].starget = NULL;
+                               if (phy_info->attached.sas_address !=
+                                       expander_sas_address)
+                                       continue;
+#ifdef MPT_DEBUG_SAS_WIDE
+                               dev_printk(KERN_DEBUG, &port->dev, "delete\n");
+#endif
+                               sas_port_delete(port);
+                               mptsas_port_delete(phy_info->port_details);
                        }
  next_port:
+
+                       phy_info = port_info->phy_info;
+                       for (i = 0; i < port_info->num_phys; i++, phy_info++)
+                               mptsas_port_delete(phy_info->port_details);
+
                        list_del(&port_info->list);
-                       if (port_info->phy_info)
-                               kfree(port_info->phy_info);
+                       kfree(port_info->phy_info);
                        kfree(port_info);
                }
                /*
                * Free this memory allocated from inside
                * mptsas_sas_expander_pg0
                */
-               if (buffer.phy_info)
-                       kfree(buffer.phy_info);
+               kfree(buffer.phy_info);
        }
        mutex_unlock(&ioc->sas_topology_mutex);
 }
@@ -1573,60 +1970,59 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
 /*
  * Work queue thread to handle Runtime discovery
  * Mere purpose is the hot add/delete of expanders
+ *(Mutex UNLOCKED)
  */
 static void
-mptscsih_discovery_work(void * arg)
+__mptsas_discovery_work(MPT_ADAPTER *ioc)
 {
-       struct mptsas_discovery_event *ev = arg;
-       MPT_ADAPTER *ioc = ev->ioc;
        u32 handle = 0xFFFF;
 
-       mutex_lock(&ioc->sas_discovery_mutex);
        ioc->sas_discovery_runtime=1;
        mptsas_delete_expander_phys(ioc);
        mptsas_probe_hba_phys(ioc);
        while (!mptsas_probe_expander_phys(ioc, &handle))
                ;
-       kfree(ev);
        ioc->sas_discovery_runtime=0;
+}
+
+/*
+ * Work queue thread to handle Runtime discovery
+ * Mere purpose is the hot add/delete of expanders
+ *(Mutex LOCKED)
+ */
+static void
+mptsas_discovery_work(void * arg)
+{
+       struct mptsas_discovery_event *ev = arg;
+       MPT_ADAPTER *ioc = ev->ioc;
+
+       mutex_lock(&ioc->sas_discovery_mutex);
+       __mptsas_discovery_work(ioc);
        mutex_unlock(&ioc->sas_discovery_mutex);
+       kfree(ev);
 }
 
 static struct mptsas_phyinfo *
-mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
+mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
 {
        struct mptsas_portinfo *port_info;
-       struct mptsas_devinfo device_info;
        struct mptsas_phyinfo *phy_info = NULL;
-       int i, error;
-
-       /*
-        * Retrieve the parent sas_address
-        */
-       error = mptsas_sas_device_pg0(ioc, &device_info,
-               (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
-                MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
-               parent_handle);
-       if (error)
-               return NULL;
+       int i;
 
-       /*
-        * The phy_info structures are never deallocated during lifetime of
-        * a host, so the code below is safe without additional refcounting.
-        */
        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].identify.sas_address ==
-                           device_info.sas_address &&
-                           port_info->phy_info[i].phy_id == phy_id) {
-                               phy_info = &port_info->phy_info[i];
-                               break;
-                       }
+                       if (port_info->phy_info[i].attached.sas_address
+                           != sas_address)
+                               continue;
+                       if (!mptsas_is_end_device(
+                               &port_info->phy_info[i].attached))
+                               continue;
+                       phy_info = &port_info->phy_info[i];
+                       break;
                }
        }
        mutex_unlock(&ioc->sas_topology_mutex);
-
        return phy_info;
 }
 
@@ -1637,21 +2033,19 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
        struct mptsas_phyinfo *phy_info = NULL;
        int i;
 
-       /*
-        * The phy_info structures are never deallocated during lifetime of
-        * a host, so the code below is safe without additional refcounting.
-        */
        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))
-                               if (port_info->phy_info[i].attached.id == id) {
-                                       phy_info = &port_info->phy_info[i];
-                                       break;
-                               }
+               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;
+                       phy_info = &port_info->phy_info[i];
+                       break;
+               }
        }
        mutex_unlock(&ioc->sas_topology_mutex);
-
        return phy_info;
 }
 
@@ -1659,7 +2053,7 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
  * Work queue thread to clear the persitency table
  */
 static void
-mptscsih_sas_persist_clear_table(void * arg)
+mptsas_persist_clear_table(void * arg)
 {
        MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
 
@@ -1680,7 +2074,6 @@ mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
                        mptsas_reprobe_lun);
 }
 
-
 /*
  * Work queue thread to handle SAS hotplug events
  */
@@ -1691,14 +2084,17 @@ mptsas_hotplug_work(void *arg)
        MPT_ADAPTER *ioc = ev->ioc;
        struct mptsas_phyinfo *phy_info;
        struct sas_rphy *rphy;
+       struct sas_port *port;
        struct scsi_device *sdev;
+       struct scsi_target * starget;
        struct sas_identify identify;
        char *ds = NULL;
        struct mptsas_devinfo sas_device;
        VirtTarget *vtarget;
+       VirtDevice *vdevice;
 
-       mutex_lock(&ioc->sas_discovery_mutex);
 
+       mutex_lock(&ioc->sas_discovery_mutex);
        switch (ev->event_type) {
        case MPTSAS_DEL_DEVICE:
 
@@ -1707,24 +2103,50 @@ mptsas_hotplug_work(void *arg)
                /*
                 * Sanity checks, for non-existing phys and remote rphys.
                 */
-               if (!phy_info)
+               if (!phy_info || !phy_info->port_details) {
+                       dfailprintk((MYIOC_s_ERR_FMT
+                               "%s: exit at line=%d\n", ioc->name,
+                               __FUNCTION__, __LINE__));
+                       break;
+               }
+               rphy = mptsas_get_rphy(phy_info);
+               if (!rphy) {
+                       dfailprintk((MYIOC_s_ERR_FMT
+                               "%s: exit at line=%d\n", ioc->name,
+                               __FUNCTION__, __LINE__));
                        break;
-               if (!phy_info->rphy)
+               }
+               port = mptsas_get_port(phy_info);
+               if (!port) {
+                       dfailprintk((MYIOC_s_ERR_FMT
+                               "%s: exit at line=%d\n", ioc->name,
+                               __FUNCTION__, __LINE__));
                        break;
-               if (phy_info->starget) {
-                       vtarget = phy_info->starget->hostdata;
+               }
 
-                       if (!vtarget)
+               starget = mptsas_get_starget(phy_info);
+               if (starget) {
+                       vtarget = starget->hostdata;
+
+                       if (!vtarget) {
+                               dfailprintk((MYIOC_s_ERR_FMT
+                                       "%s: exit at line=%d\n", ioc->name,
+                                       __FUNCTION__, __LINE__));
                                break;
+                       }
+
                        /*
                         * Handling  RAID components
                         */
                        if (ev->phys_disk_num_valid) {
                                vtarget->target_id = ev->phys_disk_num;
                                vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
-                               mptsas_reprobe_target(vtarget->starget, 1);
+                               mptsas_reprobe_target(starget, 1);
                                break;
                        }
+
+                       vtarget->deleted = 1;
+                       mptsas_target_reset(ioc, vtarget);
                }
 
                if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
@@ -1738,10 +2160,11 @@ mptsas_hotplug_work(void *arg)
                       "removing %s device, channel %d, id %d, phy %d\n",
                       ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
 
-               sas_rphy_delete(phy_info->rphy);
-               memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
-               phy_info->rphy = NULL;
-               phy_info->starget = NULL;
+#ifdef MPT_DEBUG_SAS_WIDE
+               dev_printk(KERN_DEBUG, &port->dev, "delete\n");
+#endif
+               sas_port_delete(port);
+               mptsas_port_delete(phy_info->port_details);
                break;
        case MPTSAS_ADD_DEVICE:
 
@@ -1753,59 +2176,60 @@ mptsas_hotplug_work(void *arg)
                 */
                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->id)) {
+                               dfailprintk((MYIOC_s_ERR_FMT
+                                       "%s: exit at line=%d\n", ioc->name,
+                                       __FUNCTION__, __LINE__));
                        break;
+               }
 
-               phy_info = mptsas_find_phyinfo_by_parent(ioc,
-                               sas_device.handle_parent, sas_device.phy_id);
+               ssleep(2);
+               __mptsas_discovery_work(ioc);
 
-               if (!phy_info) {
-                       u32 handle = 0xFFFF;
+               phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
+                               sas_device.sas_address);
 
-                       /*
-                       * Its possible when an expander has been hot added
-                       * containing attached devices, the sas firmware
-                       * may send a RC_ADDED event prior to the
-                       * DISCOVERY STOP event. If that occurs, our
-                       * view of the topology in the driver in respect to this
-                       * expander might of not been setup, and we hit this
-                       * condition.
-                       * Therefore, this code kicks off discovery to
-                       * refresh the data.
-                       * Then again, we check whether the parent phy has
-                       * been created.
-                       */
-                       ioc->sas_discovery_runtime=1;
-                       mptsas_delete_expander_phys(ioc);
-                       mptsas_probe_hba_phys(ioc);
-                       while (!mptsas_probe_expander_phys(ioc, &handle))
-                               ;
-                       ioc->sas_discovery_runtime=0;
-
-                       phy_info = mptsas_find_phyinfo_by_parent(ioc,
-                               sas_device.handle_parent, sas_device.phy_id);
-                       if (!phy_info)
-                               break;
+               if (!phy_info || !phy_info->port_details) {
+                       dfailprintk((MYIOC_s_ERR_FMT
+                               "%s: exit at line=%d\n", ioc->name,
+                               __FUNCTION__, __LINE__));
+                       break;
                }
 
-               if (phy_info->starget) {
-                       vtarget = phy_info->starget->hostdata;
+               starget = mptsas_get_starget(phy_info);
+               if (starget) {
+                       vtarget = starget->hostdata;
 
-                       if (!vtarget)
+                       if (!vtarget) {
+                               dfailprintk((MYIOC_s_ERR_FMT
+                                       "%s: exit at line=%d\n", ioc->name,
+                                       __FUNCTION__, __LINE__));
                                break;
+                       }
                        /*
                         * Handling  RAID components
                         */
                        if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
                                vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
                                vtarget->target_id = ev->id;
-                               mptsas_reprobe_target(phy_info->starget, 0);
+                               mptsas_reprobe_target(starget, 0);
                        }
                        break;
                }
 
-               if (phy_info->rphy)
+               if (mptsas_get_rphy(phy_info)) {
+                       dfailprintk((MYIOC_s_ERR_FMT
+                               "%s: exit at line=%d\n", ioc->name,
+                               __FUNCTION__, __LINE__));
+                       break;
+               }
+               port = mptsas_get_port(phy_info);
+               if (!port) {
+                       dfailprintk((MYIOC_s_ERR_FMT
+                               "%s: exit at line=%d\n", ioc->name,
+                               __FUNCTION__, __LINE__));
                        break;
+               }
 
                memcpy(&phy_info->attached, &sas_device,
                    sizeof(struct mptsas_devinfo));
@@ -1822,28 +2246,23 @@ mptsas_hotplug_work(void *arg)
                       ioc->name, ds, ev->channel, ev->id, ev->phy_id);
 
                mptsas_parse_device_info(&identify, &phy_info->attached);
-               switch (identify.device_type) {
-               case SAS_END_DEVICE:
-                       rphy = sas_end_device_alloc(phy_info->phy);
-                       break;
-               case SAS_EDGE_EXPANDER_DEVICE:
-               case SAS_FANOUT_EXPANDER_DEVICE:
-                       rphy = sas_expander_alloc(phy_info->phy, identify.device_type);
-                       break;
-               default:
-                       rphy = NULL;
-                       break;
-               }
-               if (!rphy)
+               rphy = sas_end_device_alloc(port);
+               if (!rphy) {
+                       dfailprintk((MYIOC_s_ERR_FMT
+                               "%s: exit at line=%d\n", ioc->name,
+                               __FUNCTION__, __LINE__));
                        break; /* non-fatal: an rphy can be added later */
+               }
 
                rphy->identify = identify;
                if (sas_rphy_add(rphy)) {
+                       dfailprintk((MYIOC_s_ERR_FMT
+                               "%s: exit at line=%d\n", ioc->name,
+                               __FUNCTION__, __LINE__));
                        sas_rphy_free(rphy);
                        break;
                }
-
-               phy_info->rphy = rphy;
+               mptsas_set_rphy(phy_info, rphy);
                break;
        case MPTSAS_ADD_RAID:
                sdev = scsi_device_lookup(
@@ -1875,6 +2294,9 @@ mptsas_hotplug_work(void *arg)
                printk(MYIOC_s_INFO_FMT
                       "removing raid volume, channel %d, id %d\n",
                       ioc->name, ioc->num_ports, 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);
@@ -1884,12 +2306,13 @@ mptsas_hotplug_work(void *arg)
                break;
        }
 
-       kfree(ev);
        mutex_unlock(&ioc->sas_discovery_mutex);
+       kfree(ev);
+
 }
 
 static void
-mptscsih_send_sas_event(MPT_ADAPTER *ioc,
+mptsas_send_sas_event(MPT_ADAPTER *ioc,
                EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
 {
        struct mptsas_hotplug_event *ev;
@@ -1905,7 +2328,7 @@ mptscsih_send_sas_event(MPT_ADAPTER *ioc,
        switch (sas_event_data->ReasonCode) {
        case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
        case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
-               ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+               ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
                if (!ev) {
                        printk(KERN_WARNING "mptsas: lost hotplug event\n");
                        break;
@@ -1935,10 +2358,9 @@ mptscsih_send_sas_event(MPT_ADAPTER *ioc,
        /*
         * Persistent table is full.
         */
-               INIT_WORK(&ioc->mptscsih_persistTask,
-                   mptscsih_sas_persist_clear_table,
-                   (void *)ioc);
-               schedule_work(&ioc->mptscsih_persistTask);
+               INIT_WORK(&ioc->sas_persist_task,
+                   mptsas_persist_clear_table, (void *)ioc);
+               schedule_work(&ioc->sas_persist_task);
                break;
        case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
        /* TODO */
@@ -1950,7 +2372,7 @@ mptscsih_send_sas_event(MPT_ADAPTER *ioc,
 }
 
 static void
-mptscsih_send_raid_event(MPT_ADAPTER *ioc,
+mptsas_send_raid_event(MPT_ADAPTER *ioc,
                EVENT_DATA_RAID *raid_event_data)
 {
        struct mptsas_hotplug_event *ev;
@@ -1960,13 +2382,12 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
        if (ioc->bus_type != SAS)
                return;
 
-       ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+       ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
        if (!ev) {
                printk(KERN_WARNING "mptsas: lost hotplug event\n");
                return;
        }
 
-       memset(ev,0,sizeof(struct mptsas_hotplug_event));
        INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
        ev->ioc = ioc;
        ev->id = raid_event_data->VolumeID;
@@ -2028,7 +2449,7 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
 }
 
 static void
-mptscsih_send_discovery(MPT_ADAPTER *ioc,
+mptsas_send_discovery_event(MPT_ADAPTER *ioc,
        EVENT_DATA_SAS_DISCOVERY *discovery_data)
 {
        struct mptsas_discovery_event *ev;
@@ -2043,11 +2464,10 @@ mptscsih_send_discovery(MPT_ADAPTER *ioc,
        if (discovery_data->DiscoveryStatus)
                return;
 
-       ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+       ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
        if (!ev)
                return;
-       memset(ev,0,sizeof(struct mptsas_discovery_event));
-       INIT_WORK(&ev->work, mptscsih_discovery_work, ev);
+       INIT_WORK(&ev->work, mptsas_discovery_work, ev);
        ev->ioc = ioc;
        schedule_work(&ev->work);
 };
@@ -2075,21 +2495,21 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
 
        switch (event) {
        case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
-               mptscsih_send_sas_event(ioc,
+               mptsas_send_sas_event(ioc,
                        (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
                break;
        case MPI_EVENT_INTEGRATED_RAID:
-               mptscsih_send_raid_event(ioc,
+               mptsas_send_raid_event(ioc,
                        (EVENT_DATA_RAID *)reply->Data);
                break;
        case MPI_EVENT_PERSISTENT_TABLE_FULL:
-               INIT_WORK(&ioc->mptscsih_persistTask,
-                   mptscsih_sas_persist_clear_table,
+               INIT_WORK(&ioc->sas_persist_task,
+                   mptsas_persist_clear_table,
                    (void *)ioc);
-               schedule_work(&ioc->mptscsih_persistTask);
+               schedule_work(&ioc->sas_persist_task);
                break;
         case MPI_EVENT_SAS_DISCOVERY:
-               mptscsih_send_discovery(ioc,
+               mptsas_send_discovery_event(ioc,
                        (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
                break;
        default:
@@ -2308,7 +2728,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        return 0;
 
-out_mptsas_probe:
+ out_mptsas_probe:
 
        mptscsih_remove(pdev);
        return error;
@@ -2318,6 +2738,7 @@ static void __devexit mptsas_remove(struct pci_dev *pdev)
 {
        MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
        struct mptsas_portinfo *p, *n;
+       int i;
 
        ioc->sas_discovery_ignore_events=1;
        sas_remove_host(ioc->sh);
@@ -2325,8 +2746,9 @@ static void __devexit mptsas_remove(struct pci_dev *pdev)
        mutex_lock(&ioc->sas_topology_mutex);
        list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
                list_del(&p->list);
-               if (p->phy_info)
-                       kfree(p->phy_info);
+               for (i = 0 ; i < p->num_phys ; i++)
+                       mptsas_port_delete(p->phy_info[i].port_details);
+               kfree(p->phy_info);
                kfree(p);
        }
        mutex_unlock(&ioc->sas_topology_mutex);
@@ -2335,17 +2757,15 @@ static void __devexit mptsas_remove(struct pci_dev *pdev)
 }
 
 static struct pci_device_id mptsas_pci_table[] = {
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066,
+       { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
                PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068,
+       { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
                PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E,
+       { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
                PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E,
+       { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
                PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E,
+       { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
                PCI_ANY_ID, PCI_ANY_ID },
        {0}     /* Terminating entry */
 };
index 3201de0..0a1ff76 100644 (file)
@@ -775,9 +775,9 @@ static struct spi_function_template mptspi_transport_functions = {
  */
 
 static struct pci_device_id mptspi_pci_table[] = {
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030,
+       { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1030,
                PCI_ANY_ID, PCI_ANY_ID },
-       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_1030_53C1035,
+       { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1035,
                PCI_ANY_ID, PCI_ANY_ID },
        {0}     /* Terminating entry */
 };
index 3c683dc..bff0479 100644 (file)
@@ -2044,7 +2044,7 @@ NCR_700_slave_configure(struct scsi_device *SDp)
        struct NCR_700_Host_Parameters *hostdata = 
                (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0];
 
-       SDp->hostdata = kmalloc(GFP_KERNEL, sizeof(struct NCR_700_sense));
+       SDp->hostdata = kmalloc(sizeof(struct NCR_700_sense), GFP_KERNEL);
 
        if (!SDp->hostdata)
                return -ENOMEM;
index 7cea514..1cd3584 100644 (file)
@@ -92,31 +92,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
        init->AdapterFibsPhysicalAddress = cpu_to_le32((u32)phys);
        init->AdapterFibsSize = cpu_to_le32(fibsize);
        init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib));
-       /* 
-        * number of 4k pages of host physical memory. The aacraid fw needs
-        * this number to be less than 4gb worth of pages. num_physpages is in
-        * system page units. New firmware doesn't have any issues with the
-        * mapping system, but older Firmware did, and had *troubles* dealing
-        * with the math overloading past 32 bits, thus we must limit this
-        * field.
-        *
-        * This assumes the memory is mapped zero->n, which isnt
-        * always true on real computers. It also has some slight problems
-        * with the GART on x86-64. I've btw never tried DMA from PCI space
-        * on this platform but don't be surprised if its problematic.
-        * [AK: something is very very wrong when a driver tests this symbol.
-        *  Someone should figure out what the comment writer really meant here and fix
-        *  the code. Or just remove that bad code. ]
-        */
-#ifndef CONFIG_IOMMU
-       if ((num_physpages << (PAGE_SHIFT - 12)) <= AAC_MAX_HOSTPHYSMEMPAGES) {
-               init->HostPhysMemPages = 
-                       cpu_to_le32(num_physpages << (PAGE_SHIFT-12));
-       } else 
-#endif 
-       {
-               init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES);
-       }
+       init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES);
 
        init->InitFlags = 0;
        if (dev->new_comm_interface) {
index eb77456..df3346b 100644 (file)
@@ -1487,6 +1487,7 @@ typedef enum {
 } ahd_queue_alg;
 
 void                   ahd_set_tags(struct ahd_softc *ahd,
+                                    struct scsi_cmnd *cmd,
                                     struct ahd_devinfo *devinfo,
                                     ahd_queue_alg alg);
 
index 801fc81..a1e8ca7 100644 (file)
@@ -1090,7 +1090,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
 
                        /* Notify XPT */
                        ahd_send_async(ahd, devinfo.channel, devinfo.target,
-                                      CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
+                                      CAM_LUN_WILDCARD, AC_SENT_BDR);
 
                        /*
                         * Allow the sequencer to continue with
@@ -3062,7 +3062,7 @@ ahd_set_syncrate(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
                tinfo->curr.ppr_options = ppr_options;
 
                ahd_send_async(ahd, devinfo->channel, devinfo->target,
-                              CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
+                              CAM_LUN_WILDCARD, AC_TRANSFER_NEG);
                if (bootverbose) {
                        if (offset != 0) {
                                int options;
@@ -3184,7 +3184,7 @@ ahd_set_width(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
 
                tinfo->curr.width = width;
                ahd_send_async(ahd, devinfo->channel, devinfo->target,
-                              CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
+                              CAM_LUN_WILDCARD, AC_TRANSFER_NEG);
                if (bootverbose) {
                        printf("%s: target %d using %dbit transfers\n",
                               ahd_name(ahd), devinfo->target,
@@ -3211,12 +3211,14 @@ ahd_set_width(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
  * Update the current state of tagged queuing for a given target.
  */
 void
-ahd_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
-            ahd_queue_alg alg)
+ahd_set_tags(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
+            struct ahd_devinfo *devinfo, ahd_queue_alg alg)
 {
-       ahd_platform_set_tags(ahd, devinfo, alg);
+       struct scsi_device *sdev = cmd->device;
+
+       ahd_platform_set_tags(ahd, sdev, devinfo, alg);
        ahd_send_async(ahd, devinfo->channel, devinfo->target,
-                      devinfo->lun, AC_TRANSFER_NEG, &alg);
+                      devinfo->lun, AC_TRANSFER_NEG);
 }
 
 static void
@@ -4746,7 +4748,7 @@ ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
                        printf("(%s:%c:%d:%d): refuses tagged commands.  "
                               "Performing non-tagged I/O\n", ahd_name(ahd),
                               devinfo->channel, devinfo->target, devinfo->lun);
-                       ahd_set_tags(ahd, devinfo, AHD_QUEUE_NONE);
+                       ahd_set_tags(ahd, scb->io_ctx, devinfo, AHD_QUEUE_NONE);
                        mask = ~0x23;
                } else {
                        printf("(%s:%c:%d:%d): refuses %s tagged commands.  "
@@ -4754,7 +4756,7 @@ ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
                               ahd_name(ahd), devinfo->channel, devinfo->target,
                               devinfo->lun, tag_type == MSG_ORDERED_TASK
                               ? "ordered" : "head of queue");
-                       ahd_set_tags(ahd, devinfo, AHD_QUEUE_BASIC);
+                       ahd_set_tags(ahd, scb->io_ctx, devinfo, AHD_QUEUE_BASIC);
                        mask = ~0x03;
                }
 
@@ -5098,7 +5100,7 @@ ahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
        
        if (status != CAM_SEL_TIMEOUT)
                ahd_send_async(ahd, devinfo->channel, devinfo->target,
-                              CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
+                              CAM_LUN_WILDCARD, AC_SENT_BDR);
 
        if (message != NULL && bootverbose)
                printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd),
@@ -7952,7 +7954,7 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
 #endif
        /* Notify the XPT that a bus reset occurred */
        ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD,
-                      CAM_LUN_WILDCARD, AC_BUS_RESET, NULL);
+                      CAM_LUN_WILDCARD, AC_BUS_RESET);
 
        /*
         * Revert to async/narrow transfers until we renegotiate.
index e0ccdf3..b244c71 100644 (file)
@@ -484,7 +484,6 @@ ahd_linux_target_alloc(struct scsi_target *starget)
        struct seeprom_config *sc = ahd->seep_config;
        unsigned long flags;
        struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget);
-       struct ahd_linux_target *targ = scsi_transport_target_data(starget);
        struct ahd_devinfo devinfo;
        struct ahd_initiator_tinfo *tinfo;
        struct ahd_tmode_tstate *tstate;
@@ -495,7 +494,6 @@ ahd_linux_target_alloc(struct scsi_target *starget)
        BUG_ON(*ahd_targp != NULL);
 
        *ahd_targp = starget;
-       memset(targ, 0, sizeof(*targ));
 
        if (sc) {
                int flags = sc->device_flags[starget->id];
@@ -551,15 +549,11 @@ ahd_linux_slave_alloc(struct scsi_device *sdev)
 {
        struct  ahd_softc *ahd =
                *((struct ahd_softc **)sdev->host->hostdata);
-       struct scsi_target *starget = sdev->sdev_target;
-       struct ahd_linux_target *targ = scsi_transport_target_data(starget);
        struct ahd_linux_device *dev;
 
        if (bootverbose)
                printf("%s: Slave Alloc %d\n", ahd_name(ahd), sdev->id);
 
-       BUG_ON(targ->sdev[sdev->lun] != NULL);
-
        dev = scsi_transport_device_data(sdev);
        memset(dev, 0, sizeof(*dev));
 
@@ -576,8 +570,6 @@ ahd_linux_slave_alloc(struct scsi_device *sdev)
         */
        dev->maxtags = 0;
        
-       targ->sdev[sdev->lun] = sdev;
-
        return (0);
 }
 
@@ -599,23 +591,6 @@ ahd_linux_slave_configure(struct scsi_device *sdev)
        return 0;
 }
 
-static void
-ahd_linux_slave_destroy(struct scsi_device *sdev)
-{
-       struct  ahd_softc *ahd;
-       struct  ahd_linux_device *dev = scsi_transport_device_data(sdev);
-       struct  ahd_linux_target *targ = scsi_transport_target_data(sdev->sdev_target);
-
-       ahd = *((struct ahd_softc **)sdev->host->hostdata);
-       if (bootverbose)
-               printf("%s: Slave Destroy %d\n", ahd_name(ahd), sdev->id);
-
-       BUG_ON(dev->active);
-
-       targ->sdev[sdev->lun] = NULL;
-
-}
-
 #if defined(__i386__)
 /*
  * Return the disk geometry for the given SCSI device.
@@ -822,7 +797,6 @@ struct scsi_host_template aic79xx_driver_template = {
        .use_clustering         = ENABLE_CLUSTERING,
        .slave_alloc            = ahd_linux_slave_alloc,
        .slave_configure        = ahd_linux_slave_configure,
-       .slave_destroy          = ahd_linux_slave_destroy,
        .target_alloc           = ahd_linux_target_alloc,
        .target_destroy         = ahd_linux_target_destroy,
 };
@@ -1249,20 +1223,13 @@ void
 ahd_platform_free(struct ahd_softc *ahd)
 {
        struct scsi_target *starget;
-       int i, j;
+       int i;
 
        if (ahd->platform_data != NULL) {
                /* destroy all of the device and target objects */
                for (i = 0; i < AHD_NUM_TARGETS; i++) {
                        starget = ahd->platform_data->starget[i];
                        if (starget != NULL) {
-                               for (j = 0; j < AHD_NUM_LUNS; j++) {
-                                       struct ahd_linux_target *targ =
-                                               scsi_transport_target_data(starget);
-                                       if (targ->sdev[j] == NULL)
-                                               continue;
-                                       targ->sdev[j] = NULL;
-                               }
                                ahd->platform_data->starget[i] = NULL;
                        }
                }
@@ -1318,20 +1285,13 @@ ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb)
 }
 
 void
-ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
-                     ahd_queue_alg alg)
+ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev,
+                     struct ahd_devinfo *devinfo, ahd_queue_alg alg)
 {
-       struct scsi_target *starget;
-       struct ahd_linux_target *targ;
        struct ahd_linux_device *dev;
-       struct scsi_device *sdev;
        int was_queuing;
        int now_queuing;
 
-       starget = ahd->platform_data->starget[devinfo->target];
-       targ = scsi_transport_target_data(starget);
-       BUG_ON(targ == NULL);
-       sdev = targ->sdev[devinfo->lun];
        if (sdev == NULL)
                return;
 
@@ -1467,11 +1427,15 @@ ahd_linux_device_queue_depth(struct scsi_device *sdev)
        tags = ahd_linux_user_tagdepth(ahd, &devinfo);
        if (tags != 0 && sdev->tagged_supported != 0) {
 
-               ahd_set_tags(ahd, &devinfo, AHD_QUEUE_TAGGED);
+               ahd_platform_set_tags(ahd, sdev, &devinfo, AHD_QUEUE_TAGGED);
+               ahd_send_async(ahd, devinfo.channel, devinfo.target,
+                              devinfo.lun, AC_TRANSFER_NEG);
                ahd_print_devinfo(ahd, &devinfo);
                printf("Tagged Queuing enabled.  Depth %d\n", tags);
        } else {
-               ahd_set_tags(ahd, &devinfo, AHD_QUEUE_NONE);
+               ahd_platform_set_tags(ahd, sdev, &devinfo, AHD_QUEUE_NONE);
+               ahd_send_async(ahd, devinfo.channel, devinfo.target,
+                              devinfo.lun, AC_TRANSFER_NEG);
        }
 }
 
@@ -1629,7 +1593,7 @@ ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs)
 
 void
 ahd_send_async(struct ahd_softc *ahd, char channel,
-              u_int target, u_int lun, ac_code code, void *arg)
+              u_int target, u_int lun, ac_code code)
 {
        switch (code) {
        case AC_TRANSFER_NEG:
@@ -1956,7 +1920,7 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
                        }
                        ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);
                        ahd_set_scsi_status(scb, SCSI_STATUS_OK);
-                       ahd_platform_set_tags(ahd, &devinfo,
+                       ahd_platform_set_tags(ahd, sdev, &devinfo,
                                     (dev->flags & AHD_DEV_Q_BASIC)
                                   ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED);
                        break;
@@ -1966,7 +1930,7 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
                 * as if the target returned BUSY SCSI status.
                 */
                dev->openings = 1;
-               ahd_platform_set_tags(ahd, &devinfo,
+               ahd_platform_set_tags(ahd, sdev, &devinfo,
                             (dev->flags & AHD_DEV_Q_BASIC)
                           ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED);
                ahd_set_scsi_status(scb, SCSI_STATUS_BUSY);
@@ -2778,8 +2742,6 @@ ahd_linux_init(void)
        if (!ahd_linux_transport_template)
                return -ENODEV;
 
-       scsi_transport_reserve_target(ahd_linux_transport_template,
-                                     sizeof(struct ahd_linux_target));
        scsi_transport_reserve_device(ahd_linux_transport_template,
                                      sizeof(struct ahd_linux_device));
 
index 2b83316..b2e65e1 100644 (file)
@@ -263,7 +263,6 @@ typedef enum {
        AHD_DEV_PERIODIC_OTAG    = 0x40, /* Send OTAG to prevent starvation */
 } ahd_linux_dev_flags;
 
-struct ahd_linux_target;
 struct ahd_linux_device {
        TAILQ_ENTRY(ahd_linux_device) links;
 
@@ -343,12 +342,6 @@ struct ahd_linux_device {
 #define AHD_OTAG_THRESH        500
 };
 
-struct ahd_linux_target {
-       struct scsi_device       *sdev[AHD_NUM_LUNS];
-       struct ahd_transinfo      last_tinfo;
-       struct ahd_softc         *ahd;
-};
-
 /********************* Definitions Required by the Core ***********************/
 /*
  * Number of SG segments we require.  So long as the S/G segments for
@@ -865,7 +858,7 @@ ahd_freeze_scb(struct scb *scb)
         }
 }
 
-void   ahd_platform_set_tags(struct ahd_softc *ahd,
+void   ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev,
                              struct ahd_devinfo *devinfo, ahd_queue_alg);
 int    ahd_platform_abort_scbs(struct ahd_softc *ahd, int target,
                                char channel, int lun, u_int tag,
@@ -874,7 +867,7 @@ irqreturn_t
        ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs);
 void   ahd_done(struct ahd_softc*, struct scb*);
 void   ahd_send_async(struct ahd_softc *, char channel,
-                      u_int target, u_int lun, ac_code, void *);
+                      u_int target, u_int lun, ac_code);
 void   ahd_print_path(struct ahd_softc *, struct scb *);
 
 #ifdef CONFIG_PCI
index 24fd59a..c5f0ee5 100644 (file)
@@ -47,7 +47,7 @@ static int    copy_info(struct info_str *info, char *fmt, ...);
 static void    ahd_dump_target_state(struct ahd_softc *ahd,
                                      struct info_str *info,
                                      u_int our_id, char channel,
-                                     u_int target_id, u_int target_offset);
+                                     u_int target_id);
 static void    ahd_dump_device_state(struct info_str *info,
                                      struct scsi_device *sdev);
 static int     ahd_proc_write_seeprom(struct ahd_softc *ahd,
@@ -204,10 +204,8 @@ ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo)
 
 static void
 ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
-                     u_int our_id, char channel, u_int target_id,
-                     u_int target_offset)
+                     u_int our_id, char channel, u_int target_id)
 {
-       struct  ahd_linux_target *targ;
        struct  scsi_target *starget;
        struct  ahd_initiator_tinfo *tinfo;
        struct  ahd_tmode_tstate *tstate;
@@ -218,10 +216,9 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
        copy_info(info, "Target %d Negotiation Settings\n", target_id);
        copy_info(info, "\tUser: ");
        ahd_format_transinfo(info, &tinfo->user);
-       starget = ahd->platform_data->starget[target_offset];
+       starget = ahd->platform_data->starget[target_id];
        if (starget == NULL)
                return;
-       targ = scsi_transport_target_data(starget);
 
        copy_info(info, "\tGoal: ");
        ahd_format_transinfo(info, &tinfo->goal);
@@ -231,7 +228,7 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
        for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
                struct scsi_device *dev;
 
-               dev = targ->sdev[lun];
+               dev = scsi_device_lookup_by_target(starget, lun);
 
                if (dev == NULL)
                        continue;
@@ -355,7 +352,7 @@ ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
        copy_info(&info, "Allocated SCBs: %d, SG List Length: %d\n\n",
                  ahd->scb_data.numscbs, AHD_NSEG);
 
-       max_targ = 15;
+       max_targ = 16;
 
        if (ahd->seep_config == NULL)
                copy_info(&info, "No Serial EEPROM\n");
@@ -373,12 +370,12 @@ ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
        copy_info(&info, "\n");
 
        if ((ahd->features & AHD_WIDE) == 0)
-               max_targ = 7;
+               max_targ = 8;
 
-       for (i = 0; i <= max_targ; i++) {
+       for (i = 0; i < max_targ; i++) {
 
                ahd_dump_target_state(ahd, &info, ahd->our_id, 'A',
-                                     /*target_id*/i, /*target_offset*/i);
+                                     /*target_id*/i);
        }
        retval = info.pos > info.offset ? info.pos - info.offset : 0;
 done:
index 3ee4d4d..69e6e98 100644 (file)
@@ -2625,29 +2625,32 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        unsigned int base_io, tmport, error,n;
        unsigned char host_id;
        struct Scsi_Host *shpnt = NULL;
-       struct atp_unit atp_dev, *p;
+       struct atp_unit *atpdev, *p;
        unsigned char setupdata[2][16];
        int count = 0;
-       
+
+       atpdev = kzalloc(sizeof(*atpdev), GFP_KERNEL);
+       if (!atpdev)
+               return -ENOMEM;
+
        if (pci_enable_device(pdev))
-               return -EIO;
+               goto err_eio;
 
         if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
                 printk(KERN_INFO "atp870u: use 32bit DMA mask.\n");
         } else {
                 printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
-                return -EIO;
+               goto err_eio;
         }
 
-       memset(&atp_dev, 0, sizeof atp_dev);
        /*
         * It's probably easier to weed out some revisions like
         * this than via the PCI device table
         */
        if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) {
-               error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver);
-               if (atp_dev.chip_ver < 2)
-                       return -EIO;
+               error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atpdev->chip_ver);
+               if (atpdev->chip_ver < 2)
+                       goto err_eio;
        }
 
        switch (ent->device) {
@@ -2656,15 +2659,15 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        case ATP880_DEVID1:     
        case ATP880_DEVID2:     
        case ATP885_DEVID:      
-               atp_dev.chip_ver = 0x04;
+               atpdev->chip_ver = 0x04;
        default:
                break;
        }
        base_io = pci_resource_start(pdev, 0);
        base_io &= 0xfffffff8;
-       
+
        if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) {
-               error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver);
+               error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atpdev->chip_ver);
                pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
 
                host_id = inb(base_io + 0x39);
@@ -2672,17 +2675,17 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
                printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d"
                        "    IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
-               atp_dev.ioport[0] = base_io + 0x40;
-               atp_dev.pciport[0] = base_io + 0x28;
-               atp_dev.dev_id = ent->device;
-               atp_dev.host_id[0] = host_id;
+               atpdev->ioport[0] = base_io + 0x40;
+               atpdev->pciport[0] = base_io + 0x28;
+               atpdev->dev_id = ent->device;
+               atpdev->host_id[0] = host_id;
 
                tmport = base_io + 0x22;
-               atp_dev.scam_on = inb(tmport);
+               atpdev->scam_on = inb(tmport);
                tmport += 0x13;
-               atp_dev.global_map[0] = inb(tmport);
+               atpdev->global_map[0] = inb(tmport);
                tmport += 0x07;
-               atp_dev.ultra_map[0] = inw(tmport);
+               atpdev->ultra_map[0] = inw(tmport);
 
                n = 0x3f09;
 next_fblk_880:
@@ -2695,57 +2698,57 @@ next_fblk_880:
                if (inb(base_io + 0x30) == 0xff)
                        goto flash_ok_880;
 
-               atp_dev.sp[0][m++] = inb(base_io + 0x30);
-               atp_dev.sp[0][m++] = inb(base_io + 0x31);
-               atp_dev.sp[0][m++] = inb(base_io + 0x32);
-               atp_dev.sp[0][m++] = inb(base_io + 0x33);
+               atpdev->sp[0][m++] = inb(base_io + 0x30);
+               atpdev->sp[0][m++] = inb(base_io + 0x31);
+               atpdev->sp[0][m++] = inb(base_io + 0x32);
+               atpdev->sp[0][m++] = inb(base_io + 0x33);
                outw(n, base_io + 0x34);
                n += 0x0002;
-               atp_dev.sp[0][m++] = inb(base_io + 0x30);
-               atp_dev.sp[0][m++] = inb(base_io + 0x31);
-               atp_dev.sp[0][m++] = inb(base_io + 0x32);
-               atp_dev.sp[0][m++] = inb(base_io + 0x33);
+               atpdev->sp[0][m++] = inb(base_io + 0x30);
+               atpdev->sp[0][m++] = inb(base_io + 0x31);
+               atpdev->sp[0][m++] = inb(base_io + 0x32);
+               atpdev->sp[0][m++] = inb(base_io + 0x33);
                outw(n, base_io + 0x34);
                n += 0x0002;
-               atp_dev.sp[0][m++] = inb(base_io + 0x30);
-               atp_dev.sp[0][m++] = inb(base_io + 0x31);
-               atp_dev.sp[0][m++] = inb(base_io + 0x32);
-               atp_dev.sp[0][m++] = inb(base_io + 0x33);
+               atpdev->sp[0][m++] = inb(base_io + 0x30);
+               atpdev->sp[0][m++] = inb(base_io + 0x31);
+               atpdev->sp[0][m++] = inb(base_io + 0x32);
+               atpdev->sp[0][m++] = inb(base_io + 0x33);
                outw(n, base_io + 0x34);
                n += 0x0002;
-               atp_dev.sp[0][m++] = inb(base_io + 0x30);
-               atp_dev.sp[0][m++] = inb(base_io + 0x31);
-               atp_dev.sp[0][m++] = inb(base_io + 0x32);
-               atp_dev.sp[0][m++] = inb(base_io + 0x33);
+               atpdev->sp[0][m++] = inb(base_io + 0x30);
+               atpdev->sp[0][m++] = inb(base_io + 0x31);
+               atpdev->sp[0][m++] = inb(base_io + 0x32);
+               atpdev->sp[0][m++] = inb(base_io + 0x33);
                n += 0x0018;
                goto next_fblk_880;
 flash_ok_880:
                outw(0, base_io + 0x34);
-               atp_dev.ultra_map[0] = 0;
-               atp_dev.async[0] = 0;
+               atpdev->ultra_map[0] = 0;
+               atpdev->async[0] = 0;
                for (k = 0; k < 16; k++) {
                        n = 1;
                        n = n << k;
-                       if (atp_dev.sp[0][k] > 1) {
-                               atp_dev.ultra_map[0] |= n;
+                       if (atpdev->sp[0][k] > 1) {
+                               atpdev->ultra_map[0] |= n;
                        } else {
-                               if (atp_dev.sp[0][k] == 0)
-                                       atp_dev.async[0] |= n;
+                               if (atpdev->sp[0][k] == 0)
+                                       atpdev->async[0] |= n;
                        }
                }
-               atp_dev.async[0] = ~(atp_dev.async[0]);
-               outb(atp_dev.global_map[0], base_io + 0x35);
+               atpdev->async[0] = ~(atpdev->async[0]);
+               outb(atpdev->global_map[0], base_io + 0x35);
  
                shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
                if (!shpnt)
-                       return -ENOMEM;
+                       goto err_nomem;
 
                p = (struct atp_unit *)&shpnt->hostdata;
 
-               atp_dev.host = shpnt;
-               atp_dev.pdev = pdev;
+               atpdev->host = shpnt;
+               atpdev->pdev = pdev;
                pci_set_drvdata(pdev, p);
-               memcpy(p, &atp_dev, sizeof atp_dev);
+               memcpy(p, atpdev, sizeof(*atpdev));
                if (atp870u_init_tables(shpnt) < 0) {
                        printk(KERN_ERR "Unable to allocate tables for Acard controller\n");
                        goto unregister;
@@ -2798,24 +2801,24 @@ flash_ok_880:
                        printk(KERN_INFO "   ACARD AEC-67162 PCI Ultra3 LVD Host Adapter:  IO:%x, IRQ:%d.\n"
                               , base_io, pdev->irq);
                
-               atp_dev.pdev = pdev;    
-               atp_dev.dev_id  = ent->device;
-               atp_dev.baseport = base_io;
-               atp_dev.ioport[0] = base_io + 0x80;
-               atp_dev.ioport[1] = base_io + 0xc0;
-               atp_dev.pciport[0] = base_io + 0x40;
-               atp_dev.pciport[1] = base_io + 0x50;
+               atpdev->pdev = pdev;
+               atpdev->dev_id  = ent->device;
+               atpdev->baseport = base_io;
+               atpdev->ioport[0] = base_io + 0x80;
+               atpdev->ioport[1] = base_io + 0xc0;
+               atpdev->pciport[0] = base_io + 0x40;
+               atpdev->pciport[1] = base_io + 0x50;
                                
                shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
                if (!shpnt)
-                       return -ENOMEM;
+                       goto err_nomem;
                
                p = (struct atp_unit *)&shpnt->hostdata;
                
-               atp_dev.host = shpnt;
-               atp_dev.pdev = pdev;
+               atpdev->host = shpnt;
+               atpdev->pdev = pdev;
                pci_set_drvdata(pdev, p);
-               memcpy(p, &atp_dev, sizeof(struct atp_unit));
+               memcpy(p, atpdev, sizeof(struct atp_unit));
                if (atp870u_init_tables(shpnt) < 0)
                        goto unregister;
                        
@@ -2974,33 +2977,33 @@ flash_ok_885:
                printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d "
                        "IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
 
-               atp_dev.ioport[0] = base_io;
-               atp_dev.pciport[0] = base_io + 0x20;
-               atp_dev.dev_id = ent->device;
+               atpdev->ioport[0] = base_io;
+               atpdev->pciport[0] = base_io + 0x20;
+               atpdev->dev_id = ent->device;
                host_id &= 0x07;
-               atp_dev.host_id[0] = host_id;
+               atpdev->host_id[0] = host_id;
                tmport = base_io + 0x22;
-               atp_dev.scam_on = inb(tmport);
+               atpdev->scam_on = inb(tmport);
                tmport += 0x0b;
-               atp_dev.global_map[0] = inb(tmport++);
-               atp_dev.ultra_map[0] = inw(tmport);
+               atpdev->global_map[0] = inb(tmport++);
+               atpdev->ultra_map[0] = inw(tmport);
 
-               if (atp_dev.ultra_map[0] == 0) {
-                       atp_dev.scam_on = 0x00;
-                       atp_dev.global_map[0] = 0x20;
-                       atp_dev.ultra_map[0] = 0xffff;
+               if (atpdev->ultra_map[0] == 0) {
+                       atpdev->scam_on = 0x00;
+                       atpdev->global_map[0] = 0x20;
+                       atpdev->ultra_map[0] = 0xffff;
                }
 
                shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
                if (!shpnt)
-                       return -ENOMEM;
+                       goto err_nomem;
 
                p = (struct atp_unit *)&shpnt->hostdata;
                
-               atp_dev.host = shpnt;
-               atp_dev.pdev = pdev;
+               atpdev->host = shpnt;
+               atpdev->pdev = pdev;
                pci_set_drvdata(pdev, p);
-               memcpy(p, &atp_dev, sizeof atp_dev);
+               memcpy(p, atpdev, sizeof(*atpdev));
                if (atp870u_init_tables(shpnt) < 0)
                        goto unregister;
 
@@ -3010,7 +3013,7 @@ flash_ok_885:
                }
 
                spin_lock_irqsave(shpnt->host_lock, flags);
-               if (atp_dev.chip_ver > 0x07) {  /* check if atp876 chip then enable terminator */
+               if (atpdev->chip_ver > 0x07) {  /* check if atp876 chip then enable terminator */
                        tmport = base_io + 0x3e;
                        outb(0x00, tmport);
                }
@@ -3044,7 +3047,7 @@ flash_ok_885:
                outb((inb(tmport) & 0xef), tmport);
                tmport++;
                outb((inb(tmport) | 0x20), tmport);
-               if (atp_dev.chip_ver == 4)
+               if (atpdev->chip_ver == 4)
                        shpnt->max_id = 16;
                else            
                        shpnt->max_id = 8;
@@ -3093,6 +3096,12 @@ unregister:
        printk("atp870u_prob:unregister\n");
        scsi_host_put(shpnt);
        return -1;              
+err_eio:
+       kfree(atpdev);
+       return -EIO;
+err_nomem:
+       kfree(atpdev);
+       return -ENOMEM;
 }
 
 /* The abort command does not leave the device in a clean state where
index 944fc12..669ea4f 100644 (file)
@@ -535,6 +535,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
                                   struct ibmvscsi_host_data *hostdata)
 {
        u64 *crq_as_u64 = (u64 *) &evt_struct->crq;
+       int request_status;
        int rc;
 
        /* If we have exhausted our request limit, just fail this request.
@@ -542,9 +543,18 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
         * (such as task management requests) that the mid layer may think we
         * can handle more requests (can_queue) when we actually can't
         */
-       if ((evt_struct->crq.format == VIOSRP_SRP_FORMAT) &&
-           (atomic_dec_if_positive(&hostdata->request_limit) < 0))
-               goto send_error;
+       if (evt_struct->crq.format == VIOSRP_SRP_FORMAT) {
+               request_status =
+                       atomic_dec_if_positive(&hostdata->request_limit);
+               /* If request limit was -1 when we started, it is now even
+                * less than that
+                */
+               if (request_status < -1)
+                       goto send_error;
+               /* Otherwise, if we have run out of requests */
+               else if (request_status < 0)
+                       goto send_busy;
+       }
 
        /* Copy the IU into the transfer area */
        *evt_struct->xfer_iu = evt_struct->iu;
@@ -567,11 +577,23 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
 
        return 0;
 
- send_error:
+ send_busy:
        unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
 
        free_event_struct(&hostdata->pool, evt_struct);
        return SCSI_MLQUEUE_HOST_BUSY;
+
+ send_error:
+       unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
+
+       if (evt_struct->cmnd != NULL) {
+               evt_struct->cmnd->result = DID_ERROR << 16;
+               evt_struct->cmnd_done(evt_struct->cmnd);
+       } else if (evt_struct->done)
+               evt_struct->done(evt_struct);
+
+       free_event_struct(&hostdata->pool, evt_struct);
+       return 0;
 }
 
 /**
@@ -1184,27 +1206,37 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
                return;
        case 0xFF:      /* Hypervisor telling us the connection is closed */
                scsi_block_requests(hostdata->host);
+               atomic_set(&hostdata->request_limit, 0);
                if (crq->format == 0x06) {
                        /* We need to re-setup the interpartition connection */
                        printk(KERN_INFO
                               "ibmvscsi: Re-enabling adapter!\n");
-                       atomic_set(&hostdata->request_limit, -1);
                        purge_requests(hostdata, DID_REQUEUE);
-                       if (ibmvscsi_reenable_crq_queue(&hostdata->queue,
-                                                       hostdata) == 0)
-                               if (ibmvscsi_send_crq(hostdata,
-                                                     0xC001000000000000LL, 0))
+                       if ((ibmvscsi_reenable_crq_queue(&hostdata->queue,
+                                                       hostdata) == 0) ||
+                           (ibmvscsi_send_crq(hostdata,
+                                              0xC001000000000000LL, 0))) {
+                                       atomic_set(&hostdata->request_limit,
+                                                  -1);
                                        printk(KERN_ERR
-                                              "ibmvscsi: transmit error after"
+                                              "ibmvscsi: error after"
                                               " enable\n");
+                       }
                } else {
                        printk(KERN_INFO
                               "ibmvscsi: Virtual adapter failed rc %d!\n",
                               crq->format);
 
-                       atomic_set(&hostdata->request_limit, -1);
                        purge_requests(hostdata, DID_ERROR);
-                       ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata);
+                       if ((ibmvscsi_reset_crq_queue(&hostdata->queue,
+                                                       hostdata)) ||
+                           (ibmvscsi_send_crq(hostdata,
+                                              0xC001000000000000LL, 0))) {
+                                       atomic_set(&hostdata->request_limit,
+                                                  -1);
+                                       printk(KERN_ERR
+                                              "ibmvscsi: error after reset\n");
+                       }
                }
                scsi_unblock_requests(hostdata->host);
                return;
@@ -1467,6 +1499,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
        struct Scsi_Host *host;
        struct device *dev = &vdev->dev;
        unsigned long wait_switch = 0;
+       int rc;
 
        vdev->dev.driver_data = NULL;
 
@@ -1484,8 +1517,8 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
        atomic_set(&hostdata->request_limit, -1);
        hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */
 
-       if (ibmvscsi_init_crq_queue(&hostdata->queue, hostdata,
-                                   max_requests) != 0) {
+       rc = ibmvscsi_init_crq_queue(&hostdata->queue, hostdata, max_requests);
+       if (rc != 0 && rc != H_RESOURCE) {
                printk(KERN_ERR "ibmvscsi: couldn't initialize crq\n");
                goto init_crq_failed;
        }
@@ -1505,7 +1538,8 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
         * to fail if the other end is not acive.  In that case we don't
         * want to scan
         */
-       if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0) {
+       if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0
+           || rc == H_RESOURCE) {
                /*
                 * Wait around max init_timeout secs for the adapter to finish
                 * initializing. When we are done initializing, we will have a
index 1a9992b..242b887 100644 (file)
@@ -208,6 +208,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
                            int max_requests)
 {
        int rc;
+       int retrc;
        struct vio_dev *vdev = to_vio_dev(hostdata->dev);
 
        queue->msgs = (struct viosrp_crq *)get_zeroed_page(GFP_KERNEL);
@@ -226,7 +227,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
        gather_partition_info();
        set_adapter_info(hostdata);
 
-       rc = plpar_hcall_norets(H_REG_CRQ,
+       retrc = rc = plpar_hcall_norets(H_REG_CRQ,
                                vdev->unit_address,
                                queue->msg_token, PAGE_SIZE);
        if (rc == H_RESOURCE)
@@ -263,7 +264,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
        tasklet_init(&hostdata->srp_task, (void *)ibmvscsi_task,
                     (unsigned long)hostdata);
 
-       return 0;
+       return retrc;
 
       req_irq_failed:
        do {
index 087c445..f81691f 100644 (file)
@@ -174,7 +174,6 @@ struct lpfc_hba {
        dma_addr_t slim2p_mapping;
        uint16_t pci_cfg_value;
 
-       struct semaphore hba_can_block;
        int32_t hba_state;
 
 #define LPFC_STATE_UNKNOWN        0    /* HBA state is unknown */
index 283b7d8..4126fd8 100644 (file)
@@ -821,7 +821,7 @@ lpfc_issue_els_plogi(struct lpfc_hba * phba, uint32_t did, uint8_t retry)
        pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
 
        cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm));
-       elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, 0, did,
+       elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, NULL, did,
                                                                ELS_CMD_PLOGI);
        if (!elsiocb)
                return 1;
@@ -2791,8 +2791,8 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
 
        ndlp = (struct lpfc_nodelist *) pmb->context2;
        xri = (uint16_t) ((unsigned long)(pmb->context1));
-       pmb->context1 = 0;
-       pmb->context2 = 0;
+       pmb->context1 = NULL;
+       pmb->context2 = NULL;
 
        if (mb->mbxStatus) {
                mempool_free( pmb, phba->mbox_mem_pool);
index 908d0f2..f68ad76 100644 (file)
@@ -939,12 +939,12 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
                                        "10-port ", "PCIe"};
                        break;
                default:
-                       m = (typeof(m)){ 0 };
+                       m = (typeof(m)){ NULL };
                        break;
                }
                break;
        default:
-               m = (typeof(m)){ 0 };
+               m = (typeof(m)){ NULL };
                break;
        }
 
@@ -1451,7 +1451,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
                goto out_put_host;
 
        host->unique_id = phba->brd_no;
-       init_MUTEX(&phba->hba_can_block);
        INIT_LIST_HEAD(&phba->ctrspbuflist);
        INIT_LIST_HEAD(&phba->rnidrspbuflist);
        INIT_LIST_HEAD(&phba->freebufList);
index 7dc4c2e..aea1ee4 100644 (file)
 #define LPFC_ABORT_WAIT  2
 
 
-static inline void
-lpfc_block_requests(struct lpfc_hba * phba)
-{
-       down(&phba->hba_can_block);
-       scsi_block_requests(phba->host);
-}
-
-static inline void
-lpfc_unblock_requests(struct lpfc_hba * phba)
-{
-       scsi_unblock_requests(phba->host);
-       up(&phba->hba_can_block);
-}
-
 /*
  * This routine allocates a scsi buffer, which contains all the necessary
  * information needed to initiate a SCSI I/O.  The non-DMAable buffer region
@@ -859,7 +845,6 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
        unsigned int loop_count = 0;
        int ret = SUCCESS;
 
-       lpfc_block_requests(phba);
        spin_lock_irq(shost->host_lock);
 
        lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
@@ -945,7 +930,6 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
                        cmnd->device->lun, cmnd->serial_number);
 
        spin_unlock_irq(shost->host_lock);
-       lpfc_unblock_requests(phba);
 
        return ret;
 }
@@ -963,7 +947,6 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
        int ret = FAILED;
        int cnt, loopcnt;
 
-       lpfc_block_requests(phba);
        spin_lock_irq(shost->host_lock);
        /*
         * If target is not in a MAPPED state, delay the reset until
@@ -1065,7 +1048,6 @@ out_free_scsi_buf:
 
 out:
        spin_unlock_irq(shost->host_lock);
-       lpfc_unblock_requests(phba);
        return ret;
 }
 
@@ -1080,7 +1062,6 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
        int cnt, loopcnt;
        struct lpfc_scsi_buf * lpfc_cmd;
 
-       lpfc_block_requests(phba);
        spin_lock_irq(shost->host_lock);
 
        lpfc_cmd = lpfc_get_scsi_buf(phba);
@@ -1163,7 +1144,6 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
                        phba->brd_no, ret);
 out:
        spin_unlock_irq(shost->host_lock);
-       lpfc_unblock_requests(phba);
        return ret;
 }
 
index 0c9516f..3e6f9fe 100644 (file)
@@ -10,7 +10,7 @@
  *        2 of the License, or (at your option) any later version.
  *
  * FILE                : megaraid_sas.c
- * Version     : v00.00.02.04
+ * Version     : v00.00.03.01
  *
  * Authors:
  *     Sreenivas Bagalkote     <Sreenivas.Bagalkote@lsil.com>
@@ -55,19 +55,25 @@ static struct pci_device_id megasas_pci_table[] = {
 
        {
         PCI_VENDOR_ID_LSI_LOGIC,
-        PCI_DEVICE_ID_LSI_SAS1064R, // xscale IOP
+        PCI_DEVICE_ID_LSI_SAS1064R, /* xscale IOP */
         PCI_ANY_ID,
         PCI_ANY_ID,
         },
        {
         PCI_VENDOR_ID_LSI_LOGIC,
-        PCI_DEVICE_ID_LSI_SAS1078R, // ppc IOP
+        PCI_DEVICE_ID_LSI_SAS1078R, /* ppc IOP */
         PCI_ANY_ID,
         PCI_ANY_ID,
        },
+       {
+        PCI_VENDOR_ID_LSI_LOGIC,
+        PCI_DEVICE_ID_LSI_VERDE_ZCR,   /* xscale IOP, vega */
+        PCI_ANY_ID,
+        PCI_ANY_ID,
+        },
        {
         PCI_VENDOR_ID_DELL,
-        PCI_DEVICE_ID_DELL_PERC5, // xscale IOP
+        PCI_DEVICE_ID_DELL_PERC5, /* xscale IOP */
         PCI_ANY_ID,
         PCI_ANY_ID,
         },
@@ -289,9 +295,14 @@ static struct megasas_instance_template megasas_instance_template_ppc = {
  * @regs:                      MFI register set
  */
 static inline void
-megasas_disable_intr(struct megasas_register_set __iomem * regs)
+megasas_disable_intr(struct megasas_instance *instance)
 {
        u32 mask = 0x1f; 
+       struct megasas_register_set __iomem *regs = instance->reg_set;
+
+       if(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078R)
+               mask = 0xffffffff;
+
        writel(mask, &regs->outbound_intr_mask);
 
        /* Dummy readl to force pci flush */
@@ -1260,7 +1271,7 @@ megasas_transition_to_ready(struct megasas_instance* instance)
                        /*
                         * Bring it to READY state; assuming max wait 2 secs
                         */
-                       megasas_disable_intr(instance->reg_set);
+                       megasas_disable_intr(instance);
                        writel(MFI_INIT_READY, &instance->reg_set->inbound_doorbell);
 
                        max_wait = 10;
@@ -1756,6 +1767,11 @@ static int megasas_init_mfi(struct megasas_instance *instance)
 
        init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info);
 
+       /*
+        * disable the intr before firing the init frame to FW
+        */
+       megasas_disable_intr(instance);
+
        /*
         * Issue the init frame in polled mode
         */
@@ -2234,7 +2250,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        megasas_mgmt_info.max_index--;
 
        pci_set_drvdata(pdev, NULL);
-       megasas_disable_intr(instance->reg_set);
+       megasas_disable_intr(instance);
        free_irq(instance->pdev->irq, instance);
 
        megasas_release_mfi(instance);
@@ -2364,7 +2380,7 @@ static void megasas_detach_one(struct pci_dev *pdev)
 
        pci_set_drvdata(instance->pdev, NULL);
 
-       megasas_disable_intr(instance->reg_set);
+       megasas_disable_intr(instance);
 
        free_irq(instance->pdev->irq, instance);
 
index 927d6ff..3531a14 100644 (file)
 /**
  * MegaRAID SAS Driver meta data
  */
-#define MEGASAS_VERSION                                "00.00.02.04"
-#define MEGASAS_RELDATE                                "Feb 03, 2006"
-#define MEGASAS_EXT_VERSION                    "Fri Feb 03 14:31:44 PST 2006"
+#define MEGASAS_VERSION                                "00.00.03.01"
+#define MEGASAS_RELDATE                                "May 14, 2006"
+#define MEGASAS_EXT_VERSION                    "Sun May 14 22:49:52 PDT 2006"
+
+/*
+ * Device IDs
+ */
+#define        PCI_DEVICE_ID_LSI_SAS1078R              0x0060
+#define        PCI_DEVICE_ID_LSI_VERDE_ZCR             0x0413
+
 /*
  * =====================================
  * MegaRAID SAS MFI firmware definitions
@@ -554,7 +561,11 @@ struct megasas_ctrl_info {
 #define MFI_POLL_TIMEOUT_SECS                  10
 
 #define MFI_REPLY_1078_MESSAGE_INTERRUPT       0x80000000
-#define PCI_DEVICE_ID_LSI_SAS1078R             0x00000060
+
+/*
+* register set for both 1068 and 1078 controllers
+* structure extended for 1078 registers
+*/
  
 struct megasas_register_set {
        u32     reserved_0[4];                  /*0000h*/
@@ -1150,10 +1161,10 @@ struct compat_megasas_iocpacket {
        struct compat_iovec sgl[MAX_IOCTL_SGE];
 } __attribute__ ((packed));
 
+#define MEGASAS_IOC_FIRMWARE32 _IOWR('M', 1, struct compat_megasas_iocpacket)
 #endif
 
 #define MEGASAS_IOC_FIRMWARE   _IOWR('M', 1, struct megasas_iocpacket)
-#define MEGASAS_IOC_FIRMWARE32 _IOWR('M', 1, struct compat_megasas_iocpacket)
 #define MEGASAS_IOC_GET_AEN    _IOW('M', 3, struct megasas_aen)
 
 struct megasas_mgmt_info {
index 5c55e15..4190788 100644 (file)
@@ -2866,8 +2866,7 @@ static int nsp32_detect(struct scsi_host_template *sht)
         */
        nsp32_do_bus_reset(data);
 
-       ret = request_irq(host->irq, do_nsp32_isr,
-                         SA_SHIRQ | SA_SAMPLE_RANDOM, "nsp32", data);
+       ret = request_irq(host->irq, do_nsp32_isr, SA_SHIRQ, "nsp32", data);
        if (ret < 0) {
                nsp32_msg(KERN_ERR, "Unable to allocate IRQ for NinjaSCSI32 "
                          "SCSI PCI controller. Interrupt: %d", host->irq);
@@ -2886,12 +2885,19 @@ static int nsp32_detect(struct scsi_host_template *sht)
         }
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
-       scsi_add_host (host, &PCIDEV->dev);
+       ret = scsi_add_host(host, &PCIDEV->dev);
+       if (ret) {
+               nsp32_msg(KERN_ERR, "failed to add scsi host");
+               goto free_region;
+       }
        scsi_scan_host(host);
 #endif
        pci_set_drvdata(PCIDEV, host);
        return DETECT_OK;
 
+ free_region:
+       release_region(host->io_port, host->n_io_port);
+
  free_irq:
        free_irq(host->irq, data);
 
index 231f9c3..bb81218 100644 (file)
@@ -1623,7 +1623,7 @@ static int nsp_cs_probe(struct pcmcia_device *link)
        /* Interrupt handler */
        link->irq.Handler        = &nspintr;
        link->irq.Instance       = info;
-       link->irq.Attributes     |= (SA_SHIRQ | SA_SAMPLE_RANDOM);
+       link->irq.Attributes     |= SA_SHIRQ;
 
        /* General socket configuration */
        link->conf.Attributes    = CONF_ENABLE_IRQ;
index e96d58d..87f90c4 100644 (file)
@@ -16,15 +16,16 @@ qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off,
 {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
+       char *rbuf = (char *)ha->fw_dump;
 
        if (ha->fw_dump_reading == 0)
                return 0;
-       if (off > ha->fw_dump_buffer_len)
-               return 0;
-       if (off + count > ha->fw_dump_buffer_len)
-               count = ha->fw_dump_buffer_len - off;
+       if (off > ha->fw_dump_len)
+                return 0;
+       if (off + count > ha->fw_dump_len)
+               count = ha->fw_dump_len - off;
 
-       memcpy(buf, &ha->fw_dump_buffer[off], count);
+       memcpy(buf, &rbuf[off], count);
 
        return (count);
 }
@@ -36,7 +37,6 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off,
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
        int reading;
-       uint32_t dump_size;
 
        if (off != 0)
                return (0);
@@ -44,46 +44,27 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off,
        reading = simple_strtol(buf, NULL, 10);
        switch (reading) {
        case 0:
-               if (ha->fw_dump_reading == 1) {
-                       qla_printk(KERN_INFO, ha,
-                           "Firmware dump cleared on (%ld).\n", ha->host_no);
+               if (!ha->fw_dump_reading)
+                       break;
 
-                       vfree(ha->fw_dump_buffer);
-                       ha->fw_dump_buffer = NULL;
-                       ha->fw_dump_reading = 0;
-                       ha->fw_dumped = 0;
-               }
+               qla_printk(KERN_INFO, ha,
+                   "Firmware dump cleared on (%ld).\n", ha->host_no);
+
+               ha->fw_dump_reading = 0;
+               ha->fw_dumped = 0;
                break;
        case 1:
                if (ha->fw_dumped && !ha->fw_dump_reading) {
                        ha->fw_dump_reading = 1;
 
-                       if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
-                               dump_size = FW_DUMP_SIZE_24XX;
-                       else {
-                               dump_size = FW_DUMP_SIZE_1M;
-                               if (ha->fw_memory_size < 0x20000)
-                                       dump_size = FW_DUMP_SIZE_128K;
-                               else if (ha->fw_memory_size < 0x80000)
-                                       dump_size = FW_DUMP_SIZE_512K;
-                       }
-                       ha->fw_dump_buffer = (char *)vmalloc(dump_size);
-                       if (ha->fw_dump_buffer == NULL) {
-                               qla_printk(KERN_WARNING, ha,
-                                   "Unable to allocate memory for firmware "
-                                   "dump buffer (%d).\n", dump_size);
-
-                               ha->fw_dump_reading = 0;
-                               return (count);
-                       }
                        qla_printk(KERN_INFO, ha,
-                           "Firmware dump ready for read on (%ld).\n",
+                           "Raw firmware dump ready for read on (%ld).\n",
                            ha->host_no);
-                       memset(ha->fw_dump_buffer, 0, dump_size);
-                       ha->isp_ops.ascii_fw_dump(ha);
-                       ha->fw_dump_buffer_len = strlen(ha->fw_dump_buffer);
                }
                break;
+       case 2:
+               qla2x00_alloc_fw_dump(ha);
+               break;
        }
        return (count);
 }
@@ -313,9 +294,6 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off,
        if (!capable(CAP_SYS_ADMIN) || off != 0)
                return 0;
 
-       if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
-               return -ENOTSUPP;
-
        /* Read NVRAM. */
        spin_lock_irqsave(&ha->hardware_lock, flags);
        ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->vpd_base, ha->vpd_size);
@@ -335,9 +313,6 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, char *buf, loff_t off,
        if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size)
                return 0;
 
-       if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
-               return -ENOTSUPP;
-
        /* Write NVRAM. */
        spin_lock_irqsave(&ha->hardware_lock, flags);
        ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count);
@@ -357,6 +332,53 @@ static struct bin_attribute sysfs_vpd_attr = {
        .write = qla2x00_sysfs_write_vpd,
 };
 
+static ssize_t
+qla2x00_sysfs_read_sfp(struct kobject *kobj, char *buf, loff_t off,
+    size_t count)
+{
+       struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
+           struct device, kobj)));
+       uint16_t iter, addr, offset;
+       int rval;
+
+       if (!capable(CAP_SYS_ADMIN) || off != 0 || count != SFP_DEV_SIZE * 2)
+               return 0;
+
+       addr = 0xa0;
+       for (iter = 0, offset = 0; iter < (SFP_DEV_SIZE * 2) / SFP_BLOCK_SIZE;
+           iter++, offset += SFP_BLOCK_SIZE) {
+               if (iter == 4) {
+                       /* Skip to next device address. */
+                       addr = 0xa2;
+                       offset = 0;
+               }
+
+               rval = qla2x00_read_sfp(ha, ha->sfp_data_dma, addr, offset,
+                   SFP_BLOCK_SIZE);
+               if (rval != QLA_SUCCESS) {
+                       qla_printk(KERN_WARNING, ha,
+                           "Unable to read SFP data (%x/%x/%x).\n", rval,
+                           addr, offset);
+                       count = 0;
+                       break;
+               }
+               memcpy(buf, ha->sfp_data, SFP_BLOCK_SIZE);
+               buf += SFP_BLOCK_SIZE;
+       }
+
+       return count;
+}
+
+static struct bin_attribute sysfs_sfp_attr = {
+       .attr = {
+               .name = "sfp",
+               .mode = S_IRUSR | S_IWUSR,
+               .owner = THIS_MODULE,
+       },
+       .size = SFP_DEV_SIZE * 2,
+       .read = qla2x00_sysfs_read_sfp,
+};
+
 void
 qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
 {
@@ -367,7 +389,12 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
        sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr);
        sysfs_create_bin_file(&host->shost_gendev.kobj,
            &sysfs_optrom_ctl_attr);
-       sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr);
+       if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+               sysfs_create_bin_file(&host->shost_gendev.kobj,
+                   &sysfs_vpd_attr);
+               sysfs_create_bin_file(&host->shost_gendev.kobj,
+                   &sysfs_sfp_attr);
+       }
 }
 
 void
@@ -380,7 +407,12 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
        sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr);
        sysfs_remove_bin_file(&host->shost_gendev.kobj,
            &sysfs_optrom_ctl_attr);
-       sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_vpd_attr);
+       if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+               sysfs_remove_bin_file(&host->shost_gendev.kobj,
+                   &sysfs_vpd_attr);
+               sysfs_remove_bin_file(&host->shost_gendev.kobj,
+                   &sysfs_sfp_attr);
+       }
 
        if (ha->beacon_blink_led == 1)
                ha->isp_ops.beacon_off(ha);
index 74e5471..f6ed696 100644 (file)
@@ -8,7 +8,34 @@
 
 #include <linux/delay.h>
 
-static int qla_uprintf(char **, char *, ...);
+static inline void
+qla2xxx_prep_dump(scsi_qla_host_t *ha, struct qla2xxx_fw_dump *fw_dump)
+{
+       fw_dump->fw_major_version = htonl(ha->fw_major_version);
+       fw_dump->fw_minor_version = htonl(ha->fw_minor_version);
+       fw_dump->fw_subminor_version = htonl(ha->fw_subminor_version);
+       fw_dump->fw_attributes = htonl(ha->fw_attributes);
+
+       fw_dump->vendor = htonl(ha->pdev->vendor);
+       fw_dump->device = htonl(ha->pdev->device);
+       fw_dump->subsystem_vendor = htonl(ha->pdev->subsystem_vendor);
+       fw_dump->subsystem_device = htonl(ha->pdev->subsystem_device);
+}
+
+static inline void *
+qla2xxx_copy_queues(scsi_qla_host_t *ha, void *ptr)
+{
+       /* Request queue. */
+       memcpy(ptr, ha->request_ring, ha->request_q_length *
+           sizeof(request_t));
+
+       /* Response queue. */
+       ptr += ha->request_q_length * sizeof(request_t);
+       memcpy(ptr, ha->response_ring, ha->response_q_length  *
+           sizeof(response_t));
+
+       return ptr + (ha->response_q_length * sizeof(response_t));
+}
 
 /**
  * qla2300_fw_dump() - Dumps binary data from the 2300 firmware.
@@ -49,10 +76,11 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
                    "request...\n", ha->fw_dump);
                goto qla2300_fw_dump_failed;
        }
-       fw = ha->fw_dump;
+       fw = &ha->fw_dump->isp.isp23;
+       qla2xxx_prep_dump(ha, ha->fw_dump);
 
        rval = QLA_SUCCESS;
-       fw->hccr = RD_REG_WORD(&reg->hccr);
+       fw->hccr = htons(RD_REG_WORD(&reg->hccr));
 
        /* Pause RISC. */
        WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
@@ -73,85 +101,86 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
        if (rval == QLA_SUCCESS) {
                dmp_reg = (uint16_t __iomem *)(reg + 0);
                for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++)
-                       fw->pbiu_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x10);
                for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2; cnt++)
-                       fw->risc_host_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_host_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x40);
                for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
-                       fw->mailbox_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->ctrl_status, 0x40);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->resp_dma_reg) / 2; cnt++)
-                       fw->resp_dma_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->resp_dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->ctrl_status, 0x50);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++)
-                       fw->dma_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->ctrl_status, 0x00);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0xA0);
                for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++)
-                       fw->risc_hdw_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->pcr, 0x2000);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->risc_gp0_reg) / 2; cnt++)
-                       fw->risc_gp0_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_gp0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->pcr, 0x2200);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->risc_gp1_reg) / 2; cnt++)
-                       fw->risc_gp1_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_gp1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->pcr, 0x2400);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->risc_gp2_reg) / 2; cnt++)
-                       fw->risc_gp2_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_gp2_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->pcr, 0x2600);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->risc_gp3_reg) / 2; cnt++)
-                       fw->risc_gp3_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_gp3_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->pcr, 0x2800);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->risc_gp4_reg) / 2; cnt++)
-                       fw->risc_gp4_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_gp4_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->pcr, 0x2A00);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->risc_gp5_reg) / 2; cnt++)
-                       fw->risc_gp5_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_gp5_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->pcr, 0x2C00);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->risc_gp6_reg) / 2; cnt++)
-                       fw->risc_gp6_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_gp6_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->pcr, 0x2E00);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->risc_gp7_reg) / 2; cnt++)
-                       fw->risc_gp7_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_gp7_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->ctrl_status, 0x10);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->frame_buf_hdw_reg) / 2; cnt++)
-                       fw->frame_buf_hdw_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->frame_buf_hdw_reg[cnt] =
+                           htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->ctrl_status, 0x20);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->fpm_b0_reg) / 2; cnt++)
-                       fw->fpm_b0_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->fpm_b0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->ctrl_status, 0x30);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->fpm_b1_reg) / 2; cnt++)
-                       fw->fpm_b1_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->fpm_b1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                /* Reset RISC. */
                WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
@@ -226,7 +255,7 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
 
                if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
                        rval = mb0 & MBS_MASK;
-                       fw->risc_ram[cnt] = mb2;
+                       fw->risc_ram[cnt] = htons(mb2);
                } else {
                        rval = QLA_FUNCTION_FAILED;
                }
@@ -285,7 +314,7 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
 
                if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
                        rval = mb0 & MBS_MASK;
-                       fw->stack_ram[cnt] = mb2;
+                       fw->stack_ram[cnt] = htons(mb2);
                } else {
                        rval = QLA_FUNCTION_FAILED;
                }
@@ -345,12 +374,15 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
 
                if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
                        rval = mb0 & MBS_MASK;
-                       fw->data_ram[cnt] = mb2;
+                       fw->data_ram[cnt] = htons(mb2);
                } else {
                        rval = QLA_FUNCTION_FAILED;
                }
        }
 
+       if (rval == QLA_SUCCESS)
+               qla2xxx_copy_queues(ha, &fw->data_ram[cnt]);
+
        if (rval != QLA_SUCCESS) {
                qla_printk(KERN_WARNING, ha,
                    "Failed to dump firmware (%x)!!!\n", rval);
@@ -368,193 +400,6 @@ qla2300_fw_dump_failed:
                spin_unlock_irqrestore(&ha->hardware_lock, flags);
 }
 
-/**
- * qla2300_ascii_fw_dump() - Converts a binary firmware dump to ASCII.
- * @ha: HA context
- */
-void
-qla2300_ascii_fw_dump(scsi_qla_host_t *ha)
-{
-       uint32_t cnt;
-       char *uiter;
-       char fw_info[30];
-       struct qla2300_fw_dump *fw;
-       uint32_t data_ram_cnt;
-
-       uiter = ha->fw_dump_buffer;
-       fw = ha->fw_dump;
-
-       qla_uprintf(&uiter, "%s Firmware Version %s\n", ha->model_number,
-           ha->isp_ops.fw_version_str(ha, fw_info));
-
-       qla_uprintf(&uiter, "\n[==>BEG]\n");
-
-       qla_uprintf(&uiter, "HCCR Register:\n%04x\n\n", fw->hccr);
-
-       qla_uprintf(&uiter, "PBIU Registers:");
-       for (cnt = 0; cnt < sizeof (fw->pbiu_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->pbiu_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nReqQ-RspQ-Risc2Host Status registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_host_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_host_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nMailbox Registers:");
-       for (cnt = 0; cnt < sizeof (fw->mailbox_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->mailbox_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nAuto Request Response DMA Registers:");
-       for (cnt = 0; cnt < sizeof (fw->resp_dma_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->resp_dma_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nDMA Registers:");
-       for (cnt = 0; cnt < sizeof (fw->dma_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->dma_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC Hardware Registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_hdw_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_hdw_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC GP0 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_gp0_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_gp0_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC GP1 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_gp1_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_gp1_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC GP2 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_gp2_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_gp2_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC GP3 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_gp3_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_gp3_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC GP4 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_gp4_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_gp4_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC GP5 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_gp5_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_gp5_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC GP6 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_gp6_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_gp6_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC GP7 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_gp7_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_gp7_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nFrame Buffer Hardware Registers:");
-       for (cnt = 0; cnt < sizeof (fw->frame_buf_hdw_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->frame_buf_hdw_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nFPM B0 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->fpm_b0_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->fpm_b0_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nFPM B1 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->fpm_b1_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->fpm_b1_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nCode RAM Dump:");
-       for (cnt = 0; cnt < sizeof (fw->risc_ram) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n%04x: ", cnt + 0x0800);
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_ram[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nStack RAM Dump:");
-       for (cnt = 0; cnt < sizeof (fw->stack_ram) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n%05x: ", cnt + 0x10000);
-               }
-               qla_uprintf(&uiter, "%04x ", fw->stack_ram[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nData RAM Dump:");
-       data_ram_cnt = ha->fw_memory_size - 0x11000 + 1;
-       for (cnt = 0; cnt < data_ram_cnt; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n%05x: ", cnt + 0x11000);
-               }
-               qla_uprintf(&uiter, "%04x ", fw->data_ram[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\n[<==END] ISP Debug Dump.");
-}
-
 /**
  * qla2100_fw_dump() - Dumps binary data from the 2100/2200 firmware.
  * @ha: HA context
@@ -591,10 +436,11 @@ qla2100_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
                    "request...\n", ha->fw_dump);
                goto qla2100_fw_dump_failed;
        }
-       fw = ha->fw_dump;
+       fw = &ha->fw_dump->isp.isp21;
+       qla2xxx_prep_dump(ha, ha->fw_dump);
 
        rval = QLA_SUCCESS;
-       fw->hccr = RD_REG_WORD(&reg->hccr);
+       fw->hccr = htons(RD_REG_WORD(&reg->hccr));
 
        /* Pause RISC. */
        WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
@@ -608,79 +454,81 @@ qla2100_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
        if (rval == QLA_SUCCESS) {
                dmp_reg = (uint16_t __iomem *)(reg + 0);
                for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++)
-                       fw->pbiu_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x10);
                for (cnt = 0; cnt < ha->mbx_count; cnt++) {
                        if (cnt == 8) {
-                               dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0xe0);
+                               dmp_reg = (uint16_t __iomem *)
+                                       ((uint8_t __iomem *)reg + 0xe0);
                        }
-                       fw->mailbox_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
                }
 
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x20);
                for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++)
-                       fw->dma_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->ctrl_status, 0x00);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0xA0);
                for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++)
-                       fw->risc_hdw_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->pcr, 0x2000);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->risc_gp0_reg) / 2; cnt++)
-                       fw->risc_gp0_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_gp0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->pcr, 0x2100);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->risc_gp1_reg) / 2; cnt++)
-                       fw->risc_gp1_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_gp1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->pcr, 0x2200);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->risc_gp2_reg) / 2; cnt++)
-                       fw->risc_gp2_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_gp2_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->pcr, 0x2300);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->risc_gp3_reg) / 2; cnt++)
-                       fw->risc_gp3_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_gp3_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->pcr, 0x2400);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->risc_gp4_reg) / 2; cnt++)
-                       fw->risc_gp4_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_gp4_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->pcr, 0x2500);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->risc_gp5_reg) / 2; cnt++)
-                       fw->risc_gp5_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_gp5_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->pcr, 0x2600);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->risc_gp6_reg) / 2; cnt++)
-                       fw->risc_gp6_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_gp6_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->pcr, 0x2700);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->risc_gp7_reg) / 2; cnt++)
-                       fw->risc_gp7_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->risc_gp7_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->ctrl_status, 0x10);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->frame_buf_hdw_reg) / 2; cnt++)
-                       fw->frame_buf_hdw_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->frame_buf_hdw_reg[cnt] =
+                           htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->ctrl_status, 0x20);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->fpm_b0_reg) / 2; cnt++)
-                       fw->fpm_b0_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->fpm_b0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                WRT_REG_WORD(&reg->ctrl_status, 0x30);
                dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->fpm_b1_reg) / 2; cnt++)
-                       fw->fpm_b1_reg[cnt] = RD_REG_WORD(dmp_reg++);
+                       fw->fpm_b1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
 
                /* Reset the ISP. */
                WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
@@ -755,12 +603,15 @@ qla2100_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
 
                if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
                        rval = mb0 & MBS_MASK;
-                       fw->risc_ram[cnt] = mb2;
+                       fw->risc_ram[cnt] = htons(mb2);
                } else {
                        rval = QLA_FUNCTION_FAILED;
                }
        }
 
+       if (rval == QLA_SUCCESS)
+               qla2xxx_copy_queues(ha, &fw->risc_ram[cnt]);
+
        if (rval != QLA_SUCCESS) {
                qla_printk(KERN_WARNING, ha,
                    "Failed to dump firmware (%x)!!!\n", rval);
@@ -778,179 +629,6 @@ qla2100_fw_dump_failed:
                spin_unlock_irqrestore(&ha->hardware_lock, flags);
 }
 
-/**
- * qla2100_ascii_fw_dump() - Converts a binary firmware dump to ASCII.
- * @ha: HA context
- */
-void
-qla2100_ascii_fw_dump(scsi_qla_host_t *ha)
-{
-       uint32_t cnt;
-       char *uiter;
-       char fw_info[30];
-       struct qla2100_fw_dump *fw;
-
-       uiter = ha->fw_dump_buffer;
-       fw = ha->fw_dump;
-
-       qla_uprintf(&uiter, "%s Firmware Version %s\n", ha->model_number,
-           ha->isp_ops.fw_version_str(ha, fw_info));
-
-       qla_uprintf(&uiter, "\n[==>BEG]\n");
-
-       qla_uprintf(&uiter, "HCCR Register:\n%04x\n\n", fw->hccr);
-
-       qla_uprintf(&uiter, "PBIU Registers:");
-       for (cnt = 0; cnt < sizeof (fw->pbiu_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->pbiu_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nMailbox Registers:");
-       for (cnt = 0; cnt < sizeof (fw->mailbox_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->mailbox_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nDMA Registers:");
-       for (cnt = 0; cnt < sizeof (fw->dma_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->dma_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC Hardware Registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_hdw_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_hdw_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC GP0 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_gp0_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_gp0_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC GP1 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_gp1_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_gp1_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC GP2 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_gp2_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_gp2_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC GP3 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_gp3_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_gp3_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC GP4 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_gp4_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_gp4_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC GP5 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_gp5_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_gp5_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC GP6 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_gp6_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_gp6_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC GP7 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->risc_gp7_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_gp7_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nFrame Buffer Hardware Registers:");
-       for (cnt = 0; cnt < sizeof (fw->frame_buf_hdw_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->frame_buf_hdw_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nFPM B0 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->fpm_b0_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->fpm_b0_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nFPM B1 Registers:");
-       for (cnt = 0; cnt < sizeof (fw->fpm_b1_reg) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n");
-               }
-               qla_uprintf(&uiter, "%04x ", fw->fpm_b1_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC SRAM:");
-       for (cnt = 0; cnt < sizeof (fw->risc_ram) / 2; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n%04x: ", cnt + 0x1000);
-               }
-               qla_uprintf(&uiter, "%04x ", fw->risc_ram[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\n[<==END] ISP Debug Dump.");
-
-       return;
-}
-
-static int
-qla_uprintf(char **uiter, char *fmt, ...)
-{
-       int     iter, len;
-       char    buf[128];
-       va_list args;
-
-       va_start(args, fmt);
-       len = vsprintf(buf, fmt, args);
-       va_end(args);
-
-       for (iter = 0; iter < len; iter++, *uiter += 1)
-               *uiter[0] = buf[iter];
-
-       return (len);
-}
-
-
 void
 qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
 {
@@ -967,6 +645,7 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
        unsigned long   flags;
        struct qla24xx_fw_dump *fw;
        uint32_t        ext_mem_cnt;
+       void            *eft;
 
        risc_address = ext_mem_cnt = 0;
        memset(mb, 0, sizeof(mb));
@@ -987,10 +666,11 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
                    "request...\n", ha->fw_dump);
                goto qla24xx_fw_dump_failed;
        }
-       fw = ha->fw_dump;
+       fw = &ha->fw_dump->isp.isp24;
+       qla2xxx_prep_dump(ha, ha->fw_dump);
 
        rval = QLA_SUCCESS;
-       fw->host_status = RD_REG_DWORD(&reg->host_status);
+       fw->host_status = htonl(RD_REG_DWORD(&reg->host_status));
 
        /* Pause RISC. */
        if ((RD_REG_DWORD(&reg->hccr) & HCCRX_RISC_PAUSE) == 0) {
@@ -1012,7 +692,7 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
                /* Host interface registers. */
                dmp_reg = (uint32_t __iomem *)(reg + 0);
                for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
-                       fw->host_reg[cnt] = RD_REG_DWORD(dmp_reg++);
+                       fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
 
                /* Disable interrupts. */
                WRT_REG_DWORD(&reg->ictrl, 0);
@@ -1024,470 +704,471 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
                WRT_REG_DWORD(dmp_reg, 0xB0000000);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
-               fw->shadow_reg[0] = RD_REG_DWORD(dmp_reg);
+               fw->shadow_reg[0] = htonl(RD_REG_DWORD(dmp_reg));
 
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
                WRT_REG_DWORD(dmp_reg, 0xB0100000);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
-               fw->shadow_reg[1] = RD_REG_DWORD(dmp_reg);
+               fw->shadow_reg[1] = htonl(RD_REG_DWORD(dmp_reg));
 
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
                WRT_REG_DWORD(dmp_reg, 0xB0200000);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
-               fw->shadow_reg[2] = RD_REG_DWORD(dmp_reg);
+               fw->shadow_reg[2] = htonl(RD_REG_DWORD(dmp_reg));
 
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
                WRT_REG_DWORD(dmp_reg, 0xB0300000);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
-               fw->shadow_reg[3] = RD_REG_DWORD(dmp_reg);
+               fw->shadow_reg[3] = htonl(RD_REG_DWORD(dmp_reg));
 
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
                WRT_REG_DWORD(dmp_reg, 0xB0400000);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
-               fw->shadow_reg[4] = RD_REG_DWORD(dmp_reg);
+               fw->shadow_reg[4] = htonl(RD_REG_DWORD(dmp_reg));
 
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
                WRT_REG_DWORD(dmp_reg, 0xB0500000);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
-               fw->shadow_reg[5] = RD_REG_DWORD(dmp_reg);
+               fw->shadow_reg[5] = htonl(RD_REG_DWORD(dmp_reg));
 
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
                WRT_REG_DWORD(dmp_reg, 0xB0600000);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
-               fw->shadow_reg[6] = RD_REG_DWORD(dmp_reg);
+               fw->shadow_reg[6] = htonl(RD_REG_DWORD(dmp_reg));
 
                /* Mailbox registers. */
                mbx_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
                for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
-                       fw->mailbox_reg[cnt] = RD_REG_WORD(mbx_reg++);
+                       fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
 
                /* Transfer sequence registers. */
                iter_reg = fw->xseq_gp_reg;
                WRT_REG_DWORD(&reg->iobase_addr, 0xBF00);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xBF10);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xBF20);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xBF30);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xBF40);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xBF50);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xBF60);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xBF70);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xBFE0);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < sizeof(fw->xseq_0_reg) / 4; cnt++)
-                       fw->xseq_0_reg[cnt] = RD_REG_DWORD(dmp_reg++);
+                       fw->xseq_0_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xBFF0);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < sizeof(fw->xseq_1_reg) / 4; cnt++)
-                       fw->xseq_1_reg[cnt] = RD_REG_DWORD(dmp_reg++);
+                       fw->xseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
 
                /* Receive sequence registers. */
                iter_reg = fw->rseq_gp_reg;
                WRT_REG_DWORD(&reg->iobase_addr, 0xFF00);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xFF10);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xFF20);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xFF30);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xFF40);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xFF50);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xFF60);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xFF70);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xFFD0);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < sizeof(fw->rseq_0_reg) / 4; cnt++)
-                       fw->rseq_0_reg[cnt] = RD_REG_DWORD(dmp_reg++);
+                       fw->rseq_0_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xFFE0);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < sizeof(fw->rseq_1_reg) / 4; cnt++)
-                       fw->rseq_1_reg[cnt] = RD_REG_DWORD(dmp_reg++);
+                       fw->rseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0xFFF0);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < sizeof(fw->rseq_2_reg) / 4; cnt++)
-                       fw->rseq_2_reg[cnt] = RD_REG_DWORD(dmp_reg++);
+                       fw->rseq_2_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
 
                /* Command DMA registers. */
                WRT_REG_DWORD(&reg->iobase_addr, 0x7100);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < sizeof(fw->cmd_dma_reg) / 4; cnt++)
-                       fw->cmd_dma_reg[cnt] = RD_REG_DWORD(dmp_reg++);
+                       fw->cmd_dma_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
 
                /* Queues. */
                iter_reg = fw->req0_dma_reg;
                WRT_REG_DWORD(&reg->iobase_addr, 0x7200);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 8; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xE4);
                for (cnt = 0; cnt < 7; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                iter_reg = fw->resp0_dma_reg;
                WRT_REG_DWORD(&reg->iobase_addr, 0x7300);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 8; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xE4);
                for (cnt = 0; cnt < 7; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                iter_reg = fw->req1_dma_reg;
                WRT_REG_DWORD(&reg->iobase_addr, 0x7400);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 8; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xE4);
                for (cnt = 0; cnt < 7; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                /* Transmit DMA registers. */
                iter_reg = fw->xmt0_dma_reg;
                WRT_REG_DWORD(&reg->iobase_addr, 0x7600);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x7610);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                iter_reg = fw->xmt1_dma_reg;
                WRT_REG_DWORD(&reg->iobase_addr, 0x7620);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x7630);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                iter_reg = fw->xmt2_dma_reg;
                WRT_REG_DWORD(&reg->iobase_addr, 0x7640);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x7650);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                iter_reg = fw->xmt3_dma_reg;
                WRT_REG_DWORD(&reg->iobase_addr, 0x7660);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x7670);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                iter_reg = fw->xmt4_dma_reg;
                WRT_REG_DWORD(&reg->iobase_addr, 0x7680);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x7690);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x76A0);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < sizeof(fw->xmt_data_dma_reg) / 4; cnt++)
-                       fw->xmt_data_dma_reg[cnt] = RD_REG_DWORD(dmp_reg++);
+                       fw->xmt_data_dma_reg[cnt] =
+                           htonl(RD_REG_DWORD(dmp_reg++));
 
                /* Receive DMA registers. */
                iter_reg = fw->rcvt0_data_dma_reg;
                WRT_REG_DWORD(&reg->iobase_addr, 0x7700);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x7710);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                iter_reg = fw->rcvt1_data_dma_reg;
                WRT_REG_DWORD(&reg->iobase_addr, 0x7720);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x7730);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                /* RISC registers. */
                iter_reg = fw->risc_gp_reg;
                WRT_REG_DWORD(&reg->iobase_addr, 0x0F00);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x0F10);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x0F20);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x0F30);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x0F40);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x0F50);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x0F60);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                /* Local memory controller registers. */
                iter_reg = fw->lmc_reg;
                WRT_REG_DWORD(&reg->iobase_addr, 0x3000);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x3010);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x3020);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x3030);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x3040);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x3050);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x3060);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                /* Fibre Protocol Module registers. */
                iter_reg = fw->fpm_hdw_reg;
                WRT_REG_DWORD(&reg->iobase_addr, 0x4000);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x4010);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x4020);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x4030);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x4040);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x4050);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x4060);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x4070);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x4080);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x4090);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x40A0);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x40B0);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                /* Frame Buffer registers. */
                iter_reg = fw->fb_hdw_reg;
                WRT_REG_DWORD(&reg->iobase_addr, 0x6000);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x6010);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x6020);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x6030);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x6040);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x6100);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x6130);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x6150);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x6170);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x6190);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                WRT_REG_DWORD(&reg->iobase_addr, 0x61B0);
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0);
                for (cnt = 0; cnt < 16; cnt++)
-                       *iter_reg++ = RD_REG_DWORD(dmp_reg++);
+                       *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
 
                /* Reset RISC. */
                WRT_REG_DWORD(&reg->ctrl_status,
@@ -1577,7 +1258,7 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
 
                if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
                        rval = mb[0] & MBS_MASK;
-                       fw->code_ram[cnt] = (mb[3] << 16) | mb[2];
+                       fw->code_ram[cnt] = htonl((mb[3] << 16) | mb[2]);
                } else {
                        rval = QLA_FUNCTION_FAILED;
                }
@@ -1627,12 +1308,18 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
 
                if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
                        rval = mb[0] & MBS_MASK;
-                       fw->ext_mem[cnt] = (mb[3] << 16) | mb[2];
+                       fw->ext_mem[cnt] = htonl((mb[3] << 16) | mb[2]);
                } else {
                        rval = QLA_FUNCTION_FAILED;
                }
        }
 
+       if (rval == QLA_SUCCESS) {
+               eft = qla2xxx_copy_queues(ha, &fw->ext_mem[cnt]);
+               if (ha->eft)
+                       memcpy(eft, ha->eft, ntohl(ha->fw_dump->eft_size));
+       }
+
        if (rval != QLA_SUCCESS) {
                qla_printk(KERN_WARNING, ha,
                    "Failed to dump firmware (%x)!!!\n", rval);
@@ -1650,252 +1337,6 @@ qla24xx_fw_dump_failed:
                spin_unlock_irqrestore(&ha->hardware_lock, flags);
 }
 
-void
-qla24xx_ascii_fw_dump(scsi_qla_host_t *ha)
-{
-       uint32_t cnt;
-       char *uiter;
-       struct qla24xx_fw_dump *fw;
-       uint32_t ext_mem_cnt;
-
-       uiter = ha->fw_dump_buffer;
-       fw = ha->fw_dump;
-
-       qla_uprintf(&uiter, "ISP FW Version %d.%02d.%02d Attributes %04x\n",
-           ha->fw_major_version, ha->fw_minor_version,
-           ha->fw_subminor_version, ha->fw_attributes);
-
-       qla_uprintf(&uiter, "\nR2H Status Register\n%04x\n", fw->host_status);
-
-       qla_uprintf(&uiter, "\nHost Interface Registers");
-       for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->host_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nShadow Registers");
-       for (cnt = 0; cnt < sizeof(fw->shadow_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->shadow_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nMailbox Registers");
-       for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->mailbox_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nXSEQ GP Registers");
-       for (cnt = 0; cnt < sizeof(fw->xseq_gp_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->xseq_gp_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nXSEQ-0 Registers");
-       for (cnt = 0; cnt < sizeof(fw->xseq_0_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->xseq_0_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nXSEQ-1 Registers");
-       for (cnt = 0; cnt < sizeof(fw->xseq_1_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->xseq_1_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRSEQ GP Registers");
-       for (cnt = 0; cnt < sizeof(fw->rseq_gp_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->rseq_gp_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRSEQ-0 Registers");
-       for (cnt = 0; cnt < sizeof(fw->rseq_0_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->rseq_0_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRSEQ-1 Registers");
-       for (cnt = 0; cnt < sizeof(fw->rseq_1_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->rseq_1_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRSEQ-2 Registers");
-       for (cnt = 0; cnt < sizeof(fw->rseq_2_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->rseq_2_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nCommand DMA Registers");
-       for (cnt = 0; cnt < sizeof(fw->cmd_dma_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->cmd_dma_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRequest0 Queue DMA Channel Registers");
-       for (cnt = 0; cnt < sizeof(fw->req0_dma_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->req0_dma_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nResponse0 Queue DMA Channel Registers");
-       for (cnt = 0; cnt < sizeof(fw->resp0_dma_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->resp0_dma_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRequest1 Queue DMA Channel Registers");
-       for (cnt = 0; cnt < sizeof(fw->req1_dma_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->req1_dma_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nXMT0 Data DMA Registers");
-       for (cnt = 0; cnt < sizeof(fw->xmt0_dma_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->xmt0_dma_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nXMT1 Data DMA Registers");
-       for (cnt = 0; cnt < sizeof(fw->xmt1_dma_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->xmt1_dma_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nXMT2 Data DMA Registers");
-       for (cnt = 0; cnt < sizeof(fw->xmt2_dma_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->xmt2_dma_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nXMT3 Data DMA Registers");
-       for (cnt = 0; cnt < sizeof(fw->xmt3_dma_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->xmt3_dma_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nXMT4 Data DMA Registers");
-       for (cnt = 0; cnt < sizeof(fw->xmt4_dma_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->xmt4_dma_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nXMT Data DMA Common Registers");
-       for (cnt = 0; cnt < sizeof(fw->xmt_data_dma_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->xmt_data_dma_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRCV Thread 0 Data DMA Registers");
-       for (cnt = 0; cnt < sizeof(fw->rcvt0_data_dma_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->rcvt0_data_dma_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRCV Thread 1 Data DMA Registers");
-       for (cnt = 0; cnt < sizeof(fw->rcvt1_data_dma_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->rcvt1_data_dma_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nRISC GP Registers");
-       for (cnt = 0; cnt < sizeof(fw->risc_gp_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->risc_gp_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nLMC Registers");
-       for (cnt = 0; cnt < sizeof(fw->lmc_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->lmc_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nFPM Hardware Registers");
-       for (cnt = 0; cnt < sizeof(fw->fpm_hdw_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->fpm_hdw_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nFB Hardware Registers");
-       for (cnt = 0; cnt < sizeof(fw->fb_hdw_reg) / 4; cnt++) {
-               if (cnt % 8 == 0)
-                       qla_uprintf(&uiter, "\n");
-
-               qla_uprintf(&uiter, "%08x ", fw->fb_hdw_reg[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nCode RAM");
-       for (cnt = 0; cnt < sizeof (fw->code_ram) / 4; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n%08x: ", cnt + 0x20000);
-               }
-               qla_uprintf(&uiter, "%08x ", fw->code_ram[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n\nExternal Memory");
-       ext_mem_cnt = ha->fw_memory_size - 0x100000 + 1;
-       for (cnt = 0; cnt < ext_mem_cnt; cnt++) {
-               if (cnt % 8 == 0) {
-                       qla_uprintf(&uiter, "\n%08x: ", cnt + 0x100000);
-               }
-               qla_uprintf(&uiter, "%08x ", fw->ext_mem[cnt]);
-       }
-
-       qla_uprintf(&uiter, "\n[<==END] ISP Debug Dump");
-}
-
-
 /****************************************************************************/
 /*                         Driver Debug Functions.                          */
 /****************************************************************************/
index ab6afea..5334253 100644 (file)
 /*
 * Macros use for debugging the driver.
 */
-#undef ENTER_TRACE
-#if defined(ENTER_TRACE)
-#define ENTER(x)       do { printk("qla2100 : Entering %s()\n", x); } while (0)
-#define LEAVE(x)       do { printk("qla2100 : Leaving %s()\n", x);  } while (0)
-#define ENTER_INTR(x)  do { printk("qla2100 : Entering %s()\n", x); } while (0)
-#define LEAVE_INTR(x)  do { printk("qla2100 : Leaving %s()\n", x);  } while (0)
-#else
-#define ENTER(x)       do {} while (0)
-#define LEAVE(x)       do {} while (0)
-#define ENTER_INTR(x)  do {} while (0)
-#define LEAVE_INTR(x)   do {} while (0)
-#endif
 
-#if  DEBUG_QLA2100
-#define DEBUG(x)       do {x;} while (0);
-#else
-#define DEBUG(x)       do {} while (0);
-#endif
+#define DEBUG(x)       do { if (extended_error_logging) { x; } } while (0)
 
 #if defined(QL_DEBUG_LEVEL_1)
-#define DEBUG1(x)      do {x;} while (0);
+#define DEBUG1(x)      do {x;} while (0)
 #else
-#define DEBUG1(x)      do {} while (0);
+#define DEBUG1(x)      do {} while (0)
 #endif
 
-#if defined(QL_DEBUG_LEVEL_2)
-#define DEBUG2(x)       do {x;} while (0);
-#define DEBUG2_3(x)     do {x;} while (0);
-#define DEBUG2_3_11(x)  do {x;} while (0);
-#define DEBUG2_9_10(x)    do {x;} while (0);
-#define DEBUG2_11(x)    do {x;} while (0);
-#define DEBUG2_13(x)    do {x;} while (0);
-#else
-#define DEBUG2(x)      do {} while (0);
-#endif
+#define DEBUG2(x)      do { if (extended_error_logging) { x; } } while (0)
+#define DEBUG2_3(x)    do { if (extended_error_logging) { x; } } while (0)
+#define DEBUG2_3_11(x) do { if (extended_error_logging) { x; } } while (0)
+#define DEBUG2_9_10(x) do { if (extended_error_logging) { x; } } while (0)
+#define DEBUG2_11(x)   do { if (extended_error_logging) { x; } } while (0)
+#define DEBUG2_13(x)   do { if (extended_error_logging) { x; } } while (0)
 
 #if defined(QL_DEBUG_LEVEL_3)
-#define DEBUG3(x)      do {x;} while (0);
-#define DEBUG2_3(x)    do {x;} while (0);
-#define DEBUG2_3_11(x) do {x;} while (0);
-#define DEBUG3_11(x)   do {x;} while (0);
+#define DEBUG3(x)      do {x;} while (0)
+#define DEBUG3_11(x)   do {x;} while (0)
 #else
-#define DEBUG3(x)      do {} while (0);
-  #if !defined(QL_DEBUG_LEVEL_2)
-  #define DEBUG2_3(x)  do {} while (0);
-  #endif
+#define DEBUG3(x)      do {} while (0)
 #endif
 
 #if defined(QL_DEBUG_LEVEL_4)
-#define DEBUG4(x)      do {x;} while (0);
+#define DEBUG4(x)      do {x;} while (0)
 #else
-#define DEBUG4(x)      do {} while (0);
+#define DEBUG4(x)      do {} while (0)
 #endif
 
 #if defined(QL_DEBUG_LEVEL_5)
-#define DEBUG5(x)          do {x;} while (0);
+#define DEBUG5(x)          do {x;} while (0)
 #else
-#define DEBUG5(x)      do {} while (0);
+#define DEBUG5(x)      do {} while (0)
 #endif
 
 #if defined(QL_DEBUG_LEVEL_7)
-#define DEBUG7(x)          do {x;} while (0);
+#define DEBUG7(x)          do {x;} while (0)
 #else
-#define DEBUG7(x)         do {} while (0);
+#define DEBUG7(x)         do {} while (0)
 #endif
 
 #if defined(QL_DEBUG_LEVEL_9)
-#define DEBUG9(x)       do {x;} while (0);
-#define DEBUG9_10(x)    do {x;} while (0);
-#define DEBUG2_9_10(x) do {x;} while (0);
+#define DEBUG9(x)       do {x;} while (0)
+#define DEBUG9_10(x)    do {x;} while (0)
 #else
-#define DEBUG9(x)      do {} while (0);
+#define DEBUG9(x)      do {} while (0)
 #endif
 
 #if defined(QL_DEBUG_LEVEL_10)
-#define DEBUG10(x)      do {x;} while (0);
-#define DEBUG2_9_10(x) do {x;} while (0);
-#define DEBUG9_10(x)   do {x;} while (0);
+#define DEBUG10(x)      do {x;} while (0)
+#define DEBUG9_10(x)   do {x;} while (0)
 #else
-#define DEBUG10(x)     do {} while (0);
-  #if !defined(DEBUG2_9_10)
-  #define DEBUG2_9_10(x)       do {} while (0);
-  #endif
+#define DEBUG10(x)     do {} while (0)
   #if !defined(DEBUG9_10)
-  #define DEBUG9_10(x) do {} while (0);
+  #define DEBUG9_10(x) do {} while (0)
   #endif
 #endif
 
 #if defined(QL_DEBUG_LEVEL_11)
-#define DEBUG11(x)      do{x;} while(0);
-#if !defined(DEBUG2_11)
-#define DEBUG2_11(x)    do{x;} while(0);
-#endif
-#if !defined(DEBUG2_3_11)
-#define DEBUG2_3_11(x)  do{x;} while(0);
-#endif
+#define DEBUG11(x)      do{x;} while(0)
 #if !defined(DEBUG3_11)
-#define DEBUG3_11(x)    do{x;} while(0);
+#define DEBUG3_11(x)    do{x;} while(0)
 #endif
 #else
-#define DEBUG11(x)     do{} while(0);
-  #if !defined(QL_DEBUG_LEVEL_2)
-  #define DEBUG2_11(x) do{} while(0);
-    #if !defined(QL_DEBUG_LEVEL_3)
-    #define DEBUG2_3_11(x) do{} while(0);
-    #endif
-  #endif
+#define DEBUG11(x)     do{} while(0)
   #if !defined(QL_DEBUG_LEVEL_3)
-  #define DEBUG3_11(x) do{} while(0);
+  #define DEBUG3_11(x) do{} while(0)
   #endif
 #endif
 
 #if defined(QL_DEBUG_LEVEL_12)
-#define DEBUG12(x)      do {x;} while (0);
+#define DEBUG12(x)      do {x;} while (0)
 #else
-#define DEBUG12(x)     do {} while (0);
+#define DEBUG12(x)     do {} while (0)
 #endif
 
 #if defined(QL_DEBUG_LEVEL_13)
 #define DEBUG13(x)      do {x;} while (0)
-#if !defined(DEBUG2_13)
-#define DEBUG2_13(x)    do {x;} while(0)
-#endif
 #else
 #define DEBUG13(x)     do {} while (0)
-#if !defined(QL_DEBUG_LEVEL_2)
-#define DEBUG2_13(x)   do {} while(0)
-#endif
 #endif
 
 #if defined(QL_DEBUG_LEVEL_14)
 /*
  * Firmware Dump structure definition
  */
-#define FW_DUMP_SIZE_128K      0xBC000
-#define FW_DUMP_SIZE_512K      0x2FC000
-#define FW_DUMP_SIZE_1M                0x5FC000
 
 struct qla2300_fw_dump {
        uint16_t hccr;
@@ -224,8 +173,6 @@ struct qla2100_fw_dump {
        uint16_t risc_ram[0xf000];
 };
 
-#define FW_DUMP_SIZE_24XX      0x2B0000
-
 struct qla24xx_fw_dump {
        uint32_t host_status;
        uint32_t host_reg[32];
@@ -257,3 +204,39 @@ struct qla24xx_fw_dump {
        uint32_t code_ram[0x2000];
        uint32_t ext_mem[1];
 };
+
+#define EFT_NUM_BUFFERS                4
+#define EFT_BYTES_PER_BUFFER   0x4000
+#define EFT_SIZE               ((EFT_BYTES_PER_BUFFER) * (EFT_NUM_BUFFERS))
+
+struct qla2xxx_fw_dump {
+       uint8_t signature[4];
+       uint32_t version;
+
+       uint32_t fw_major_version;
+       uint32_t fw_minor_version;
+       uint32_t fw_subminor_version;
+       uint32_t fw_attributes;
+
+       uint32_t vendor;
+       uint32_t device;
+       uint32_t subsystem_vendor;
+       uint32_t subsystem_device;
+
+       uint32_t fixed_size;
+       uint32_t mem_size;
+       uint32_t req_q_size;
+       uint32_t rsp_q_size;
+
+       uint32_t eft_size;
+       uint32_t eft_addr_l;
+       uint32_t eft_addr_h;
+
+       uint32_t header_size;
+
+       union {
+               struct qla2100_fw_dump isp21;
+               struct qla2300_fw_dump isp23;
+               struct qla24xx_fw_dump isp24;
+       } isp;
+};
index d6f6579..bb0b5f5 100644 (file)
@@ -608,7 +608,9 @@ typedef struct {
 #define MBC_SERDES_PARAMS              0x10    /* Serdes Tx Parameters. */
 #define MBC_GET_IOCB_STATUS            0x12    /* Get IOCB status command. */
 #define MBC_GET_TIMEOUT_PARAMS         0x22    /* Get FW timeouts. */
+#define MBC_TRACE_CONTROL              0x27    /* Trace control command. */
 #define MBC_GEN_SYSTEM_ERROR           0x2a    /* Generate System Error. */
+#define MBC_READ_SFP                   0x31    /* Read SFP Data. */
 #define MBC_SET_TIMEOUT_PARAMS         0x32    /* Set FW timeouts. */
 #define MBC_MID_INITIALIZE_FIRMWARE    0x48    /* MID Initialize firmware. */
 #define MBC_MID_GET_VP_DATABASE                0x49    /* MID Get VP Database. */
@@ -618,6 +620,9 @@ typedef struct {
 #define MBC_GET_LINK_PRIV_STATS                0x6d    /* Get link & private data. */
 #define MBC_SET_VENDOR_ID              0x76    /* Set Vendor ID. */
 
+#define TC_ENABLE                      4
+#define TC_DISABLE                     5
+
 /* Firmware return data sizes */
 #define FCAL_MAP_SIZE  128
 
@@ -1997,7 +2002,6 @@ struct isp_operations {
                uint32_t);
 
        void (*fw_dump) (struct scsi_qla_host *, int);
-       void (*ascii_fw_dump) (struct scsi_qla_host *);
 
        int (*beacon_on) (struct scsi_qla_host *);
        int (*beacon_off) (struct scsi_qla_host *);
@@ -2041,6 +2045,7 @@ typedef struct scsi_qla_host {
                uint32_t        enable_led_scheme       :1;
                uint32_t        msi_enabled             :1;
                uint32_t        msix_enabled            :1;
+               uint32_t        disable_serdes          :1;
        } flags;
 
        atomic_t        loop_state;
@@ -2238,6 +2243,11 @@ typedef struct scsi_qla_host {
        struct sns_cmd_pkt      *sns_cmd;
        dma_addr_t              sns_cmd_dma;
 
+#define SFP_DEV_SIZE   256
+#define SFP_BLOCK_SIZE 64
+       void                    *sfp_data;
+       dma_addr_t              sfp_data_dma;
+
        struct task_struct      *dpc_thread;
        uint8_t dpc_active;                  /* DPC routine is active */
 
@@ -2303,11 +2313,12 @@ typedef struct scsi_qla_host {
        uint16_t        fw_seriallink_options24[4];
 
        /* Firmware dump information. */
-       void            *fw_dump;
+       struct qla2xxx_fw_dump *fw_dump;
+       uint32_t        fw_dump_len;
        int             fw_dumped;
        int             fw_dump_reading;
-       char            *fw_dump_buffer;
-       int             fw_dump_buffer_len;
+       dma_addr_t      eft_dma;
+       void            *eft;
 
        uint8_t         host_str[16];
        uint32_t        pci_attr;
index a8fc0ff..dd43541 100644 (file)
@@ -1,4 +1,4 @@
-#define QLA_MODEL_NAMES         0x4A
+#define QLA_MODEL_NAMES                0x57
 
 /*
  * Adapter model names and descriptions.
@@ -76,6 +76,19 @@ static char *qla2x00_model_name[QLA_MODEL_NAMES*2] = {
        "QLE2440",      "PCI-Express to 4Gb FC, Single Channel",        /* 0x145 */
        "QLE2464",      "PCI-Express to 4Gb FC, Quad Channel",          /* 0x146 */
        "QLA2440",      "PCI-X 2.0 to 4Gb FC, Single Channel",          /* 0x147 */
-       " ",            " ",                                            /* 0x148 */
+       "HP AE369A",    "PCI-X 2.0 to 4Gb FC, Dual Channel",            /* 0x148 */
        "QLA2340",      "Sun 133MHz PCI-X to 2Gb FC, Single Channel",   /* 0x149 */
+       " ",            " ",                                            /* 0x14a */
+       " ",            " ",                                            /* 0x14b */
+       "QMC2432M",     "IBM eServer BC 4Gb FC Expansion Card CFFE",    /* 0x14c */
+       "QMC2422M",     "IBM eServer BC 4Gb FC Expansion Card CFFX",    /* 0x14d */
+       "QLE220",       "Sun PCI-Express to 4Gb FC, Single Channel",    /* 0x14e */
+       " ",            " ",                                            /* 0x14f */
+       " ",            " ",                                            /* 0x150 */
+       " ",            " ",                                            /* 0x151 */
+       "QME2462",      "PCI-Express to 4Gb FC, Dual Channel Mezz HBA", /* 0x152 */
+       "QMH2462",      "PCI-Express to 4Gb FC, Dual Channel Mezz HBA", /* 0x153 */
+       " ",            " ",                                            /* 0x154 */
+       "QLE220",       "PCI-Express to 4Gb FC, Single Channel",        /* 0x155 */
+       "QLE220",       "PCI-Express to 4Gb FC, Single Channel",        /* 0x156 */
 };
index 3af4786..a0a722c 100644 (file)
@@ -141,7 +141,7 @@ struct nvram_24xx {
         * BIT 2  = Enable Memory Map BIOS
         * BIT 3  = Enable Selectable Boot
         * BIT 4  = Disable RISC code load
-        * BIT 5  =
+        * BIT 5  = Disable Serdes
         * BIT 6  =
         * BIT 7  =
         *
@@ -278,7 +278,7 @@ struct init_cb_24xx {
        uint16_t response_q_length;
        uint16_t request_q_length;
 
-       uint16_t link_down_timeout;             /* Milliseconds. */
+       uint16_t link_down_on_nos;              /* Milliseconds. */
 
        uint16_t prio_request_q_length;
 
index 164d53c..750aef1 100644 (file)
@@ -51,6 +51,8 @@ extern int qla2x00_abort_isp(scsi_qla_host_t *);
 extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *);
 extern void qla2x00_reg_remote_port(scsi_qla_host_t *, fc_port_t *);
 
+extern void qla2x00_alloc_fw_dump(scsi_qla_host_t *);
+
 /*
  * Global Data in qla_os.c source file.
  */
@@ -61,6 +63,8 @@ extern int qlport_down_retry;
 extern int ql2xplogiabsentdevice;
 extern int ql2xloginretrycount;
 extern int ql2xfdmienable;
+extern int ql2xallocfwdump;
+extern int extended_error_logging;
 
 extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *);
 
@@ -204,6 +208,12 @@ qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
 extern int
 qla2x00_stop_firmware(scsi_qla_host_t *);
 
+extern int
+qla2x00_trace_control(scsi_qla_host_t *, uint16_t, dma_addr_t, uint16_t);
+
+extern int
+qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t, uint16_t);
+
 /*
  * Global Function Prototypes in qla_isr.c source file.
  */
@@ -254,9 +264,6 @@ extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *,
 extern void qla2100_fw_dump(scsi_qla_host_t *, int);
 extern void qla2300_fw_dump(scsi_qla_host_t *, int);
 extern void qla24xx_fw_dump(scsi_qla_host_t *, int);
-extern void qla2100_ascii_fw_dump(scsi_qla_host_t *);
-extern void qla2300_ascii_fw_dump(scsi_qla_host_t *);
-extern void qla24xx_ascii_fw_dump(scsi_qla_host_t *);
 extern void qla2x00_dump_regs(scsi_qla_host_t *);
 extern void qla2x00_dump_buffer(uint8_t *, uint32_t);
 extern void qla2x00_print_scsi_cmd(struct scsi_cmnd *);
@@ -279,13 +286,6 @@ extern void *qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
 extern void *qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
 extern int qla2x00_fdmi_register(scsi_qla_host_t *);
 
-/*
- * Global Function Prototypes in qla_xioctl.c source file.
- */
-#define qla2x00_enqueue_aen(ha, cmd, mode)     do { } while (0)
-#define qla2x00_alloc_ioctl_mem(ha)            (0)
-#define qla2x00_free_ioctl_mem(ha)             do { } while (0)
-
 /*
  * Global Function Prototypes in qla_attr.c source file.
  */
index 3d4487e..ce74a60 100644 (file)
@@ -89,6 +89,17 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
 
        ha->isp_ops.nvram_config(ha);
 
+       if (ha->flags.disable_serdes) {
+               /* Mask HBA via NVRAM settings? */
+               qla_printk(KERN_INFO, ha, "Masking HBA WWPN "
+                   "%02x%02x%02x%02x%02x%02x%02x%02x (via NVRAM).\n",
+                   ha->port_name[0], ha->port_name[1],
+                   ha->port_name[2], ha->port_name[3],
+                   ha->port_name[4], ha->port_name[5],
+                   ha->port_name[6], ha->port_name[7]);
+               return QLA_FUNCTION_FAILED;
+       }
+
        qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n");
 
        retry = 10;
@@ -770,29 +781,104 @@ qla24xx_chip_diag(scsi_qla_host_t *ha)
        return rval;
 }
 
-static void
+void
 qla2x00_alloc_fw_dump(scsi_qla_host_t *ha)
 {
-       uint32_t dump_size = 0;
+       int rval;
+       uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size,
+           eft_size;
+       dma_addr_t eft_dma;
+       void *eft;
+
+       if (ha->fw_dump) {
+               qla_printk(KERN_WARNING, ha,
+                   "Firmware dump previously allocated.\n");
+               return;
+       }
 
        ha->fw_dumped = 0;
+       fixed_size = mem_size = eft_size = 0;
        if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
-               dump_size = sizeof(struct qla2100_fw_dump);
+               fixed_size = sizeof(struct qla2100_fw_dump);
        } else if (IS_QLA23XX(ha)) {
-               dump_size = sizeof(struct qla2300_fw_dump);
-               dump_size += (ha->fw_memory_size - 0x11000) * sizeof(uint16_t);
-        } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
-               dump_size = sizeof(struct qla24xx_fw_dump);
-               dump_size += (ha->fw_memory_size - 0x100000) * sizeof(uint32_t);
+               fixed_size = offsetof(struct qla2300_fw_dump, data_ram);
+               mem_size = (ha->fw_memory_size - 0x11000 + 1) *
+                   sizeof(uint16_t);
+       } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+               fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem);
+               mem_size = (ha->fw_memory_size - 0x100000 + 1) *
+                   sizeof(uint32_t);
+
+               /* Allocate memory for Extended Trace Buffer. */
+               eft = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &eft_dma,
+                   GFP_KERNEL);
+               if (!eft) {
+                       qla_printk(KERN_WARNING, ha, "Unable to allocate "
+                           "(%d KB) for EFT.\n", EFT_SIZE / 1024);
+                       goto cont_alloc;
+               }
+
+               rval = qla2x00_trace_control(ha, TC_ENABLE, eft_dma,
+                   EFT_NUM_BUFFERS);
+               if (rval) {
+                       qla_printk(KERN_WARNING, ha, "Unable to initialize "
+                           "EFT (%d).\n", rval);
+                       dma_free_coherent(&ha->pdev->dev, EFT_SIZE, eft,
+                           eft_dma);
+                       goto cont_alloc;
+               }
+
+               qla_printk(KERN_INFO, ha, "Allocated (%d KB) for EFT...\n",
+                   EFT_SIZE / 1024);
+
+               eft_size = EFT_SIZE;
+               memset(eft, 0, eft_size);
+               ha->eft_dma = eft_dma;
+               ha->eft = eft;
        }
+cont_alloc:
+       req_q_size = ha->request_q_length * sizeof(request_t);
+       rsp_q_size = ha->response_q_length * sizeof(response_t);
+
+       dump_size = offsetof(struct qla2xxx_fw_dump, isp);
+       dump_size += fixed_size + mem_size + req_q_size + rsp_q_size +
+           eft_size;
 
        ha->fw_dump = vmalloc(dump_size);
-       if (ha->fw_dump)
-               qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware "
-                   "dump...\n", dump_size / 1024);
-       else
+       if (!ha->fw_dump) {
                qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for "
                    "firmware dump!!!\n", dump_size / 1024);
+
+               if (ha->eft) {
+                       dma_free_coherent(&ha->pdev->dev, eft_size, ha->eft,
+                           ha->eft_dma);
+                       ha->eft = NULL;
+                       ha->eft_dma = 0;
+               }
+               return;
+       }
+
+       qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware dump...\n",
+           dump_size / 1024);
+
+       ha->fw_dump_len = dump_size;
+       ha->fw_dump->signature[0] = 'Q';
+       ha->fw_dump->signature[1] = 'L';
+       ha->fw_dump->signature[2] = 'G';
+       ha->fw_dump->signature[3] = 'C';
+       ha->fw_dump->version = __constant_htonl(1);
+
+       ha->fw_dump->fixed_size = htonl(fixed_size);
+       ha->fw_dump->mem_size = htonl(mem_size);
+       ha->fw_dump->req_q_size = htonl(req_q_size);
+       ha->fw_dump->rsp_q_size = htonl(rsp_q_size);
+
+       ha->fw_dump->eft_size = htonl(eft_size);
+       ha->fw_dump->eft_addr_l = htonl(LSD(ha->eft_dma));
+       ha->fw_dump->eft_addr_h = htonl(MSD(ha->eft_dma));
+
+       ha->fw_dump->header_size =
+           htonl(offsetof(struct qla2xxx_fw_dump, isp));
 }
 
 /**
@@ -810,8 +896,6 @@ qla2x00_resize_request_q(scsi_qla_host_t *ha)
        dma_addr_t request_dma;
        request_t *request_ring;
 
-       qla2x00_alloc_fw_dump(ha);
-
        /* Valid only on recent ISPs. */
        if (IS_QLA2100(ha) || IS_QLA2200(ha))
                return;
@@ -883,6 +967,9 @@ qla2x00_setup_chip(scsi_qla_host_t *ha)
                                    &ha->fw_subminor_version,
                                    &ha->fw_attributes, &ha->fw_memory_size);
                                qla2x00_resize_request_q(ha);
+
+                               if (ql2xallocfwdump)
+                                       qla2x00_alloc_fw_dump(ha);
                        }
                } else {
                        DEBUG2(printk(KERN_INFO
@@ -1186,8 +1273,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
                        rval = QLA_FUNCTION_FAILED;
 
                        if (atomic_read(&ha->loop_down_timer) &&
-                           (fw_state >= FSTATE_LOSS_OF_SYNC ||
-                               fw_state == FSTATE_WAIT_AL_PA)) {
+                           fw_state != FSTATE_READY) {
                                /* Loop down. Timeout on min_wait for states
                                 * other than Wait for Login.
                                 */
@@ -1555,6 +1641,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
        /*
         * Set host adapter parameters.
         */
+       if (nv->host_p[0] & BIT_7)
+               extended_error_logging = 1;
        ha->flags.disable_risc_code_load = ((nv->host_p[0] & BIT_4) ? 1 : 0);
        /* Always load RISC code on non ISP2[12]00 chips. */
        if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
@@ -1563,6 +1651,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
        ha->flags.enable_lip_full_login = ((nv->host_p[1] & BIT_2) ? 1 : 0);
        ha->flags.enable_target_reset = ((nv->host_p[1] & BIT_3) ? 1 : 0);
        ha->flags.enable_led_scheme = (nv->special_options[1] & BIT_4) ? 1 : 0;
+       ha->flags.disable_serdes = 0;
 
        ha->operating_mode =
            (icb->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) >> 4;
@@ -3048,14 +3137,14 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
                                        ha->isp_abort_cnt--;
                                        DEBUG(printk("qla%ld: ISP abort - "
                                            "retry remaining %d\n",
-                                           ha->host_no, ha->isp_abort_cnt);)
+                                           ha->host_no, ha->isp_abort_cnt));
                                        status = 1;
                                }
                        } else {
                                ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT;
                                DEBUG(printk("qla2x00(%ld): ISP error recovery "
                                    "- retrying (%d) more times\n",
-                                   ha->host_no, ha->isp_abort_cnt);)
+                                   ha->host_no, ha->isp_abort_cnt));
                                set_bit(ISP_ABORT_RETRY, &ha->dpc_flags);
                                status = 1;
                        }
@@ -3069,7 +3158,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
        } else {
                DEBUG(printk(KERN_INFO
                                "qla2x00_abort_isp(%ld): exiting.\n",
-                               ha->host_no);)
+                               ha->host_no));
        }
 
        return(status);
@@ -3145,7 +3234,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha)
                clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
                if (!(status = qla2x00_fw_ready(ha))) {
                        DEBUG(printk("%s(): Start configure loop, "
-                           "status = %d\n", __func__, status);)
+                           "status = %d\n", __func__, status));
 
                        /* Issue a marker after FW becomes ready. */
                        qla2x00_marker(ha, 0, 0, MK_SYNC_ALL);
@@ -3169,7 +3258,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha)
 
                DEBUG(printk("%s(): Configure loop done, status = 0x%x\n",
                                __func__,
-                               status);)
+                               status));
        }
        return (status);
 }
@@ -3289,7 +3378,6 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
                nv->node_name[6] = 0x55;
                nv->node_name[7] = 0x86;
                nv->login_retry_count = __constant_cpu_to_le16(8);
-               nv->link_down_timeout = __constant_cpu_to_le16(200);
                nv->interrupt_delay_timer = __constant_cpu_to_le16(0);
                nv->login_timeout = __constant_cpu_to_le16(0);
                nv->firmware_options_1 =
@@ -3318,7 +3406,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
                *dptr1++ = *dptr2++;
 
        icb->login_retry_count = nv->login_retry_count;
-       icb->link_down_timeout = nv->link_down_timeout;
+       icb->link_down_on_nos = nv->link_down_on_nos;
 
        /* Copy 2nd segment. */
        dptr1 = (uint8_t *)&icb->interrupt_delay_timer;
@@ -3373,6 +3461,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
        ha->flags.enable_lip_full_login = 1;
        ha->flags.enable_target_reset = 1;
        ha->flags.enable_led_scheme = 0;
+       ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0;
 
        ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) &
            (BIT_6 | BIT_5 | BIT_4)) >> 4;
index b28ac0a..795bf15 100644 (file)
@@ -395,10 +395,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
 
                ha->flags.management_server_logged_in = 0;
-
-               /* Update AEN queue. */
-               qla2x00_enqueue_aen(ha, MBA_LIP_OCCURRED, NULL);
-
                break;
 
        case MBA_LOOP_UP:               /* Loop Up Event */
@@ -418,9 +414,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                    link_speed);
 
                ha->flags.management_server_logged_in = 0;
-
-               /* Update AEN queue. */
-               qla2x00_enqueue_aen(ha, MBA_LOOP_UP, NULL);
                break;
 
        case MBA_LOOP_DOWN:             /* Loop Down Event */
@@ -439,9 +432,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                ha->link_data_rate = LDR_UNKNOWN;
                if (ql2xfdmienable)
                        set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
-
-               /* Update AEN queue. */
-               qla2x00_enqueue_aen(ha, MBA_LOOP_DOWN, NULL);
                break;
 
        case MBA_LIP_RESET:             /* LIP reset occurred */
@@ -460,10 +450,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
 
                ha->operating_mode = LOOP;
                ha->flags.management_server_logged_in = 0;
-
-               /* Update AEN queue. */
-               qla2x00_enqueue_aen(ha, MBA_LIP_RESET, NULL);
-
                break;
 
        case MBA_POINT_TO_POINT:        /* Point-to-Point */
@@ -545,9 +531,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
 
                set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
                set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
-
-               /* Update AEN queue. */
-               qla2x00_enqueue_aen(ha, MBA_PORT_UPDATE, NULL);
                break;
 
        case MBA_RSCN_UPDATE:           /* State Change Registration */
@@ -584,9 +567,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
 
                set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
                set_bit(RSCN_UPDATE, &ha->dpc_flags);
-
-               /* Update AEN queue. */
-               qla2x00_enqueue_aen(ha, MBA_RSCN_UPDATE, &mb[0]);
                break;
 
        /* case MBA_RIO_RESPONSE: */
@@ -1452,8 +1432,8 @@ qla24xx_ms_entry(scsi_qla_host_t *ha, struct ct_entry_24xx *pkt)
        DEBUG3(printk("%s(%ld): pkt=%p pkthandle=%d.\n",
            __func__, ha->host_no, pkt, pkt->handle));
 
-       DEBUG9(printk("%s: ct pkt dump:\n", __func__);)
-       DEBUG9(qla2x00_dump_buffer((void *)pkt, sizeof(struct ct_entry_24xx));)
+       DEBUG9(printk("%s: ct pkt dump:\n", __func__));
+       DEBUG9(qla2x00_dump_buffer((void *)pkt, sizeof(struct ct_entry_24xx)));
 
        /* Validate handle. */
        if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
index d6cb3bd..879f281 100644 (file)
@@ -13,13 +13,13 @@ qla2x00_mbx_sem_timeout(unsigned long data)
 {
        struct semaphore        *sem_ptr = (struct semaphore *)data;
 
-       DEBUG11(printk("qla2x00_sem_timeout: entered.\n");)
+       DEBUG11(printk("qla2x00_sem_timeout: entered.\n"));
 
        if (sem_ptr != NULL) {
                up(sem_ptr);
        }
 
-       DEBUG11(printk("qla2x00_mbx_sem_timeout: exiting.\n");)
+       DEBUG11(printk("qla2x00_mbx_sem_timeout: exiting.\n"));
 }
 
 /*
@@ -61,7 +61,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
        rval = QLA_SUCCESS;
        abort_active = test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
 
        /*
         * Wait for active mailbox commands to finish by waiting at most tov
@@ -72,7 +72,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
                if (qla2x00_down_timeout(&ha->mbx_cmd_sem, mcp->tov * HZ)) {
                        /* Timeout occurred. Return error. */
                        DEBUG2_3_11(printk("%s(%ld): cmd access timeout. "
-                           "Exiting.\n", __func__, ha->host_no);)
+                           "Exiting.\n", __func__, ha->host_no));
                        return QLA_FUNCTION_TIMEOUT;
                }
        }
@@ -86,7 +86,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
                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]);)
+           ha->host_no, mcp->mb[0]));
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
 
@@ -131,14 +131,14 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
 
        /* Unlock mbx registers and wait for interrupt */
        DEBUG11(printk("%s(%ld): going to unlock irq & waiting for interrupt. "
-           "jiffies=%lx.\n", __func__, ha->host_no, jiffies);)
+           "jiffies=%lx.\n", __func__, ha->host_no, jiffies));
 
        /* Wait for mbx cmd completion until timeout */
 
        if (!abort_active && io_lock_on) {
                /* sleep on completion semaphore */
                DEBUG11(printk("%s(%ld): INTERRUPT MODE. Initializing timer.\n",
-                   __func__, ha->host_no);)
+                   __func__, ha->host_no));
 
                init_timer(&tmp_intr_timer);
                tmp_intr_timer.data = (unsigned long)&ha->mbx_intr_sem;
@@ -147,11 +147,11 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
                    (void (*)(unsigned long))qla2x00_mbx_sem_timeout;
 
                DEBUG11(printk("%s(%ld): Adding timer.\n", __func__,
-                   ha->host_no);)
+                   ha->host_no));
                add_timer(&tmp_intr_timer);
 
                DEBUG11(printk("%s(%ld): going to unlock & sleep. "
-                   "time=0x%lx.\n", __func__, ha->host_no, jiffies);)
+                   "time=0x%lx.\n", __func__, ha->host_no, jiffies));
 
                set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
 
@@ -170,14 +170,14 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
                down(&ha->mbx_intr_sem);
 
                DEBUG11(printk("%s(%ld): waking up. time=0x%lx\n", __func__,
-                   ha->host_no, jiffies);)
+                   ha->host_no, jiffies));
                clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
 
                /* delete the timer */
                del_timer(&tmp_intr_timer);
        } else {
                DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__,
-                   ha->host_no, command);)
+                   ha->host_no, command));
 
                if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
                        WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT);
@@ -209,7 +209,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
                uint16_t *iptr2;
 
                DEBUG3_11(printk("%s(%ld): cmd %x completed.\n", __func__,
-                   ha->host_no, command);)
+                   ha->host_no, command));
 
                /* Got interrupt. Clear the flag. */
                ha->flags.mbox_int = 0;
@@ -266,7 +266,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
 
        if (!abort_active) {
                DEBUG11(printk("%s(%ld): checking for additional resp "
-                   "interrupt.\n", __func__, ha->host_no);)
+                   "interrupt.\n", __func__, ha->host_no));
 
                /* polling mode for non isp_abort commands. */
                qla2x00_poll(ha);
@@ -277,9 +277,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
                if (!io_lock_on || (mcp->flags & IOCTL_CMD)) {
                        /* not in dpc. schedule it for dpc to take over. */
                        DEBUG(printk("%s(%ld): timeout schedule "
-                           "isp_abort_needed.\n", __func__, ha->host_no);)
+                           "isp_abort_needed.\n", __func__, ha->host_no));
                        DEBUG2_3_11(printk("%s(%ld): timeout schedule "
-                           "isp_abort_needed.\n", __func__, ha->host_no);)
+                           "isp_abort_needed.\n", __func__, ha->host_no));
                        qla_printk(KERN_WARNING, ha,
                            "Mailbox command timeout occured. Scheduling ISP "
                            "abort.\n");
@@ -288,9 +288,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
                } else if (!abort_active) {
                        /* call abort directly since we are in the DPC thread */
                        DEBUG(printk("%s(%ld): timeout calling abort_isp\n",
-                           __func__, ha->host_no);)
+                           __func__, ha->host_no));
                        DEBUG2_3_11(printk("%s(%ld): timeout calling "
-                           "abort_isp\n", __func__, ha->host_no);)
+                           "abort_isp\n", __func__, ha->host_no));
                        qla_printk(KERN_WARNING, ha,
                            "Mailbox command timeout occured. Issuing ISP "
                            "abort.\n");
@@ -303,9 +303,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
                        }
                        clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
                        DEBUG(printk("%s(%ld): finished abort_isp\n", __func__,
-                           ha->host_no);)
+                           ha->host_no));
                        DEBUG2_3_11(printk("%s(%ld): finished abort_isp\n",
-                           __func__, ha->host_no);)
+                           __func__, ha->host_no));
                }
        }
 
@@ -316,9 +316,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
        if (rval) {
                DEBUG2_3_11(printk("%s(%ld): **** FAILED. mbx0=%x, mbx1=%x, "
                    "mbx2=%x, cmd=%x ****\n", __func__, ha->host_no,
-                   mcp->mb[0], mcp->mb[1], mcp->mb[2], command);)
+                   mcp->mb[0], mcp->mb[1], mcp->mb[2], command));
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);)
+               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
        }
 
        return rval;
@@ -394,7 +394,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
 
        mcp->mb[0] = MBC_EXECUTE_FIRMWARE;
        mcp->out_mb = MBX_0;
@@ -424,10 +424,10 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr)
        } else {
                if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
                        DEBUG11(printk("%s(%ld): done exchanges=%x.\n",
-                           __func__, ha->host_no, mcp->mb[1]);)
+                           __func__, ha->host_no, mcp->mb[1]));
                } else {
                        DEBUG11(printk("%s(%ld): done.\n", __func__,
-                           ha->host_no);)
+                           ha->host_no));
                }
        }
 
@@ -611,7 +611,7 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *ha)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("qla2x00_mbx_reg_test(%ld): entered.\n", ha->host_no);)
+       DEBUG11(printk("qla2x00_mbx_reg_test(%ld): entered.\n", ha->host_no));
 
        mcp->mb[0] = MBC_MAILBOX_REGISTER_TEST;
        mcp->mb[1] = 0xAAAA;
@@ -639,11 +639,11 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *ha)
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
                DEBUG2_3_11(printk("qla2x00_mbx_reg_test(%ld): failed=%x.\n",
-                   ha->host_no, rval);)
+                   ha->host_no, rval));
        } else {
                /*EMPTY*/
                DEBUG11(printk("qla2x00_mbx_reg_test(%ld): done.\n",
-                   ha->host_no);)
+                   ha->host_no));
        }
 
        return rval;
@@ -671,7 +671,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
 
        mcp->mb[0] = MBC_VERIFY_CHECKSUM;
        mcp->out_mb = MBX_0;
@@ -694,9 +694,9 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
        if (rval != QLA_SUCCESS) {
                DEBUG2_3_11(printk("%s(%ld): failed=%x chk sum=%x.\n", __func__,
                    ha->host_no, rval, (IS_QLA24XX(ha) || IS_QLA54XX(ha) ?
-                   (mcp->mb[2] << 16) | mcp->mb[1]: mcp->mb[1]));)
+                   (mcp->mb[2] << 16) | mcp->mb[1]: mcp->mb[1])));
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);)
+               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
        }
 
        return rval;
@@ -743,9 +743,9 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void*  buffer, dma_addr_t phys_addr,
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
                DEBUG(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x\n",
-                   ha->host_no, rval);)
+                   ha->host_no, rval));
                DEBUG2(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x\n",
-                   ha->host_no, rval);)
+                   ha->host_no, rval));
        } else {
                sts_entry_t *sts_entry = (sts_entry_t *) buffer;
 
@@ -781,7 +781,7 @@ qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp)
        mbx_cmd_t       mc;
        mbx_cmd_t       *mcp = &mc;
 
-       DEBUG11(printk("qla2x00_abort_command(%ld): entered.\n", ha->host_no);)
+       DEBUG11(printk("qla2x00_abort_command(%ld): entered.\n", ha->host_no));
 
        fcport = sp->fcport;
 
@@ -813,11 +813,11 @@ qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp)
 
        if (rval != QLA_SUCCESS) {
                DEBUG2_3_11(printk("qla2x00_abort_command(%ld): failed=%x.\n",
-                   ha->host_no, rval);)
+                   ha->host_no, rval));
        } else {
                sp->flags |= SRB_ABORT_PENDING;
                DEBUG11(printk("qla2x00_abort_command(%ld): done.\n",
-                   ha->host_no);)
+                   ha->host_no));
        }
 
        return rval;
@@ -848,7 +848,7 @@ qla2x00_abort_target(fc_port_t *fcport)
        if (fcport == NULL)
                return 0;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no);)
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
 
        ha = fcport->ha;
        mcp->mb[0] = MBC_ABORT_TARGET;
@@ -872,11 +872,11 @@ qla2x00_abort_target(fc_port_t *fcport)
 
        if (rval != QLA_SUCCESS) {
                DEBUG2_3_11(printk("qla2x00_abort_target(%ld): failed=%x.\n",
-                   ha->host_no, rval);)
+                   ha->host_no, rval));
        } else {
                /*EMPTY*/
                DEBUG11(printk("qla2x00_abort_target(%ld): done.\n",
-                   ha->host_no);)
+                   ha->host_no));
        }
 
        return rval;
@@ -912,7 +912,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa,
        mbx_cmd_t *mcp = &mc;
 
        DEBUG11(printk("qla2x00_get_adapter_id(%ld): entered.\n",
-           ha->host_no);)
+           ha->host_no));
 
        mcp->mb[0] = MBC_GET_ADAPTER_LOOP_ID;
        mcp->out_mb = MBX_0;
@@ -933,11 +933,11 @@ qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa,
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
                DEBUG2_3_11(printk("qla2x00_get_adapter_id(%ld): failed=%x.\n",
-                   ha->host_no, rval);)
+                   ha->host_no, rval));
        } else {
                /*EMPTY*/
                DEBUG11(printk("qla2x00_get_adapter_id(%ld): done.\n",
-                   ha->host_no);)
+                   ha->host_no));
        }
 
        return rval;
@@ -968,7 +968,7 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *ha, uint8_t *retry_cnt, uint8_t *tov,
        mbx_cmd_t *mcp = &mc;
 
        DEBUG11(printk("qla2x00_get_retry_cnt(%ld): entered.\n",
-                       ha->host_no);)
+                       ha->host_no));
 
        mcp->mb[0] = MBC_GET_RETRY_COUNT;
        mcp->out_mb = MBX_0;
@@ -980,7 +980,7 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *ha, uint8_t *retry_cnt, uint8_t *tov,
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
                DEBUG2_3_11(printk("qla2x00_get_retry_cnt(%ld): failed = %x.\n",
-                   ha->host_no, mcp->mb[0]);)
+                   ha->host_no, mcp->mb[0]));
        } else {
                /* Convert returned data and check our values. */
                *r_a_tov = mcp->mb[3] / 2;
@@ -992,7 +992,7 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *ha, uint8_t *retry_cnt, uint8_t *tov,
                }
 
                DEBUG11(printk("qla2x00_get_retry_cnt(%ld): done. mb3=%d "
-                   "ratov=%d.\n", ha->host_no, mcp->mb[3], ratov);)
+                   "ratov=%d.\n", ha->host_no, mcp->mb[3], ratov));
        }
 
        return rval;
@@ -1023,7 +1023,7 @@ qla2x00_init_firmware(scsi_qla_host_t *ha, uint16_t size)
        mbx_cmd_t *mcp = &mc;
 
        DEBUG11(printk("qla2x00_init_firmware(%ld): entered.\n",
-           ha->host_no);)
+           ha->host_no));
 
        mcp->mb[0] = MBC_INITIALIZE_FIRMWARE;
        mcp->mb[2] = MSW(ha->init_cb_dma);
@@ -1043,11 +1043,11 @@ qla2x00_init_firmware(scsi_qla_host_t *ha, uint16_t size)
                /*EMPTY*/
                DEBUG2_3_11(printk("qla2x00_init_firmware(%ld): failed=%x "
                    "mb0=%x.\n",
-                   ha->host_no, rval, mcp->mb[0]);)
+                   ha->host_no, rval, mcp->mb[0]));
        } else {
                /*EMPTY*/
                DEBUG11(printk("qla2x00_init_firmware(%ld): done.\n",
-                   ha->host_no);)
+                   ha->host_no));
        }
 
        return rval;
@@ -1079,7 +1079,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt)
        struct port_database_24xx *pd24;
        dma_addr_t pd_dma;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
 
        pd24 = NULL;
        pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
@@ -1220,7 +1220,7 @@ qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *dptr)
        mbx_cmd_t *mcp = &mc;
 
        DEBUG11(printk("qla2x00_get_firmware_state(%ld): entered.\n",
-           ha->host_no);)
+           ha->host_no));
 
        mcp->mb[0] = MBC_GET_FIRMWARE_STATE;
        mcp->out_mb = MBX_0;
@@ -1235,11 +1235,11 @@ qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *dptr)
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
                DEBUG2_3_11(printk("qla2x00_get_firmware_state(%ld): "
-                   "failed=%x.\n", ha->host_no, rval);)
+                   "failed=%x.\n", ha->host_no, rval));
        } else {
                /*EMPTY*/
                DEBUG11(printk("qla2x00_get_firmware_state(%ld): done.\n",
-                   ha->host_no);)
+                   ha->host_no));
        }
 
        return rval;
@@ -1272,7 +1272,7 @@ qla2x00_get_port_name(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t *name,
        mbx_cmd_t *mcp = &mc;
 
        DEBUG11(printk("qla2x00_get_port_name(%ld): entered.\n",
-           ha->host_no);)
+           ha->host_no));
 
        mcp->mb[0] = MBC_GET_PORT_NAME;
        mcp->out_mb = MBX_1|MBX_0;
@@ -1292,7 +1292,7 @@ qla2x00_get_port_name(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t *name,
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
                DEBUG2_3_11(printk("qla2x00_get_port_name(%ld): failed=%x.\n",
-                   ha->host_no, rval);)
+                   ha->host_no, rval));
        } else {
                if (name != NULL) {
                        /* This function returns name in big endian. */
@@ -1307,7 +1307,7 @@ qla2x00_get_port_name(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t *name,
                }
 
                DEBUG11(printk("qla2x00_get_port_name(%ld): done.\n",
-                   ha->host_no);)
+                   ha->host_no));
        }
 
        return rval;
@@ -1335,7 +1335,7 @@ qla2x00_lip_reset(scsi_qla_host_t *ha)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
 
        if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
                mcp->mb[0] = MBC_LIP_FULL_LOGIN;
@@ -1364,10 +1364,10 @@ qla2x00_lip_reset(scsi_qla_host_t *ha)
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
                DEBUG2_3_11(printk("%s(%ld): failed=%x.\n",
-                   __func__, ha->host_no, rval);)
+                   __func__, ha->host_no, rval));
        } else {
                /*EMPTY*/
-               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);)
+               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
        }
 
        return rval;
@@ -1400,10 +1400,10 @@ qla2x00_send_sns(scsi_qla_host_t *ha, dma_addr_t sns_phys_address,
        mbx_cmd_t *mcp = &mc;
 
        DEBUG11(printk("qla2x00_send_sns(%ld): entered.\n",
-           ha->host_no);)
+           ha->host_no));
 
        DEBUG11(printk("qla2x00_send_sns: retry cnt=%d ratov=%d total "
-           "tov=%d.\n", ha->retry_count, ha->login_timeout, mcp->tov);)
+           "tov=%d.\n", ha->retry_count, ha->login_timeout, mcp->tov));
 
        mcp->mb[0] = MBC_SEND_SNS_COMMAND;
        mcp->mb[1] = cmd_size;
@@ -1421,12 +1421,12 @@ qla2x00_send_sns(scsi_qla_host_t *ha, dma_addr_t sns_phys_address,
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
                DEBUG(printk("qla2x00_send_sns(%ld): failed=%x mb[0]=%x "
-                   "mb[1]=%x.\n", ha->host_no, rval, mcp->mb[0], mcp->mb[1]);)
+                   "mb[1]=%x.\n", ha->host_no, rval, mcp->mb[0], mcp->mb[1]));
                DEBUG2_3_11(printk("qla2x00_send_sns(%ld): failed=%x mb[0]=%x "
-                   "mb[1]=%x.\n", ha->host_no, rval, mcp->mb[0], mcp->mb[1]);)
+                   "mb[1]=%x.\n", ha->host_no, rval, mcp->mb[0], mcp->mb[1]));
        } else {
                /*EMPTY*/
-               DEBUG11(printk("qla2x00_send_sns(%ld): done.\n", ha->host_no);)
+               DEBUG11(printk("qla2x00_send_sns(%ld): done.\n", ha->host_no));
        }
 
        return rval;
@@ -1442,7 +1442,7 @@ qla24xx_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
        dma_addr_t      lg_dma;
        uint32_t        iop[2];
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
 
        lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);
        if (lg == NULL) {
@@ -1458,13 +1458,15 @@ qla24xx_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
        lg->control_flags = __constant_cpu_to_le16(LCF_COMMAND_PLOGI);
        if (opt & BIT_0)
                lg->control_flags |= __constant_cpu_to_le16(LCF_COND_PLOGI);
+       if (opt & BIT_1)
+               lg->control_flags |= __constant_cpu_to_le16(LCF_SKIP_PRLI);
        lg->port_id[0] = al_pa;
        lg->port_id[1] = area;
        lg->port_id[2] = domain;
        rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0);
        if (rval != QLA_SUCCESS) {
                DEBUG2_3_11(printk("%s(%ld): failed to issue Login IOCB "
-                   "(%x).\n", __func__, ha->host_no, rval);)
+                   "(%x).\n", __func__, ha->host_no, rval));
        } else if (lg->entry_status != 0) {
                DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
                    "-- error status (%x).\n", __func__, ha->host_no,
@@ -1505,7 +1507,7 @@ qla24xx_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
                        break;
                }
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);)
+               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
 
                iop[0] = le32_to_cpu(lg->io_parameter[0]);
 
@@ -1559,7 +1561,7 @@ qla2x00_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       DEBUG11(printk("qla2x00_login_fabric(%ld): entered.\n", ha->host_no);)
+       DEBUG11(printk("qla2x00_login_fabric(%ld): entered.\n", ha->host_no));
 
        mcp->mb[0] = MBC_LOGIN_FABRIC_PORT;
        mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
@@ -1604,11 +1606,11 @@ qla2x00_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
                /*EMPTY*/
                DEBUG2_3_11(printk("qla2x00_login_fabric(%ld): failed=%x "
                    "mb[0]=%x mb[1]=%x mb[2]=%x.\n", ha->host_no, rval,
-                   mcp->mb[0], mcp->mb[1], mcp->mb[2]);)
+                   mcp->mb[0], mcp->mb[1], mcp->mb[2]));
        } else {
                /*EMPTY*/
                DEBUG11(printk("qla2x00_login_fabric(%ld): done.\n",
-                   ha->host_no);)
+                   ha->host_no));
        }
 
        return rval;
@@ -1643,7 +1645,7 @@ qla2x00_login_local_device(scsi_qla_host_t *ha, fc_port_t *fcport,
                    fcport->d_id.b.domain, fcport->d_id.b.area,
                    fcport->d_id.b.al_pa, mb_ret, opt);
 
-       DEBUG3(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
+       DEBUG3(printk("%s(%ld): entered.\n", __func__, ha->host_no));
 
        mcp->mb[0] = MBC_LOGIN_LOOP_PORT;
        if (HAS_EXTENDED_IDS(ha))
@@ -1677,13 +1679,13 @@ qla2x00_login_local_device(scsi_qla_host_t *ha, fc_port_t *fcport,
 
                DEBUG(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x "
                    "mb[6]=%x mb[7]=%x.\n", __func__, ha->host_no, rval,
-                   mcp->mb[0], mcp->mb[1], mcp->mb[6], mcp->mb[7]);)
+                   mcp->mb[0], mcp->mb[1], mcp->mb[6], mcp->mb[7]));
                DEBUG2_3(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x "
                    "mb[6]=%x mb[7]=%x.\n", __func__, ha->host_no, rval,
-                   mcp->mb[0], mcp->mb[1], mcp->mb[6], mcp->mb[7]);)
+                   mcp->mb[0], mcp->mb[1], mcp->mb[6], mcp->mb[7]));
        } else {
                /*EMPTY*/
-               DEBUG3(printk("%s(%ld): done.\n", __func__, ha->host_no);)
+               DEBUG3(printk("%s(%ld): done.\n", __func__, ha->host_no));
        }
 
        return (rval);
@@ -1697,7 +1699,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
        struct logio_entry_24xx *lg;
        dma_addr_t      lg_dma;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
 
        lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);
        if (lg == NULL) {
@@ -1718,7 +1720,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
        rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0);
        if (rval != QLA_SUCCESS) {
                DEBUG2_3_11(printk("%s(%ld): failed to issue Logout IOCB "
-                   "(%x).\n", __func__, ha->host_no, rval);)
+                   "(%x).\n", __func__, ha->host_no, rval));
        } else if (lg->entry_status != 0) {
                DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
                    "-- error status (%x).\n", __func__, ha->host_no,
@@ -1729,10 +1731,10 @@ qla24xx_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
                    "-- completion status (%x)  ioparam=%x/%x.\n", __func__,
                    ha->host_no, le16_to_cpu(lg->comp_status),
                    le32_to_cpu(lg->io_parameter[0]),
-                   le32_to_cpu(lg->io_parameter[1]));)
+                   le32_to_cpu(lg->io_parameter[1])));
        } else {
                /*EMPTY*/
-               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);)
+               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
        }
 
        dma_pool_free(ha->s_dma_pool, lg, lg_dma);
@@ -1765,7 +1767,7 @@ qla2x00_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
        mbx_cmd_t *mcp = &mc;
 
        DEBUG11(printk("qla2x00_fabric_logout(%ld): entered.\n",
-           ha->host_no);)
+           ha->host_no));
 
        mcp->mb[0] = MBC_LOGOUT_FABRIC_PORT;
        mcp->out_mb = MBX_1|MBX_0;
@@ -1785,11 +1787,11 @@ qla2x00_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
                DEBUG2_3_11(printk("qla2x00_fabric_logout(%ld): failed=%x "
-                   "mbx1=%x.\n", ha->host_no, rval, mcp->mb[1]);)
+                   "mbx1=%x.\n", ha->host_no, rval, mcp->mb[1]));
        } else {
                /*EMPTY*/
                DEBUG11(printk("qla2x00_fabric_logout(%ld): done.\n",
-                   ha->host_no);)
+                   ha->host_no));
        }
 
        return rval;
@@ -1818,7 +1820,7 @@ qla2x00_full_login_lip(scsi_qla_host_t *ha)
        mbx_cmd_t *mcp = &mc;
 
        DEBUG11(printk("qla2x00_full_login_lip(%ld): entered.\n",
-           ha->host_no);)
+           ha->host_no));
 
        mcp->mb[0] = MBC_LIP_FULL_LOGIN;
        mcp->mb[1] = 0;
@@ -1833,11 +1835,11 @@ qla2x00_full_login_lip(scsi_qla_host_t *ha)
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
                DEBUG2_3_11(printk("qla2x00_full_login_lip(%ld): failed=%x.\n",
-                   ha->host_no, rval);)
+                   ha->host_no, rval));
        } else {
                /*EMPTY*/
                DEBUG11(printk("qla2x00_full_login_lip(%ld): done.\n",
-                   ha->host_no);)
+                   ha->host_no));
        }
 
        return rval;
@@ -1864,7 +1866,7 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma,
        mbx_cmd_t *mcp = &mc;
 
        DEBUG11(printk("qla2x00_get_id_list(%ld): entered.\n",
-           ha->host_no);)
+           ha->host_no));
 
        if (id_list == NULL)
                return QLA_FUNCTION_FAILED;
@@ -1893,11 +1895,11 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma,
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
                DEBUG2_3_11(printk("qla2x00_get_id_list(%ld): failed=%x.\n",
-                   ha->host_no, rval);)
+                   ha->host_no, rval));
        } else {
                *entries = mcp->mb[1];
                DEBUG11(printk("qla2x00_get_id_list(%ld): done.\n",
-                   ha->host_no);)
+                   ha->host_no));
        }
 
        return rval;
@@ -1936,7 +1938,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt,
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
                DEBUG2_3_11(printk("%s(%ld): failed = %x.\n", __func__,
-                   ha->host_no, mcp->mb[0]);)
+                   ha->host_no, mcp->mb[0]));
        } else {
                DEBUG11(printk("%s(%ld): done. mb1=%x mb2=%x mb3=%x mb6=%x "
                    "mb7=%x mb10=%x.\n", __func__, ha->host_no,
@@ -2045,7 +2047,7 @@ qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id,
        link_stat_t *stat_buf;
        dma_addr_t stat_buf_dma;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
 
        stat_buf = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &stat_buf_dma);
        if (stat_buf == NULL) {
@@ -2083,7 +2085,7 @@ qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id,
        if (rval == QLA_SUCCESS) {
                if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
                        DEBUG2_3_11(printk("%s(%ld): cmd failed. mbx0=%x.\n",
-                           __func__, ha->host_no, mcp->mb[0]);)
+                           __func__, ha->host_no, mcp->mb[0]));
                        status[0] = mcp->mb[0];
                        rval = BIT_1;
                } else {
@@ -2108,12 +2110,12 @@ qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id,
                            stat_buf->loss_sync_cnt, stat_buf->loss_sig_cnt,
                            stat_buf->prim_seq_err_cnt,
                            stat_buf->inval_xmit_word_cnt,
-                           stat_buf->inval_crc_cnt);)
+                           stat_buf->inval_crc_cnt));
                }
        } else {
                /* Failed. */
                DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
-                   ha->host_no, rval);)
+                   ha->host_no, rval));
                rval = BIT_1;
        }
 
@@ -2132,7 +2134,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *ha, uint32_t *dwbuf, uint32_t dwords,
        uint32_t *sbuf, *siter;
        dma_addr_t sbuf_dma;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
 
        if (dwords > (DMA_POOL_SIZE / 4)) {
                DEBUG2_3_11(printk("%s(%ld): Unabled to retrieve %d DWORDs "
@@ -2196,7 +2198,7 @@ qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp)
        dma_addr_t      abt_dma;
        uint32_t        handle;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
 
        fcport = sp->fcport;
 
@@ -2229,7 +2231,7 @@ qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp)
        rval = qla2x00_issue_iocb(ha, abt, abt_dma, 0);
        if (rval != QLA_SUCCESS) {
                DEBUG2_3_11(printk("%s(%ld): failed to issue IOCB (%x).\n",
-                   __func__, ha->host_no, rval);)
+                   __func__, ha->host_no, rval));
        } else if (abt->entry_status != 0) {
                DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
                    "-- error status (%x).\n", __func__, ha->host_no,
@@ -2238,10 +2240,10 @@ qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp)
        } else if (abt->nport_handle != __constant_cpu_to_le16(0)) {
                DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
                    "-- completion status (%x).\n", __func__, ha->host_no,
-                   le16_to_cpu(abt->nport_handle));)
+                   le16_to_cpu(abt->nport_handle)));
                rval = QLA_FUNCTION_FAILED;
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);)
+               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
                sp->flags |= SRB_ABORT_PENDING;
        }
 
@@ -2268,7 +2270,7 @@ qla24xx_abort_target(fc_port_t *fcport)
        if (fcport == NULL)
                return 0;
 
-       DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no);)
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
 
        ha = fcport->ha;
        tsk = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma);
@@ -2290,7 +2292,7 @@ qla24xx_abort_target(fc_port_t *fcport)
        rval = qla2x00_issue_iocb(ha, tsk, tsk_dma, 0);
        if (rval != QLA_SUCCESS) {
                DEBUG2_3_11(printk("%s(%ld): failed to issue Target Reset IOCB "
-                   "(%x).\n", __func__, ha->host_no, rval);)
+                   "(%x).\n", __func__, ha->host_no, rval));
                goto atarget_done;
        } else if (tsk->p.sts.entry_status != 0) {
                DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
@@ -2302,7 +2304,7 @@ qla24xx_abort_target(fc_port_t *fcport)
            __constant_cpu_to_le16(CS_COMPLETE)) {
                DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
                    "-- completion status (%x).\n", __func__,
-                   ha->host_no, le16_to_cpu(tsk->p.sts.comp_status));)
+                   ha->host_no, le16_to_cpu(tsk->p.sts.comp_status)));
                rval = QLA_FUNCTION_FAILED;
                goto atarget_done;
        }
@@ -2311,9 +2313,9 @@ qla24xx_abort_target(fc_port_t *fcport)
        rval = qla2x00_marker(ha, fcport->loop_id, 0, MK_SYNC_ID);
        if (rval != QLA_SUCCESS) {
                DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
-                   "(%x).\n", __func__, ha->host_no, rval);)
+                   "(%x).\n", __func__, ha->host_no, rval));
        } else {
-               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);)
+               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
        }
 
 atarget_done:
@@ -2460,3 +2462,81 @@ qla2x00_stop_firmware(scsi_qla_host_t *ha)
 
        return rval;
 }
+
+int
+qla2x00_trace_control(scsi_qla_host_t *ha, uint16_t ctrl, dma_addr_t eft_dma,
+    uint16_t buffers)
+{
+       int rval;
+       mbx_cmd_t mc;
+       mbx_cmd_t *mcp = &mc;
+
+       if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
+               return QLA_FUNCTION_FAILED;
+
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
+
+       mcp->mb[0] = MBC_TRACE_CONTROL;
+       mcp->mb[1] = ctrl;
+       mcp->out_mb = MBX_1|MBX_0;
+       mcp->in_mb = MBX_1|MBX_0;
+       if (ctrl == TC_ENABLE) {
+               mcp->mb[2] = LSW(eft_dma);
+               mcp->mb[3] = MSW(eft_dma);
+               mcp->mb[4] = LSW(MSD(eft_dma));
+               mcp->mb[5] = MSW(MSD(eft_dma));
+               mcp->mb[6] = buffers;
+               mcp->mb[7] = buffers;
+               mcp->out_mb |= MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2;
+       }
+       mcp->tov = 30;
+       mcp->flags = 0;
+       rval = qla2x00_mailbox_command(ha, mcp);
+
+       if (rval != QLA_SUCCESS) {
+               DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
+                   __func__, ha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+       } else {
+               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
+       }
+
+       return rval;
+}
+
+int
+qla2x00_read_sfp(scsi_qla_host_t *ha, dma_addr_t sfp_dma, uint16_t addr,
+    uint16_t off, uint16_t count)
+{
+       int rval;
+       mbx_cmd_t mc;
+       mbx_cmd_t *mcp = &mc;
+
+       if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
+               return QLA_FUNCTION_FAILED;
+
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
+
+       mcp->mb[0] = MBC_READ_SFP;
+       mcp->mb[1] = addr;
+       mcp->mb[2] = MSW(sfp_dma);
+       mcp->mb[3] = LSW(sfp_dma);
+       mcp->mb[6] = MSW(MSD(sfp_dma));
+       mcp->mb[7] = LSW(MSD(sfp_dma));
+       mcp->mb[8] = count;
+       mcp->mb[9] = off;
+       mcp->mb[10] = 0;
+       mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+       mcp->in_mb = MBX_0;
+       mcp->tov = 30;
+       mcp->flags = 0;
+       rval = qla2x00_mailbox_command(ha, mcp);
+
+       if (rval != QLA_SUCCESS) {
+               DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
+                   ha->host_no, rval, mcp->mb[0]));
+       } else {
+               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
+       }
+
+       return rval;
+}
index ccaad0b..3516e36 100644 (file)
@@ -54,6 +54,19 @@ module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR);
 MODULE_PARM_DESC(ql2xloginretrycount,
                "Specify an alternate value for the NVRAM login retry count.");
 
+int ql2xallocfwdump = 1;
+module_param(ql2xallocfwdump, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xallocfwdump,
+               "Option to enable allocation of memory for a firmware dump "
+               "during HBA initialization.  Memory allocation requirements "
+               "vary by ISP type.  Default is 1 - allocate memory.");
+
+int extended_error_logging;
+module_param(extended_error_logging, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(extended_error_logging,
+               "Option to enable extended error logging, "
+               "Default is 0 - no logging. 1 - log errors.");
+
 static void qla2x00_free_device(scsi_qla_host_t *);
 
 static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha);
@@ -624,7 +637,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 
                DEBUG2(printk("%s(%ld): aborting sp %p from RISC. pid=%ld.\n",
                    __func__, ha->host_no, sp, serial));
-               DEBUG3(qla2x00_print_scsi_cmd(cmd);)
+               DEBUG3(qla2x00_print_scsi_cmd(cmd));
 
                spin_unlock_irqrestore(&ha->hardware_lock, flags);
                if (ha->isp_ops.abort_command(ha, sp)) {
@@ -766,7 +779,7 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
 #endif
        } else {
                DEBUG2(printk(KERN_INFO
-                   "%s failed: loop not ready\n",__func__);)
+                   "%s failed: loop not ready\n",__func__));
        }
 
        if (ret == FAILED) {
@@ -1021,12 +1034,12 @@ qla2x00_loop_reset(scsi_qla_host_t *ha)
                /* Empty */
                DEBUG2_3(printk("%s(%ld): **** FAILED ****\n",
                                __func__,
-                               ha->host_no);)
+                               ha->host_no));
        } else {
                /* Empty */
                DEBUG3(printk("%s(%ld): exiting normally.\n",
                                __func__,
-                               ha->host_no);)
+                               ha->host_no));
        }
 
        return(status);
@@ -1324,7 +1337,8 @@ qla24xx_disable_intrs(scsi_qla_host_t *ha)
 /*
  * PCI driver interface
  */
-static int qla2x00_probe_one(struct pci_dev *pdev)
+static int __devinit
+qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int     ret = -ENODEV;
        device_reg_t __iomem *reg;
@@ -1405,7 +1419,6 @@ static int qla2x00_probe_one(struct pci_dev *pdev)
        ha->isp_ops.read_nvram          = qla2x00_read_nvram_data;
        ha->isp_ops.write_nvram         = qla2x00_write_nvram_data;
        ha->isp_ops.fw_dump             = qla2100_fw_dump;
-       ha->isp_ops.ascii_fw_dump       = qla2100_ascii_fw_dump;
        ha->isp_ops.read_optrom         = qla2x00_read_optrom_data;
        ha->isp_ops.write_optrom        = qla2x00_write_optrom_data;
        if (IS_QLA2100(ha)) {
@@ -1432,7 +1445,6 @@ static int qla2x00_probe_one(struct pci_dev *pdev)
                ha->isp_ops.pci_config = qla2300_pci_config;
                ha->isp_ops.intr_handler = qla2300_intr_handler;
                ha->isp_ops.fw_dump = qla2300_fw_dump;
-               ha->isp_ops.ascii_fw_dump = qla2300_ascii_fw_dump;
                ha->isp_ops.beacon_on = qla2x00_beacon_on;
                ha->isp_ops.beacon_off = qla2x00_beacon_off;
                ha->isp_ops.beacon_blink = qla2x00_beacon_blink;
@@ -1469,7 +1481,6 @@ static int qla2x00_probe_one(struct pci_dev *pdev)
                ha->isp_ops.read_nvram = qla24xx_read_nvram_data;
                ha->isp_ops.write_nvram = qla24xx_write_nvram_data;
                ha->isp_ops.fw_dump = qla24xx_fw_dump;
-               ha->isp_ops.ascii_fw_dump = qla24xx_ascii_fw_dump;
                ha->isp_ops.read_optrom = qla24xx_read_optrom_data;
                ha->isp_ops.write_optrom = qla24xx_write_optrom_data;
                ha->isp_ops.beacon_on = qla24xx_beacon_on;
@@ -1640,7 +1651,8 @@ probe_out:
        return ret;
 }
 
-static void qla2x00_remove_one(struct pci_dev *pdev)
+static void __devexit
+qla2x00_remove_one(struct pci_dev *pdev)
 {
        scsi_qla_host_t *ha;
 
@@ -1678,6 +1690,9 @@ qla2x00_free_device(scsi_qla_host_t *ha)
                kthread_stop(t);
        }
 
+       if (ha->eft)
+               qla2x00_trace_control(ha, TC_DISABLE, 0, 0);
+
        /* Stop currently executing firmware. */
        qla2x00_stop_firmware(ha);
 
@@ -1899,17 +1914,6 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
                }
                memset(ha->init_cb, 0, ha->init_cb_size);
 
-               /* Allocate ioctl related memory. */
-               if (qla2x00_alloc_ioctl_mem(ha)) {
-                       qla_printk(KERN_WARNING, ha,
-                           "Memory Allocation failed - ioctl_mem\n");
-
-                       qla2x00_mem_free(ha);
-                       msleep(100);
-
-                       continue;
-               }
-
                if (qla2x00_allocate_sp_pool(ha)) {
                        qla_printk(KERN_WARNING, ha,
                            "Memory Allocation failed - "
@@ -1972,6 +1976,26 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
                                continue;
                        }
                        memset(ha->ct_sns, 0, sizeof(struct ct_sns_pkt));
+
+                       if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+                               /*
+                                * Get consistent memory allocated for SFP
+                                * block.
+                                */
+                               ha->sfp_data = dma_pool_alloc(ha->s_dma_pool,
+                                   GFP_KERNEL, &ha->sfp_data_dma);
+                               if (ha->sfp_data == NULL) {
+                                       qla_printk(KERN_WARNING, ha,
+                                           "Memory Allocation failed - "
+                                           "sfp_data\n");
+
+                                       qla2x00_mem_free(ha);
+                                       msleep(100);
+
+                                       continue;
+                               }
+                               memset(ha->sfp_data, 0, SFP_BLOCK_SIZE);
+                       }
                }
 
                /* Done all allocations without any error. */
@@ -2006,12 +2030,16 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
                return;
        }
 
-       /* free ioctl memory */
-       qla2x00_free_ioctl_mem(ha);
-
        /* free sp pool */
        qla2x00_free_sp_pool(ha);
 
+       if (ha->fw_dump) {
+               if (ha->eft)
+                       dma_free_coherent(&ha->pdev->dev,
+                           ntohl(ha->fw_dump->eft_size), ha->eft, ha->eft_dma);
+               vfree(ha->fw_dump);
+       }
+
        if (ha->sns_cmd)
                dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt),
                    ha->sns_cmd, ha->sns_cmd_dma);
@@ -2020,6 +2048,9 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
                dma_free_coherent(&ha->pdev->dev, sizeof(struct ct_sns_pkt),
                    ha->ct_sns, ha->ct_sns_dma);
 
+       if (ha->sfp_data)
+               dma_pool_free(ha->s_dma_pool, ha->sfp_data, ha->sfp_data_dma);
+
        if (ha->ms_iocb)
                dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
 
@@ -2043,6 +2074,8 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
                    (ha->request_q_length + 1) * sizeof(request_t),
                    ha->request_ring, ha->request_dma);
 
+       ha->eft = NULL;
+       ha->eft_dma = 0;
        ha->sns_cmd = NULL;
        ha->sns_cmd_dma = 0;
        ha->ct_sns = NULL;
@@ -2071,13 +2104,9 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
        }
        INIT_LIST_HEAD(&ha->fcports);
 
-       vfree(ha->fw_dump);
-       vfree(ha->fw_dump_buffer);
-
        ha->fw_dump = NULL;
        ha->fw_dumped = 0;
        ha->fw_dump_reading = 0;
-       ha->fw_dump_buffer = NULL;
 
        vfree(ha->optrom_buffer);
 }
@@ -2617,40 +2646,16 @@ static struct pci_device_id qla2xxx_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);
 
-static int __devinit
-qla2xxx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-       return qla2x00_probe_one(pdev);
-}
-
-static void __devexit
-qla2xxx_remove_one(struct pci_dev *pdev)
-{
-       qla2x00_remove_one(pdev);
-}
-
 static struct pci_driver qla2xxx_pci_driver = {
        .name           = QLA2XXX_DRIVER_NAME,
        .driver         = {
                .owner          = THIS_MODULE,
        },
        .id_table       = qla2xxx_pci_tbl,
-       .probe          = qla2xxx_probe_one,
-       .remove         = __devexit_p(qla2xxx_remove_one),
+       .probe          = qla2x00_probe_one,
+       .remove         = __devexit_p(qla2x00_remove_one),
 };
 
-static inline int
-qla2x00_pci_module_init(void)
-{
-       return pci_module_init(&qla2xxx_pci_driver);
-}
-
-static inline void
-qla2x00_pci_module_exit(void)
-{
-       pci_unregister_driver(&qla2xxx_pci_driver);
-}
-
 /**
  * qla2x00_module_init - Module initialization.
  **/
@@ -2670,16 +2675,16 @@ qla2x00_module_init(void)
 
        /* Derive version string. */
        strcpy(qla2x00_version_str, QLA2XXX_VERSION);
-#if DEBUG_QLA2100
-       strcat(qla2x00_version_str, "-debug");
-#endif
+       if (extended_error_logging)
+               strcat(qla2x00_version_str, "-debug");
+
        qla2xxx_transport_template =
            fc_attach_transport(&qla2xxx_transport_functions);
        if (!qla2xxx_transport_template)
                return -ENODEV;
 
        printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n");
-       ret = qla2x00_pci_module_init();
+       ret = pci_register_driver(&qla2xxx_pci_driver);
        if (ret) {
                kmem_cache_destroy(srb_cachep);
                fc_release_transport(qla2xxx_transport_template);
@@ -2693,7 +2698,7 @@ qla2x00_module_init(void)
 static void __exit
 qla2x00_module_exit(void)
 {
-       qla2x00_pci_module_exit();
+       pci_unregister_driver(&qla2xxx_pci_driver);
        qla2x00_release_firmware();
        kmem_cache_destroy(srb_cachep);
        fc_release_transport(qla2xxx_transport_template);
index 6b31552..d2d6834 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.01.05-k2"
+#define QLA2XXX_VERSION      "8.01.05-k3"
 
 #define QLA_DRIVER_MAJOR_VER   8
 #define QLA_DRIVER_MINOR_VER   1
index 5a5d2af..1da8ccd 100644 (file)
 #include "scsi_logging.h"
 #include "scsi_debug.h"
 
-#define SCSI_DEBUG_VERSION "1.75"
-static const char * scsi_debug_version_date = "20050113";
+#define SCSI_DEBUG_VERSION "1.79"
+static const char * scsi_debug_version_date = "20060604";
 
 /* Additional Sense Code (ASC) used */
-#define NO_ADDED_SENSE 0x0
+#define NO_ADDITIONAL_SENSE 0x0
+#define LOGICAL_UNIT_NOT_READY 0x4
 #define UNRECOVERED_READ_ERR 0x11
+#define PARAMETER_LIST_LENGTH_ERR 0x1a
 #define INVALID_OPCODE 0x20
 #define ADDR_OUT_OF_RANGE 0x21
 #define INVALID_FIELD_IN_CDB 0x24
+#define INVALID_FIELD_IN_PARAM_LIST 0x26
 #define POWERON_RESET 0x29
 #define SAVING_PARAMS_UNSUP 0x39
-#define THRESHHOLD_EXCEEDED 0x5d
+#define THRESHOLD_EXCEEDED 0x5d
+#define LOW_POWER_COND_ON 0x5e
 
 #define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */
 
@@ -81,6 +85,8 @@ static const char * scsi_debug_version_date = "20050113";
 #define DEF_SCSI_LEVEL   5    /* INQUIRY, byte2 [5->SPC-3] */
 #define DEF_PTYPE   0
 #define DEF_D_SENSE   0
+#define DEF_NO_LUN_0   0
+#define DEF_VIRTUAL_GB   0
 
 /* bit mask values for scsi_debug_opts */
 #define SCSI_DEBUG_OPT_NOISE   1
@@ -107,6 +113,7 @@ static const char * scsi_debug_version_date = "20050113";
 /* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1)
  * or "peripheral device" addressing (value 0) */
 #define SAM2_LUN_ADDRESS_METHOD 0
+#define SAM2_WLUN_REPORT_LUNS 0xc101
 
 static int scsi_debug_add_host = DEF_NUM_HOST;
 static int scsi_debug_delay = DEF_DELAY;
@@ -119,13 +126,16 @@ static int scsi_debug_opts = DEF_OPTS;
 static int scsi_debug_scsi_level = DEF_SCSI_LEVEL;
 static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */
 static int scsi_debug_dsense = DEF_D_SENSE;
+static int scsi_debug_no_lun_0 = DEF_NO_LUN_0;
+static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB;
 
 static int scsi_debug_cmnd_count = 0;
 
 #define DEV_READONLY(TGT)      (0)
 #define DEV_REMOVEABLE(TGT)    (0)
 
-static unsigned long sdebug_store_size;        /* in bytes */
+static unsigned int sdebug_store_size; /* in bytes */
+static unsigned int sdebug_store_sectors;
 static sector_t sdebug_capacity;       /* in sectors */
 
 /* old BIOS stuff, kernel may get rid of them but some mode sense pages
@@ -150,7 +160,9 @@ struct sdebug_dev_info {
        unsigned int target;
        unsigned int lun;
        struct sdebug_host_info *sdbg_host;
+       unsigned int wlun;
        char reset;
+       char stopped;
        char used;
 };
 
@@ -194,11 +206,11 @@ static struct scsi_host_template sdebug_driver_template = {
        .bios_param =           scsi_debug_biosparam,
        .can_queue =            SCSI_DEBUG_CANQUEUE,
        .this_id =              7,
-       .sg_tablesize =         64,
-       .cmd_per_lun =          3,
-       .max_sectors =          4096,
+       .sg_tablesize =         256,
+       .cmd_per_lun =          16,
+       .max_sectors =          0xffff,
        .unchecked_isa_dma =    0,
-       .use_clustering =       DISABLE_CLUSTERING,
+       .use_clustering =       ENABLE_CLUSTERING,
        .module =               THIS_MODULE,
 };
 
@@ -226,19 +238,32 @@ static struct device_driver sdebug_driverfs_driver = {
 static const int check_condition_result =
                (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
 
+static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
+                                   0, 0, 0x2, 0x4b};
+static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
+                                  0, 0, 0x0, 0x0};
+
 /* function declarations */
 static int resp_inquiry(struct scsi_cmnd * SCpnt, int target,
                        struct sdebug_dev_info * devip);
 static int resp_requests(struct scsi_cmnd * SCpnt,
                         struct sdebug_dev_info * devip);
+static int resp_start_stop(struct scsi_cmnd * scp,
+                          struct sdebug_dev_info * devip);
 static int resp_readcap(struct scsi_cmnd * SCpnt,
                        struct sdebug_dev_info * devip);
-static int resp_mode_sense(struct scsi_cmnd * SCpnt, int target,
+static int resp_readcap16(struct scsi_cmnd * SCpnt,
+                         struct sdebug_dev_info * devip);
+static int resp_mode_sense(struct scsi_cmnd * scp, int target,
                           struct sdebug_dev_info * devip);
-static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block,
-                    int num, struct sdebug_dev_info * devip);
-static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block,
-                     int num, struct sdebug_dev_info * devip);
+static int resp_mode_select(struct scsi_cmnd * scp, int mselect6,
+                           struct sdebug_dev_info * devip);
+static int resp_log_sense(struct scsi_cmnd * scp,
+                         struct sdebug_dev_info * devip);
+static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba,
+                    unsigned int num, struct sdebug_dev_info * devip);
+static int resp_write(struct scsi_cmnd * SCpnt, unsigned long long lba,
+                     unsigned int num, struct sdebug_dev_info * devip);
 static int resp_report_luns(struct scsi_cmnd * SCpnt,
                            struct sdebug_dev_info * devip);
 static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
@@ -249,8 +274,8 @@ static void timer_intr_handler(unsigned long);
 static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev);
 static void mk_sense_buffer(struct sdebug_dev_info * devip, int key,
                            int asc, int asq);
-static int check_reset(struct scsi_cmnd * SCpnt,
-                      struct sdebug_dev_info * devip);
+static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only,
+                          struct sdebug_dev_info * devip);
 static int schedule_resp(struct scsi_cmnd * cmnd,
                         struct sdebug_dev_info * devip,
                         done_funct_t done, int scsi_result, int delta_jiff);
@@ -258,8 +283,10 @@ static void __init sdebug_build_parts(unsigned char * ramp);
 static void __init init_all_queued(void);
 static void stop_all_queued(void);
 static int stop_queued_cmnd(struct scsi_cmnd * cmnd);
-static int inquiry_evpd_83(unsigned char * arr, int dev_id_num,
-                           const char * dev_id_str, int dev_id_str_len);
+static int inquiry_evpd_83(unsigned char * arr, int target_dev_id,
+                          int dev_id_num, const char * dev_id_str,
+                          int dev_id_str_len);
+static int inquiry_evpd_88(unsigned char * arr, int target_dev_id);
 static void do_create_driverfs_files(void);
 static void do_remove_driverfs_files(void);
 
@@ -275,18 +302,22 @@ static
 int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
 {
        unsigned char *cmd = (unsigned char *) SCpnt->cmnd;
-       int block, upper_blk, num, k;
+       int len, k, j;
+       unsigned int num;
+       unsigned long long lba;
        int errsts = 0;
-       int target = scmd_id(SCpnt);
+       int target = SCpnt->device->id;
        struct sdebug_dev_info * devip = NULL;
        int inj_recovered = 0;
+       int delay_override = 0;
 
        if (done == NULL)
                return 0;       /* assume mid level reprocessing command */
 
+       SCpnt->resid = 0;
        if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) {
                printk(KERN_INFO "scsi_debug: cmd ");
-               for (k = 0, num = SCpnt->cmd_len; k < num; ++k)
+               for (k = 0, len = SCpnt->cmd_len; k < len; ++k)
                        printk("%02x ", (int)cmd[k]);
                printk("\n");
        }
@@ -297,7 +328,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
                                     DID_NO_CONNECT << 16, 0);
         }
 
-       if (SCpnt->device->lun >= scsi_debug_max_luns)
+       if ((SCpnt->device->lun >= scsi_debug_max_luns) &&
+           (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS))
                return schedule_resp(SCpnt, NULL, done,
                                     DID_NO_CONNECT << 16, 0);
        devip = devInfoReg(SCpnt->device);
@@ -316,118 +348,150 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
                        inj_recovered = 1; /* to reads and writes below */
         }
 
+       if (devip->wlun) {
+               switch (*cmd) {
+               case INQUIRY:
+               case REQUEST_SENSE:
+               case TEST_UNIT_READY:
+               case REPORT_LUNS:
+                       break;  /* only allowable wlun commands */
+               default:
+                       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+                               printk(KERN_INFO "scsi_debug: Opcode: 0x%x "
+                                      "not supported for wlun\n", *cmd);
+                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                                       INVALID_OPCODE, 0);
+                       errsts = check_condition_result;
+                       return schedule_resp(SCpnt, devip, done, errsts,
+                                            0);
+               }
+       }
+
        switch (*cmd) {
        case INQUIRY:     /* mandatory, ignore unit attention */
+               delay_override = 1;
                errsts = resp_inquiry(SCpnt, target, devip);
                break;
        case REQUEST_SENSE:     /* mandatory, ignore unit attention */
+               delay_override = 1;
                errsts = resp_requests(SCpnt, devip);
                break;
        case REZERO_UNIT:       /* actually this is REWIND for SSC */
        case START_STOP:
-               errsts = check_reset(SCpnt, devip);
+               errsts = resp_start_stop(SCpnt, devip);
                break;
        case ALLOW_MEDIUM_REMOVAL:
-               if ((errsts = check_reset(SCpnt, devip)))
+               if ((errsts = check_readiness(SCpnt, 1, devip)))
                        break;
                if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
                        printk(KERN_INFO "scsi_debug: Medium removal %s\n",
                                cmd[4] ? "inhibited" : "enabled");
                break;
        case SEND_DIAGNOSTIC:     /* mandatory */
-               errsts = check_reset(SCpnt, devip);
+               errsts = check_readiness(SCpnt, 1, devip);
                break;
        case TEST_UNIT_READY:     /* mandatory */
-               errsts = check_reset(SCpnt, devip);
+               delay_override = 1;
+               errsts = check_readiness(SCpnt, 0, devip);
                break;
         case RESERVE:
-               errsts = check_reset(SCpnt, devip);
+               errsts = check_readiness(SCpnt, 1, devip);
                 break;
         case RESERVE_10:
-               errsts = check_reset(SCpnt, devip);
+               errsts = check_readiness(SCpnt, 1, devip);
                 break;
         case RELEASE:
-               errsts = check_reset(SCpnt, devip);
+               errsts = check_readiness(SCpnt, 1, devip);
                 break;
         case RELEASE_10:
-               errsts = check_reset(SCpnt, devip);
+               errsts = check_readiness(SCpnt, 1, devip);
                 break;
        case READ_CAPACITY:
                errsts = resp_readcap(SCpnt, devip);
                break;
+       case SERVICE_ACTION_IN:
+               if (SAI_READ_CAPACITY_16 != cmd[1]) {
+                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                                       INVALID_OPCODE, 0);
+                       errsts = check_condition_result;
+                       break;
+               }
+               errsts = resp_readcap16(SCpnt, devip);
+               break;
        case READ_16:
        case READ_12:
        case READ_10:
        case READ_6:
-               if ((errsts = check_reset(SCpnt, devip)))
+               if ((errsts = check_readiness(SCpnt, 0, devip)))
                        break;
-               upper_blk = 0;
                if ((*cmd) == READ_16) {
-                       upper_blk = cmd[5] + (cmd[4] << 8) +
-                                   (cmd[3] << 16) + (cmd[2] << 24);
-                       block = cmd[9] + (cmd[8] << 8) +
-                               (cmd[7] << 16) + (cmd[6] << 24);
+                       for (lba = 0, j = 0; j < 8; ++j) {
+                               if (j > 0)
+                                       lba <<= 8;
+                               lba += cmd[2 + j];
+                       }
                        num = cmd[13] + (cmd[12] << 8) +
                                (cmd[11] << 16) + (cmd[10] << 24);
                } else if ((*cmd) == READ_12) {
-                       block = cmd[5] + (cmd[4] << 8) +
+                       lba = cmd[5] + (cmd[4] << 8) +
                                (cmd[3] << 16) + (cmd[2] << 24);
                        num = cmd[9] + (cmd[8] << 8) +
                                (cmd[7] << 16) + (cmd[6] << 24);
                } else if ((*cmd) == READ_10) {
-                       block = cmd[5] + (cmd[4] << 8) +
+                       lba = cmd[5] + (cmd[4] << 8) +
                                (cmd[3] << 16) + (cmd[2] << 24);
                        num = cmd[8] + (cmd[7] << 8);
-               } else {
-                       block = cmd[3] + (cmd[2] << 8) +
+               } else {        /* READ (6) */
+                       lba = cmd[3] + (cmd[2] << 8) +
                                ((cmd[1] & 0x1f) << 16);
-                       num = cmd[4];
+                       num = (0 == cmd[4]) ? 256 : cmd[4];
                }
-               errsts = resp_read(SCpnt, upper_blk, block, num, devip);
+               errsts = resp_read(SCpnt, lba, num, devip);
                if (inj_recovered && (0 == errsts)) {
                        mk_sense_buffer(devip, RECOVERED_ERROR,
-                                       THRESHHOLD_EXCEEDED, 0);
+                                       THRESHOLD_EXCEEDED, 0);
                        errsts = check_condition_result;
                }
                break;
        case REPORT_LUNS:       /* mandatory, ignore unit attention */
+               delay_override = 1;
                errsts = resp_report_luns(SCpnt, devip);
                break;
        case VERIFY:            /* 10 byte SBC-2 command */
-               errsts = check_reset(SCpnt, devip);
+               errsts = check_readiness(SCpnt, 0, devip);
                break;
        case WRITE_16:
        case WRITE_12:
        case WRITE_10:
        case WRITE_6:
-               if ((errsts = check_reset(SCpnt, devip)))
+               if ((errsts = check_readiness(SCpnt, 0, devip)))
                        break;
-               upper_blk = 0;
                if ((*cmd) == WRITE_16) {
-                       upper_blk = cmd[5] + (cmd[4] << 8) +
-                                   (cmd[3] << 16) + (cmd[2] << 24);
-                       block = cmd[9] + (cmd[8] << 8) +
-                               (cmd[7] << 16) + (cmd[6] << 24);
+                       for (lba = 0, j = 0; j < 8; ++j) {
+                               if (j > 0)
+                                       lba <<= 8;
+                               lba += cmd[2 + j];
+                       }
                        num = cmd[13] + (cmd[12] << 8) +
                                (cmd[11] << 16) + (cmd[10] << 24);
                } else if ((*cmd) == WRITE_12) {
-                       block = cmd[5] + (cmd[4] << 8) +
+                       lba = cmd[5] + (cmd[4] << 8) +
                                (cmd[3] << 16) + (cmd[2] << 24);
                        num = cmd[9] + (cmd[8] << 8) +
                                (cmd[7] << 16) + (cmd[6] << 24);
                } else if ((*cmd) == WRITE_10) {
-                       block = cmd[5] + (cmd[4] << 8) +
+                       lba = cmd[5] + (cmd[4] << 8) +
                                (cmd[3] << 16) + (cmd[2] << 24);
                        num = cmd[8] + (cmd[7] << 8);
-               } else {
-                       block = cmd[3] + (cmd[2] << 8) +
+               } else {        /* WRITE (6) */
+                       lba = cmd[3] + (cmd[2] << 8) +
                                ((cmd[1] & 0x1f) << 16);
-                       num = cmd[4];
+                       num = (0 == cmd[4]) ? 256 : cmd[4];
                }
-               errsts = resp_write(SCpnt, upper_blk, block, num, devip);
+               errsts = resp_write(SCpnt, lba, num, devip);
                if (inj_recovered && (0 == errsts)) {
                        mk_sense_buffer(devip, RECOVERED_ERROR,
-                                       THRESHHOLD_EXCEEDED, 0);
+                                       THRESHOLD_EXCEEDED, 0);
                        errsts = check_condition_result;
                }
                break;
@@ -435,20 +499,31 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
        case MODE_SENSE_10:
                errsts = resp_mode_sense(SCpnt, target, devip);
                break;
+       case MODE_SELECT:
+               errsts = resp_mode_select(SCpnt, 1, devip);
+               break;
+       case MODE_SELECT_10:
+               errsts = resp_mode_select(SCpnt, 0, devip);
+               break;
+       case LOG_SENSE:
+               errsts = resp_log_sense(SCpnt, devip);
+               break;
        case SYNCHRONIZE_CACHE:
-               errsts = check_reset(SCpnt, devip);
+               delay_override = 1;
+               errsts = check_readiness(SCpnt, 0, devip);
                break;
        default:
                if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
                        printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "
                               "supported\n", *cmd);
-               if ((errsts = check_reset(SCpnt, devip)))
+               if ((errsts = check_readiness(SCpnt, 1, devip)))
                        break;  /* Unit attention takes precedence */
                mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
                errsts = check_condition_result;
                break;
        }
-       return schedule_resp(SCpnt, devip, done, errsts, scsi_debug_delay);
+       return schedule_resp(SCpnt, devip, done, errsts,
+                            (delay_override ? 0 : scsi_debug_delay));
 }
 
 static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
@@ -460,7 +535,8 @@ static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
        /* return -ENOTTY; // correct return but upsets fdisk */
 }
 
-static int check_reset(struct scsi_cmnd * SCpnt, struct sdebug_dev_info * devip)
+static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only,
+                          struct sdebug_dev_info * devip)
 {
        if (devip->reset) {
                if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
@@ -470,6 +546,14 @@ static int check_reset(struct scsi_cmnd * SCpnt, struct sdebug_dev_info * devip)
                mk_sense_buffer(devip, UNIT_ATTENTION, POWERON_RESET, 0);
                return check_condition_result;
        }
+       if ((0 == reset_only) && devip->stopped) {
+               if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+                       printk(KERN_INFO "scsi_debug: Reporting Not "
+                              "ready: initializing command required\n");
+               mk_sense_buffer(devip, NOT_READY, LOGICAL_UNIT_NOT_READY,
+                               0x2);
+               return check_condition_result;
+       }
        return 0;
 }
 
@@ -493,7 +577,10 @@ static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
                req_len = scp->request_bufflen;
                act_len = (req_len < arr_len) ? req_len : arr_len;
                memcpy(scp->request_buffer, arr, act_len);
-               scp->resid = req_len - act_len;
+               if (scp->resid)
+                       scp->resid -= act_len;
+               else
+                       scp->resid = req_len - act_len;
                return 0;
        }
        sgpnt = (struct scatterlist *)scp->request_buffer;
@@ -516,7 +603,10 @@ static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
                }
                req_len += sgpnt->length;
        }
-       scp->resid = req_len - act_len;
+       if (scp->resid)
+               scp->resid -= act_len;
+       else
+               scp->resid = req_len - act_len;
        return 0;
 }
 
@@ -567,12 +657,14 @@ static const char * inq_vendor_id = "Linux   ";
 static const char * inq_product_id = "scsi_debug      ";
 static const char * inq_product_rev = "0004";
 
-static int inquiry_evpd_83(unsigned char * arr, int dev_id_num,
-                          const char * dev_id_str, int dev_id_str_len)
+static int inquiry_evpd_83(unsigned char * arr, int target_dev_id,
+                          int dev_id_num, const char * dev_id_str,
+                          int dev_id_str_len)
 {
-       int num;
+       int num, port_a;
+       char b[32];
 
-       /* Two identification descriptors: */
+       port_a = target_dev_id + 1;
        /* T10 vendor identifier field format (faked) */
        arr[0] = 0x2;   /* ASCII */
        arr[1] = 0x1;
@@ -583,25 +675,246 @@ static int inquiry_evpd_83(unsigned char * arr, int dev_id_num,
        num = 8 + 16 + dev_id_str_len;
        arr[3] = num;
        num += 4;
-       /* NAA IEEE registered identifier (faked) */
-       arr[num] = 0x1; /* binary */
-       arr[num + 1] = 0x3;
-       arr[num + 2] = 0x0;
-       arr[num + 3] = 0x8;
-       arr[num + 4] = 0x51;    /* ieee company id=0x123456 (faked) */
-       arr[num + 5] = 0x23;
-       arr[num + 6] = 0x45;
-       arr[num + 7] = 0x60;
-       arr[num + 8] = (dev_id_num >> 24);
-       arr[num + 9] = (dev_id_num >> 16) & 0xff;
-       arr[num + 10] = (dev_id_num >> 8) & 0xff;
-       arr[num + 11] = dev_id_num & 0xff;
-       return num + 12;
+       if (dev_id_num >= 0) {
+               /* NAA-5, Logical unit identifier (binary) */
+               arr[num++] = 0x1;       /* binary (not necessarily sas) */
+               arr[num++] = 0x3;       /* PIV=0, lu, naa */
+               arr[num++] = 0x0;
+               arr[num++] = 0x8;
+               arr[num++] = 0x53;  /* naa-5 ieee company id=0x333333 (fake) */
+               arr[num++] = 0x33;
+               arr[num++] = 0x33;
+               arr[num++] = 0x30;
+               arr[num++] = (dev_id_num >> 24);
+               arr[num++] = (dev_id_num >> 16) & 0xff;
+               arr[num++] = (dev_id_num >> 8) & 0xff;
+               arr[num++] = dev_id_num & 0xff;
+               /* Target relative port number */
+               arr[num++] = 0x61;      /* proto=sas, binary */
+               arr[num++] = 0x94;      /* PIV=1, target port, rel port */
+               arr[num++] = 0x0;       /* reserved */
+               arr[num++] = 0x4;       /* length */
+               arr[num++] = 0x0;       /* reserved */
+               arr[num++] = 0x0;       /* reserved */
+               arr[num++] = 0x0;
+               arr[num++] = 0x1;       /* relative port A */
+       }
+       /* NAA-5, Target port identifier */
+       arr[num++] = 0x61;      /* proto=sas, binary */
+       arr[num++] = 0x93;      /* piv=1, target port, naa */
+       arr[num++] = 0x0;
+       arr[num++] = 0x8;
+       arr[num++] = 0x52;      /* naa-5, company id=0x222222 (fake) */
+       arr[num++] = 0x22;
+       arr[num++] = 0x22;
+       arr[num++] = 0x20;
+       arr[num++] = (port_a >> 24);
+       arr[num++] = (port_a >> 16) & 0xff;
+       arr[num++] = (port_a >> 8) & 0xff;
+       arr[num++] = port_a & 0xff;
+       /* NAA-5, Target device identifier */
+       arr[num++] = 0x61;      /* proto=sas, binary */
+       arr[num++] = 0xa3;      /* piv=1, target device, naa */
+       arr[num++] = 0x0;
+       arr[num++] = 0x8;
+       arr[num++] = 0x52;      /* naa-5, company id=0x222222 (fake) */
+       arr[num++] = 0x22;
+       arr[num++] = 0x22;
+       arr[num++] = 0x20;
+       arr[num++] = (target_dev_id >> 24);
+       arr[num++] = (target_dev_id >> 16) & 0xff;
+       arr[num++] = (target_dev_id >> 8) & 0xff;
+       arr[num++] = target_dev_id & 0xff;
+       /* SCSI name string: Target device identifier */
+       arr[num++] = 0x63;      /* proto=sas, UTF-8 */
+       arr[num++] = 0xa8;      /* piv=1, target device, SCSI name string */
+       arr[num++] = 0x0;
+       arr[num++] = 24;
+       memcpy(arr + num, "naa.52222220", 12);
+       num += 12;
+       snprintf(b, sizeof(b), "%08X", target_dev_id);
+       memcpy(arr + num, b, 8);
+       num += 8;
+       memset(arr + num, 0, 4);
+       num += 4;
+       return num;
+}
+
+
+static unsigned char vpd84_data[] = {
+/* from 4th byte */ 0x22,0x22,0x22,0x0,0xbb,0x0,
+    0x22,0x22,0x22,0x0,0xbb,0x1,
+    0x22,0x22,0x22,0x0,0xbb,0x2,
+};
+
+static int inquiry_evpd_84(unsigned char * arr)
+{
+       memcpy(arr, vpd84_data, sizeof(vpd84_data));
+       return sizeof(vpd84_data);
+}
+
+static int inquiry_evpd_85(unsigned char * arr)
+{
+       int num = 0;
+       const char * na1 = "https://www.kernel.org/config";
+       const char * na2 = "http://www.kernel.org/log";
+       int plen, olen;
+
+       arr[num++] = 0x1;       /* lu, storage config */
+       arr[num++] = 0x0;       /* reserved */
+       arr[num++] = 0x0;
+       olen = strlen(na1);
+       plen = olen + 1;
+       if (plen % 4)
+               plen = ((plen / 4) + 1) * 4;
+       arr[num++] = plen;      /* length, null termianted, padded */
+       memcpy(arr + num, na1, olen);
+       memset(arr + num + olen, 0, plen - olen);
+       num += plen;
+
+       arr[num++] = 0x4;       /* lu, logging */
+       arr[num++] = 0x0;       /* reserved */
+       arr[num++] = 0x0;
+       olen = strlen(na2);
+       plen = olen + 1;
+       if (plen % 4)
+               plen = ((plen / 4) + 1) * 4;
+       arr[num++] = plen;      /* length, null terminated, padded */
+       memcpy(arr + num, na2, olen);
+       memset(arr + num + olen, 0, plen - olen);
+       num += plen;
+
+       return num;
+}
+
+/* SCSI ports VPD page */
+static int inquiry_evpd_88(unsigned char * arr, int target_dev_id)
+{
+       int num = 0;
+       int port_a, port_b;
+
+       port_a = target_dev_id + 1;
+       port_b = port_a + 1;
+       arr[num++] = 0x0;       /* reserved */
+       arr[num++] = 0x0;       /* reserved */
+       arr[num++] = 0x0;
+       arr[num++] = 0x1;       /* relative port 1 (primary) */
+       memset(arr + num, 0, 6);
+       num += 6;
+       arr[num++] = 0x0;
+       arr[num++] = 12;        /* length tp descriptor */
+       /* naa-5 target port identifier (A) */
+       arr[num++] = 0x61;      /* proto=sas, binary */
+       arr[num++] = 0x93;      /* PIV=1, target port, NAA */
+       arr[num++] = 0x0;       /* reserved */
+       arr[num++] = 0x8;       /* length */
+       arr[num++] = 0x52;      /* NAA-5, company_id=0x222222 (fake) */
+       arr[num++] = 0x22;
+       arr[num++] = 0x22;
+       arr[num++] = 0x20;
+       arr[num++] = (port_a >> 24);
+       arr[num++] = (port_a >> 16) & 0xff;
+       arr[num++] = (port_a >> 8) & 0xff;
+       arr[num++] = port_a & 0xff;
+
+       arr[num++] = 0x0;       /* reserved */
+       arr[num++] = 0x0;       /* reserved */
+       arr[num++] = 0x0;
+       arr[num++] = 0x2;       /* relative port 2 (secondary) */
+       memset(arr + num, 0, 6);
+       num += 6;
+       arr[num++] = 0x0;
+       arr[num++] = 12;        /* length tp descriptor */
+       /* naa-5 target port identifier (B) */
+       arr[num++] = 0x61;      /* proto=sas, binary */
+       arr[num++] = 0x93;      /* PIV=1, target port, NAA */
+       arr[num++] = 0x0;       /* reserved */
+       arr[num++] = 0x8;       /* length */
+       arr[num++] = 0x52;      /* NAA-5, company_id=0x222222 (fake) */
+       arr[num++] = 0x22;
+       arr[num++] = 0x22;
+       arr[num++] = 0x20;
+       arr[num++] = (port_b >> 24);
+       arr[num++] = (port_b >> 16) & 0xff;
+       arr[num++] = (port_b >> 8) & 0xff;
+       arr[num++] = port_b & 0xff;
+
+       return num;
+}
+
+
+static unsigned char vpd89_data[] = {
+/* from 4th byte */ 0,0,0,0,
+'l','i','n','u','x',' ',' ',' ',
+'S','A','T',' ','s','c','s','i','_','d','e','b','u','g',' ',' ',
+'1','2','3','4',
+0x34,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
+0xec,0,0,0,
+0x5a,0xc,0xff,0x3f,0x37,0xc8,0x10,0,0,0,0,0,0x3f,0,0,0,
+0,0,0,0,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x20,0x20,0x20,0x20,
+0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0,0,0,0x40,0x4,0,0x2e,0x33,
+0x38,0x31,0x20,0x20,0x20,0x20,0x54,0x53,0x38,0x33,0x30,0x30,0x33,0x31,
+0x53,0x41,
+0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+0x20,0x20,
+0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+0x10,0x80,
+0,0,0,0x2f,0,0,0,0x2,0,0x2,0x7,0,0xff,0xff,0x1,0,
+0x3f,0,0xc1,0xff,0x3e,0,0x10,0x1,0xb0,0xf8,0x50,0x9,0,0,0x7,0,
+0x3,0,0x78,0,0x78,0,0xf0,0,0x78,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0x2,0,0,0,0,0,0,0,
+0x7e,0,0x1b,0,0x6b,0x34,0x1,0x7d,0x3,0x40,0x69,0x34,0x1,0x3c,0x3,0x40,
+0x7f,0x40,0,0,0,0,0xfe,0xfe,0,0,0,0,0,0xfe,0,0,
+0,0,0,0,0,0,0,0,0xb0,0xf8,0x50,0x9,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0x1,0,0xb0,0xf8,0x50,0x9,0xb0,0xf8,0x50,0x9,0x20,0x20,0x2,0,0xb6,0x42,
+0,0x80,0x8a,0,0x6,0x3c,0xa,0x3c,0xff,0xff,0xc6,0x7,0,0x1,0,0x8,
+0xf0,0xf,0,0x10,0x2,0,0x30,0,0,0,0,0,0,0,0x6,0xfe,
+0,0,0x2,0,0x50,0,0x8a,0,0x4f,0x95,0,0,0x21,0,0xb,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa5,0x51,
+};
+
+static int inquiry_evpd_89(unsigned char * arr)
+{
+       memcpy(arr, vpd89_data, sizeof(vpd89_data));
+       return sizeof(vpd89_data);
+}
+
+
+static unsigned char vpdb0_data[] = {
+       /* from 4th byte */ 0,0,0,4,
+       0,0,0x4,0,
+       0,0,0,64,
+};
+
+static int inquiry_evpd_b0(unsigned char * arr)
+{
+       memcpy(arr, vpdb0_data, sizeof(vpdb0_data));
+       if (sdebug_store_sectors > 0x400) {
+               arr[4] = (sdebug_store_sectors >> 24) & 0xff;
+               arr[5] = (sdebug_store_sectors >> 16) & 0xff;
+               arr[6] = (sdebug_store_sectors >> 8) & 0xff;
+               arr[7] = sdebug_store_sectors & 0xff;
+       }
+       return sizeof(vpdb0_data);
 }
 
 
 #define SDEBUG_LONG_INQ_SZ 96
-#define SDEBUG_MAX_INQ_ARR_SZ 128
+#define SDEBUG_MAX_INQ_ARR_SZ 584
 
 static int resp_inquiry(struct scsi_cmnd * scp, int target,
                        struct sdebug_dev_info * devip)
@@ -609,64 +922,113 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
        unsigned char pq_pdt;
        unsigned char arr[SDEBUG_MAX_INQ_ARR_SZ];
        unsigned char *cmd = (unsigned char *)scp->cmnd;
-       int alloc_len;
+       int alloc_len, n;
 
        alloc_len = (cmd[3] << 8) + cmd[4];
        memset(arr, 0, SDEBUG_MAX_INQ_ARR_SZ);
-       pq_pdt = (scsi_debug_ptype & 0x1f);
+       if (devip->wlun)
+               pq_pdt = 0x1e;  /* present, wlun */
+       else if (scsi_debug_no_lun_0 && (0 == devip->lun))
+               pq_pdt = 0x7f;  /* not present, no device type */
+       else
+               pq_pdt = (scsi_debug_ptype & 0x1f);
        arr[0] = pq_pdt;
        if (0x2 & cmd[1]) {  /* CMDDT bit set */
                mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
                                0);
                return check_condition_result;
        } else if (0x1 & cmd[1]) {  /* EVPD bit set */
-               int dev_id_num, len;
-               char dev_id_str[6];
+               int lu_id_num, target_dev_id, len;
+               char lu_id_str[6];
+               int host_no = devip->sdbg_host->shost->host_no;
                
-               dev_id_num = ((devip->sdbg_host->shost->host_no + 1) * 2000) +
-                            (devip->target * 1000) + devip->lun;
-               len = scnprintf(dev_id_str, 6, "%d", dev_id_num);
+               lu_id_num = devip->wlun ? -1 : (((host_no + 1) * 2000) +
+                           (devip->target * 1000) + devip->lun);
+               target_dev_id = ((host_no + 1) * 2000) +
+                                (devip->target * 1000) - 3;
+               len = scnprintf(lu_id_str, 6, "%d", lu_id_num);
                if (0 == cmd[2]) { /* supported vital product data pages */
-                       arr[3] = 3;
-                       arr[4] = 0x0; /* this page */
-                       arr[5] = 0x80; /* unit serial number */
-                       arr[6] = 0x83; /* device identification */
+                       arr[1] = cmd[2];        /*sanity */
+                       n = 4;
+                       arr[n++] = 0x0;   /* this page */
+                       arr[n++] = 0x80;  /* unit serial number */
+                       arr[n++] = 0x83;  /* device identification */
+                       arr[n++] = 0x84;  /* software interface ident. */
+                       arr[n++] = 0x85;  /* management network addresses */
+                       arr[n++] = 0x86;  /* extended inquiry */
+                       arr[n++] = 0x87;  /* mode page policy */
+                       arr[n++] = 0x88;  /* SCSI ports */
+                       arr[n++] = 0x89;  /* ATA information */
+                       arr[n++] = 0xb0;  /* Block limits (SBC) */
+                       arr[3] = n - 4;   /* number of supported VPD pages */
                } else if (0x80 == cmd[2]) { /* unit serial number */
-                       arr[1] = 0x80;
+                       arr[1] = cmd[2];        /*sanity */
                        arr[3] = len;
-                       memcpy(&arr[4], dev_id_str, len);
+                       memcpy(&arr[4], lu_id_str, len);
                } else if (0x83 == cmd[2]) { /* device identification */
-                       arr[1] = 0x83;
-                       arr[3] = inquiry_evpd_83(&arr[4], dev_id_num,
-                                                dev_id_str, len);
+                       arr[1] = cmd[2];        /*sanity */
+                       arr[3] = inquiry_evpd_83(&arr[4], target_dev_id,
+                                                lu_id_num, lu_id_str, len);
+               } else if (0x84 == cmd[2]) { /* Software interface ident. */
+                       arr[1] = cmd[2];        /*sanity */
+                       arr[3] = inquiry_evpd_84(&arr[4]);
+               } else if (0x85 == cmd[2]) { /* Management network addresses */
+                       arr[1] = cmd[2];        /*sanity */
+                       arr[3] = inquiry_evpd_85(&arr[4]);
+               } else if (0x86 == cmd[2]) { /* extended inquiry */
+                       arr[1] = cmd[2];        /*sanity */
+                       arr[3] = 0x3c;  /* number of following entries */
+                       arr[4] = 0x0;   /* no protection stuff */
+                       arr[5] = 0x7;   /* head of q, ordered + simple q's */
+               } else if (0x87 == cmd[2]) { /* mode page policy */
+                       arr[1] = cmd[2];        /*sanity */
+                       arr[3] = 0x8;   /* number of following entries */
+                       arr[4] = 0x2;   /* disconnect-reconnect mp */
+                       arr[6] = 0x80;  /* mlus, shared */
+                       arr[8] = 0x18;   /* protocol specific lu */
+                       arr[10] = 0x82;  /* mlus, per initiator port */
+               } else if (0x88 == cmd[2]) { /* SCSI Ports */
+                       arr[1] = cmd[2];        /*sanity */
+                       arr[3] = inquiry_evpd_88(&arr[4], target_dev_id);
+               } else if (0x89 == cmd[2]) { /* ATA information */
+                       arr[1] = cmd[2];        /*sanity */
+                       n = inquiry_evpd_89(&arr[4]);
+                       arr[2] = (n >> 8);
+                       arr[3] = (n & 0xff);
+               } else if (0xb0 == cmd[2]) { /* Block limits (SBC) */
+                       arr[1] = cmd[2];        /*sanity */
+                       arr[3] = inquiry_evpd_b0(&arr[4]);
                } else {
                        /* Illegal request, invalid field in cdb */
                        mk_sense_buffer(devip, ILLEGAL_REQUEST,
                                        INVALID_FIELD_IN_CDB, 0);
                        return check_condition_result;
                }
+               len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len);
                return fill_from_dev_buffer(scp, arr,
-                           min(alloc_len, SDEBUG_MAX_INQ_ARR_SZ));
+                           min(len, SDEBUG_MAX_INQ_ARR_SZ));
        }
        /* drops through here for a standard inquiry */
        arr[1] = DEV_REMOVEABLE(target) ? 0x80 : 0;     /* Removable disk */
        arr[2] = scsi_debug_scsi_level;
        arr[3] = 2;    /* response_data_format==2 */
        arr[4] = SDEBUG_LONG_INQ_SZ - 5;
-       arr[6] = 0x1; /* claim: ADDR16 */
+       arr[6] = 0x10; /* claim: MultiP */
        /* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */
-       arr[7] = 0x3a; /* claim: WBUS16, SYNC, LINKED + CMDQUE */
+       arr[7] = 0xa; /* claim: LINKED + CMDQUE */
        memcpy(&arr[8], inq_vendor_id, 8);
        memcpy(&arr[16], inq_product_id, 16);
        memcpy(&arr[32], inq_product_rev, 4);
        /* version descriptors (2 bytes each) follow */
-       arr[58] = 0x0; arr[59] = 0x40; /* SAM-2 */
-       arr[60] = 0x3; arr[61] = 0x0;  /* SPC-3 */
+       arr[58] = 0x0; arr[59] = 0x77; /* SAM-3 ANSI */
+       arr[60] = 0x3; arr[61] = 0x14;  /* SPC-3 ANSI */
+       n = 62;
        if (scsi_debug_ptype == 0) {
-               arr[62] = 0x1; arr[63] = 0x80; /* SBC */
+               arr[n++] = 0x3; arr[n++] = 0x3d; /* SBC-2 ANSI */
        } else if (scsi_debug_ptype == 1) {
-               arr[62] = 0x2; arr[63] = 0x00; /* SSC */
+               arr[n++] = 0x3; arr[n++] = 0x60; /* SSC-2 no version */
        }
+       arr[n++] = 0xc; arr[n++] = 0xf;  /* SAS-1.1 rev 10 */
        return fill_from_dev_buffer(scp, arr,
                            min(alloc_len, SDEBUG_LONG_INQ_SZ));
 }
@@ -677,46 +1039,141 @@ static int resp_requests(struct scsi_cmnd * scp,
        unsigned char * sbuff;
        unsigned char *cmd = (unsigned char *)scp->cmnd;
        unsigned char arr[SDEBUG_SENSE_LEN];
+       int want_dsense;
        int len = 18;
 
-       memset(arr, 0, SDEBUG_SENSE_LEN);
+       memset(arr, 0, sizeof(arr));
        if (devip->reset == 1)
-               mk_sense_buffer(devip, 0, NO_ADDED_SENSE, 0);
+               mk_sense_buffer(devip, 0, NO_ADDITIONAL_SENSE, 0);
+       want_dsense = !!(cmd[1] & 1) || scsi_debug_dsense;
        sbuff = devip->sense_buff;
-       if ((cmd[1] & 1) && (! scsi_debug_dsense)) {
-               /* DESC bit set and sense_buff in fixed format */
-               arr[0] = 0x72;
-               arr[1] = sbuff[2];     /* sense key */
-               arr[2] = sbuff[12];    /* asc */
-               arr[3] = sbuff[13];    /* ascq */
-               len = 8;
-       } else
+       if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) {
+               if (want_dsense) {
+                       arr[0] = 0x72;
+                       arr[1] = 0x0;           /* NO_SENSE in sense_key */
+                       arr[2] = THRESHOLD_EXCEEDED;
+                       arr[3] = 0xff;          /* TEST set and MRIE==6 */
+               } else {
+                       arr[0] = 0x70;
+                       arr[2] = 0x0;           /* NO_SENSE in sense_key */
+                       arr[7] = 0xa;           /* 18 byte sense buffer */
+                       arr[12] = THRESHOLD_EXCEEDED;
+                       arr[13] = 0xff;         /* TEST set and MRIE==6 */
+               }
+       } else if (devip->stopped) {
+               if (want_dsense) {
+                       arr[0] = 0x72;
+                       arr[1] = 0x0;           /* NO_SENSE in sense_key */
+                       arr[2] = LOW_POWER_COND_ON;
+                       arr[3] = 0x0;           /* TEST set and MRIE==6 */
+               } else {
+                       arr[0] = 0x70;
+                       arr[2] = 0x0;           /* NO_SENSE in sense_key */
+                       arr[7] = 0xa;           /* 18 byte sense buffer */
+                       arr[12] = LOW_POWER_COND_ON;
+                       arr[13] = 0x0;          /* TEST set and MRIE==6 */
+               }
+       } else {
                memcpy(arr, sbuff, SDEBUG_SENSE_LEN);
-       mk_sense_buffer(devip, 0, NO_ADDED_SENSE, 0);
+               if ((cmd[1] & 1) && (! scsi_debug_dsense)) {
+                       /* DESC bit set and sense_buff in fixed format */
+                       memset(arr, 0, sizeof(arr));
+                       arr[0] = 0x72;
+                       arr[1] = sbuff[2];     /* sense key */
+                       arr[2] = sbuff[12];    /* asc */
+                       arr[3] = sbuff[13];    /* ascq */
+                       len = 8;
+               }
+       }
+       mk_sense_buffer(devip, 0, NO_ADDITIONAL_SENSE, 0);
        return fill_from_dev_buffer(scp, arr, len);
 }
 
+static int resp_start_stop(struct scsi_cmnd * scp,
+                          struct sdebug_dev_info * devip)
+{
+       unsigned char *cmd = (unsigned char *)scp->cmnd;
+       int power_cond, errsts, start;
+
+       if ((errsts = check_readiness(scp, 1, devip)))
+               return errsts;
+       power_cond = (cmd[4] & 0xf0) >> 4;
+       if (power_cond) {
+               mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+                               0);
+               return check_condition_result;
+       }
+       start = cmd[4] & 1;
+       if (start == devip->stopped)
+               devip->stopped = !start;
+       return 0;
+}
+
 #define SDEBUG_READCAP_ARR_SZ 8
 static int resp_readcap(struct scsi_cmnd * scp,
                        struct sdebug_dev_info * devip)
 {
        unsigned char arr[SDEBUG_READCAP_ARR_SZ];
-       unsigned long capac;
+       unsigned int capac;
        int errsts;
 
-       if ((errsts = check_reset(scp, devip)))
+       if ((errsts = check_readiness(scp, 1, devip)))
                return errsts;
+       /* following just in case virtual_gb changed */
+       if (scsi_debug_virtual_gb > 0) {
+               sdebug_capacity = 2048 * 1024;
+               sdebug_capacity *= scsi_debug_virtual_gb;
+       } else
+               sdebug_capacity = sdebug_store_sectors;
        memset(arr, 0, SDEBUG_READCAP_ARR_SZ);
-       capac = (unsigned long)sdebug_capacity - 1;
-       arr[0] = (capac >> 24);
-       arr[1] = (capac >> 16) & 0xff;
-       arr[2] = (capac >> 8) & 0xff;
-       arr[3] = capac & 0xff;
+       if (sdebug_capacity < 0xffffffff) {
+               capac = (unsigned int)sdebug_capacity - 1;
+               arr[0] = (capac >> 24);
+               arr[1] = (capac >> 16) & 0xff;
+               arr[2] = (capac >> 8) & 0xff;
+               arr[3] = capac & 0xff;
+       } else {
+               arr[0] = 0xff;
+               arr[1] = 0xff;
+               arr[2] = 0xff;
+               arr[3] = 0xff;
+       }
        arr[6] = (SECT_SIZE_PER(target) >> 8) & 0xff;
        arr[7] = SECT_SIZE_PER(target) & 0xff;
        return fill_from_dev_buffer(scp, arr, SDEBUG_READCAP_ARR_SZ);
 }
 
+#define SDEBUG_READCAP16_ARR_SZ 32
+static int resp_readcap16(struct scsi_cmnd * scp,
+                         struct sdebug_dev_info * devip)
+{
+       unsigned char *cmd = (unsigned char *)scp->cmnd;
+       unsigned char arr[SDEBUG_READCAP16_ARR_SZ];
+       unsigned long long capac;
+       int errsts, k, alloc_len;
+
+       if ((errsts = check_readiness(scp, 1, devip)))
+               return errsts;
+       alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8)
+                    + cmd[13]);
+       /* following just in case virtual_gb changed */
+       if (scsi_debug_virtual_gb > 0) {
+               sdebug_capacity = 2048 * 1024;
+               sdebug_capacity *= scsi_debug_virtual_gb;
+       } else
+               sdebug_capacity = sdebug_store_sectors;
+       memset(arr, 0, SDEBUG_READCAP16_ARR_SZ);
+       capac = sdebug_capacity - 1;
+       for (k = 0; k < 8; ++k, capac >>= 8)
+               arr[7 - k] = capac & 0xff;
+       arr[8] = (SECT_SIZE_PER(target) >> 24) & 0xff;
+       arr[9] = (SECT_SIZE_PER(target) >> 16) & 0xff;
+       arr[10] = (SECT_SIZE_PER(target) >> 8) & 0xff;
+       arr[11] = SECT_SIZE_PER(target) & 0xff;
+       return fill_from_dev_buffer(scp, arr,
+                                   min(alloc_len, SDEBUG_READCAP16_ARR_SZ));
+}
+
 /* <<Following mode page info copied from ST318451LW>> */
 
 static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target)
@@ -772,27 +1229,98 @@ static int resp_caching_pg(unsigned char * p, int pcontrol, int target)
 
 static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target)
 {      /* Control mode page for mode_sense */
-       unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
+       unsigned char ch_ctrl_m_pg[] = {/* 0xa, 10, */ 0x6, 0, 0, 0, 0, 0,
+                                       0, 0, 0, 0};
+       unsigned char d_ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
                                     0, 0, 0x2, 0x4b};
 
        if (scsi_debug_dsense)
                ctrl_m_pg[2] |= 0x4;
+       else
+               ctrl_m_pg[2] &= ~0x4;
        memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg));
        if (1 == pcontrol)
-               memset(p + 2, 0, sizeof(ctrl_m_pg) - 2);
+               memcpy(p + 2, ch_ctrl_m_pg, sizeof(ch_ctrl_m_pg));
+       else if (2 == pcontrol)
+               memcpy(p, d_ctrl_m_pg, sizeof(d_ctrl_m_pg));
        return sizeof(ctrl_m_pg);
 }
 
+
 static int resp_iec_m_pg(unsigned char * p, int pcontrol, int target)
 {      /* Informational Exceptions control mode page for mode_sense */
-       unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
-                                   0, 0, 0x0, 0x0};
+       unsigned char ch_iec_m_pg[] = {/* 0x1c, 0xa, */ 0x4, 0xf, 0, 0, 0, 0,
+                                      0, 0, 0x0, 0x0};
+       unsigned char d_iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
+                                     0, 0, 0x0, 0x0};
+
        memcpy(p, iec_m_pg, sizeof(iec_m_pg));
        if (1 == pcontrol)
-               memset(p + 2, 0, sizeof(iec_m_pg) - 2);
+               memcpy(p + 2, ch_iec_m_pg, sizeof(ch_iec_m_pg));
+       else if (2 == pcontrol)
+               memcpy(p, d_iec_m_pg, sizeof(d_iec_m_pg));
        return sizeof(iec_m_pg);
 }
 
+static int resp_sas_sf_m_pg(unsigned char * p, int pcontrol, int target)
+{      /* SAS SSP mode page - short format for mode_sense */
+       unsigned char sas_sf_m_pg[] = {0x19, 0x6,
+               0x6, 0x0, 0x7, 0xd0, 0x0, 0x0};
+
+       memcpy(p, sas_sf_m_pg, sizeof(sas_sf_m_pg));
+       if (1 == pcontrol)
+               memset(p + 2, 0, sizeof(sas_sf_m_pg) - 2);
+       return sizeof(sas_sf_m_pg);
+}
+
+
+static int resp_sas_pcd_m_spg(unsigned char * p, int pcontrol, int target,
+                             int target_dev_id)
+{      /* SAS phy control and discover mode page for mode_sense */
+       unsigned char sas_pcd_m_pg[] = {0x59, 0x1, 0, 0x64, 0, 0x6, 0, 2,
+                   0, 0, 0, 0, 0x10, 0x9, 0x8, 0x0,
+                   0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0,
+                   0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1,
+                   0x2, 0, 0, 0, 0, 0, 0, 0,
+                   0x88, 0x99, 0, 0, 0, 0, 0, 0,
+                   0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 1, 0, 0, 0x10, 0x9, 0x8, 0x0,
+                   0x52, 0x22, 0x22, 0x20, 0x0, 0x0, 0x0, 0x0,
+                   0x51, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x1,
+                   0x3, 0, 0, 0, 0, 0, 0, 0,
+                   0x88, 0x99, 0, 0, 0, 0, 0, 0,
+                   0, 0, 0, 0, 0, 0, 0, 0,
+               };
+       int port_a, port_b;
+
+       port_a = target_dev_id + 1;
+       port_b = port_a + 1;
+       memcpy(p, sas_pcd_m_pg, sizeof(sas_pcd_m_pg));
+       p[20] = (port_a >> 24);
+       p[21] = (port_a >> 16) & 0xff;
+       p[22] = (port_a >> 8) & 0xff;
+       p[23] = port_a & 0xff;
+       p[48 + 20] = (port_b >> 24);
+       p[48 + 21] = (port_b >> 16) & 0xff;
+       p[48 + 22] = (port_b >> 8) & 0xff;
+       p[48 + 23] = port_b & 0xff;
+       if (1 == pcontrol)
+               memset(p + 4, 0, sizeof(sas_pcd_m_pg) - 4);
+       return sizeof(sas_pcd_m_pg);
+}
+
+static int resp_sas_sha_m_spg(unsigned char * p, int pcontrol)
+{      /* SAS SSP shared protocol specific port mode subpage */
+       unsigned char sas_sha_m_pg[] = {0x59, 0x2, 0, 0xc, 0, 0x6, 0x10, 0,
+                   0, 0, 0, 0, 0, 0, 0, 0,
+               };
+
+       memcpy(p, sas_sha_m_pg, sizeof(sas_sha_m_pg));
+       if (1 == pcontrol)
+               memset(p + 4, 0, sizeof(sas_sha_m_pg) - 4);
+       return sizeof(sas_sha_m_pg);
+}
+
 #define SDEBUG_MAX_MSENSE_SZ 256
 
 static int resp_mode_sense(struct scsi_cmnd * scp, int target,
@@ -801,12 +1329,12 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
        unsigned char dbd;
        int pcontrol, pcode, subpcode;
        unsigned char dev_spec;
-       int alloc_len, msense_6, offset, len, errsts;
+       int alloc_len, msense_6, offset, len, errsts, target_dev_id;
        unsigned char * ap;
        unsigned char arr[SDEBUG_MAX_MSENSE_SZ];
        unsigned char *cmd = (unsigned char *)scp->cmnd;
 
-       if ((errsts = check_reset(scp, devip)))
+       if ((errsts = check_readiness(scp, 1, devip)))
                return errsts;
        dbd = cmd[1] & 0x8;
        pcontrol = (cmd[2] & 0xc0) >> 6;
@@ -820,6 +1348,8 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
                                0);
                return check_condition_result;
        }
+       target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) +
+                       (devip->target * 1000) - 3;
        dev_spec = DEV_READONLY(target) ? 0x80 : 0x0;
        if (msense_6) {
                arr[2] = dev_spec;
@@ -830,7 +1360,8 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
        }
        ap = arr + offset;
 
-       if (0 != subpcode) { /* TODO: Control Extension page */
+       if ((subpcode > 0x0) && (subpcode < 0xff) && (0x19 != pcode)) {
+               /* TODO: Control Extension page */
                mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
                                0);
                return check_condition_result;
@@ -856,17 +1387,45 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
                len = resp_ctrl_m_pg(ap, pcontrol, target);
                offset += len;
                break;
+       case 0x19:      /* if spc==1 then sas phy, control+discover */
+               if ((subpcode > 0x2) && (subpcode < 0xff)) {
+                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                                       INVALID_FIELD_IN_CDB, 0);
+                       return check_condition_result;
+               }
+               len = 0;
+               if ((0x0 == subpcode) || (0xff == subpcode))
+                       len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
+               if ((0x1 == subpcode) || (0xff == subpcode))
+                       len += resp_sas_pcd_m_spg(ap + len, pcontrol, target,
+                                                 target_dev_id);
+               if ((0x2 == subpcode) || (0xff == subpcode))
+                       len += resp_sas_sha_m_spg(ap + len, pcontrol);
+               offset += len;
+               break;
        case 0x1c:      /* Informational Exceptions Mode page, all devices */
                len = resp_iec_m_pg(ap, pcontrol, target);
                offset += len;
                break;
        case 0x3f:      /* Read all Mode pages */
-               len = resp_err_recov_pg(ap, pcontrol, target);
-               len += resp_disconnect_pg(ap + len, pcontrol, target);
-               len += resp_format_pg(ap + len, pcontrol, target);
-               len += resp_caching_pg(ap + len, pcontrol, target);
-               len += resp_ctrl_m_pg(ap + len, pcontrol, target);
-               len += resp_iec_m_pg(ap + len, pcontrol, target);
+               if ((0 == subpcode) || (0xff == subpcode)) {
+                       len = resp_err_recov_pg(ap, pcontrol, target);
+                       len += resp_disconnect_pg(ap + len, pcontrol, target);
+                       len += resp_format_pg(ap + len, pcontrol, target);
+                       len += resp_caching_pg(ap + len, pcontrol, target);
+                       len += resp_ctrl_m_pg(ap + len, pcontrol, target);
+                       len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
+                       if (0xff == subpcode) {
+                               len += resp_sas_pcd_m_spg(ap + len, pcontrol,
+                                                 target, target_dev_id);
+                               len += resp_sas_sha_m_spg(ap + len, pcontrol);
+                       }
+                       len += resp_iec_m_pg(ap + len, pcontrol, target);
+               } else {
+                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                                       INVALID_FIELD_IN_CDB, 0);
+                       return check_condition_result;
+                }
                offset += len;
                break;
        default:
@@ -883,71 +1442,274 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
        return fill_from_dev_buffer(scp, arr, min(alloc_len, offset));
 }
 
-static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block,
-                    int num, struct sdebug_dev_info * devip)
+#define SDEBUG_MAX_MSELECT_SZ 512
+
+static int resp_mode_select(struct scsi_cmnd * scp, int mselect6,
+                           struct sdebug_dev_info * devip)
+{
+       int pf, sp, ps, md_len, bd_len, off, spf, pg_len;
+       int param_len, res, errsts, mpage;
+       unsigned char arr[SDEBUG_MAX_MSELECT_SZ];
+       unsigned char *cmd = (unsigned char *)scp->cmnd;
+
+       if ((errsts = check_readiness(scp, 1, devip)))
+               return errsts;
+       memset(arr, 0, sizeof(arr));
+       pf = cmd[1] & 0x10;
+       sp = cmd[1] & 0x1;
+       param_len = mselect6 ? cmd[4] : ((cmd[7] << 8) + cmd[8]);
+       if ((0 == pf) || sp || (param_len > SDEBUG_MAX_MSELECT_SZ)) {
+               mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                               INVALID_FIELD_IN_CDB, 0);
+               return check_condition_result;
+       }
+        res = fetch_to_dev_buffer(scp, arr, param_len);
+        if (-1 == res)
+                return (DID_ERROR << 16);
+        else if ((res < param_len) &&
+                 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
+                printk(KERN_INFO "scsi_debug: mode_select: cdb indicated=%d, "
+                       " IO sent=%d bytes\n", param_len, res);
+       md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2);
+       bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]);
+       if ((md_len > 2) || (0 != bd_len)) {
+               mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                               INVALID_FIELD_IN_PARAM_LIST, 0);
+               return check_condition_result;
+       }
+       off = bd_len + (mselect6 ? 4 : 8);
+       mpage = arr[off] & 0x3f;
+       ps = !!(arr[off] & 0x80);
+       if (ps) {
+               mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                               INVALID_FIELD_IN_PARAM_LIST, 0);
+               return check_condition_result;
+       }
+       spf = !!(arr[off] & 0x40);
+       pg_len = spf ? ((arr[off + 2] << 8) + arr[off + 3] + 4) :
+                      (arr[off + 1] + 2);
+       if ((pg_len + off) > param_len) {
+               mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                               PARAMETER_LIST_LENGTH_ERR, 0);
+               return check_condition_result;
+       }
+       switch (mpage) {
+       case 0xa:      /* Control Mode page */
+               if (ctrl_m_pg[1] == arr[off + 1]) {
+                       memcpy(ctrl_m_pg + 2, arr + off + 2,
+                              sizeof(ctrl_m_pg) - 2);
+                       scsi_debug_dsense = !!(ctrl_m_pg[2] & 0x4);
+                       return 0;
+               }
+               break;
+       case 0x1c:      /* Informational Exceptions Mode page */
+               if (iec_m_pg[1] == arr[off + 1]) {
+                       memcpy(iec_m_pg + 2, arr + off + 2,
+                              sizeof(iec_m_pg) - 2);
+                       return 0;
+               }
+               break;
+       default:
+               break;
+       }
+       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                       INVALID_FIELD_IN_PARAM_LIST, 0);
+       return check_condition_result;
+}
+
+static int resp_temp_l_pg(unsigned char * arr)
+{
+       unsigned char temp_l_pg[] = {0x0, 0x0, 0x3, 0x2, 0x0, 38,
+                                    0x0, 0x1, 0x3, 0x2, 0x0, 65,
+               };
+
+        memcpy(arr, temp_l_pg, sizeof(temp_l_pg));
+        return sizeof(temp_l_pg);
+}
+
+static int resp_ie_l_pg(unsigned char * arr)
+{
+       unsigned char ie_l_pg[] = {0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 38,
+               };
+
+        memcpy(arr, ie_l_pg, sizeof(ie_l_pg));
+       if (iec_m_pg[2] & 0x4) {        /* TEST bit set */
+               arr[4] = THRESHOLD_EXCEEDED;
+               arr[5] = 0xff;
+       }
+        return sizeof(ie_l_pg);
+}
+
+#define SDEBUG_MAX_LSENSE_SZ 512
+
+static int resp_log_sense(struct scsi_cmnd * scp,
+                          struct sdebug_dev_info * devip)
+{
+       int ppc, sp, pcontrol, pcode, alloc_len, errsts, len, n;
+       unsigned char arr[SDEBUG_MAX_LSENSE_SZ];
+       unsigned char *cmd = (unsigned char *)scp->cmnd;
+
+       if ((errsts = check_readiness(scp, 1, devip)))
+               return errsts;
+       memset(arr, 0, sizeof(arr));
+       ppc = cmd[1] & 0x2;
+       sp = cmd[1] & 0x1;
+       if (ppc || sp) {
+               mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                               INVALID_FIELD_IN_CDB, 0);
+               return check_condition_result;
+       }
+       pcontrol = (cmd[2] & 0xc0) >> 6;
+       pcode = cmd[2] & 0x3f;
+       alloc_len = (cmd[7] << 8) + cmd[8];
+       arr[0] = pcode;
+       switch (pcode) {
+       case 0x0:       /* Supported log pages log page */
+               n = 4;
+               arr[n++] = 0x0;         /* this page */
+               arr[n++] = 0xd;         /* Temperature */
+               arr[n++] = 0x2f;        /* Informational exceptions */
+               arr[3] = n - 4;
+               break;
+       case 0xd:       /* Temperature log page */
+               arr[3] = resp_temp_l_pg(arr + 4);
+               break;
+       case 0x2f:      /* Informational exceptions log page */
+               arr[3] = resp_ie_l_pg(arr + 4);
+               break;
+       default:
+               mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                               INVALID_FIELD_IN_CDB, 0);
+               return check_condition_result;
+       }
+       len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len);
+       return fill_from_dev_buffer(scp, arr,
+                   min(len, SDEBUG_MAX_INQ_ARR_SZ));
+}
+
+static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba,
+                    unsigned int num, struct sdebug_dev_info * devip)
 {
        unsigned long iflags;
+       unsigned int block, from_bottom;
+       unsigned long long u;
        int ret;
 
-       if (upper_blk || (block + num > sdebug_capacity)) {
+       if (lba + num > sdebug_capacity) {
                mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
                                0);
                return check_condition_result;
        }
+       /* transfer length excessive (tie in to block limits VPD page) */
+       if (num > sdebug_store_sectors) {
+               mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+                               0);
+               return check_condition_result;
+       }
        if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
-           (block <= OPT_MEDIUM_ERR_ADDR) &&
-           ((block + num) > OPT_MEDIUM_ERR_ADDR)) {
+           (lba <= OPT_MEDIUM_ERR_ADDR) &&
+           ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
+               /* claim unrecoverable read error */
                mk_sense_buffer(devip, MEDIUM_ERROR, UNRECOVERED_READ_ERR,
                                0);
-               /* claim unrecoverable read error */
+               /* set info field and valid bit for fixed descriptor */
+               if (0x70 == (devip->sense_buff[0] & 0x7f)) {
+                       devip->sense_buff[0] |= 0x80;   /* Valid bit */
+                       ret = OPT_MEDIUM_ERR_ADDR;
+                       devip->sense_buff[3] = (ret >> 24) & 0xff;
+                       devip->sense_buff[4] = (ret >> 16) & 0xff;
+                       devip->sense_buff[5] = (ret >> 8) & 0xff;
+                       devip->sense_buff[6] = ret & 0xff;
+               }
                return check_condition_result;
        }
        read_lock_irqsave(&atomic_rw, iflags);
-       ret = fill_from_dev_buffer(SCpnt, fake_storep + (block * SECT_SIZE),
-                                  num * SECT_SIZE);
+       if ((lba + num) <= sdebug_store_sectors)
+               ret = fill_from_dev_buffer(SCpnt,
+                                          fake_storep + (lba * SECT_SIZE),
+                                          num * SECT_SIZE);
+       else {
+               /* modulo when one arg is 64 bits needs do_div() */
+               u = lba;
+               block = do_div(u, sdebug_store_sectors);
+               from_bottom = 0;
+               if ((block + num) > sdebug_store_sectors)
+                       from_bottom = (block + num) - sdebug_store_sectors;
+               ret = fill_from_dev_buffer(SCpnt,
+                                          fake_storep + (block * SECT_SIZE),
+                                          (num - from_bottom) * SECT_SIZE);
+               if ((0 == ret) && (from_bottom > 0))
+                       ret = fill_from_dev_buffer(SCpnt, fake_storep,
+                                                  from_bottom * SECT_SIZE);
+       }
        read_unlock_irqrestore(&atomic_rw, iflags);
        return ret;
 }
 
-static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block,
-                     int num, struct sdebug_dev_info * devip)
+static int resp_write(struct scsi_cmnd * SCpnt, unsigned long long lba,
+                     unsigned int num, struct sdebug_dev_info * devip)
 {
        unsigned long iflags;
+       unsigned int block, to_bottom;
+       unsigned long long u;
        int res;
 
-       if (upper_blk || (block + num > sdebug_capacity)) {
+       if (lba + num > sdebug_capacity) {
                mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
                                0);
                return check_condition_result;
        }
+       /* transfer length excessive (tie in to block limits VPD page) */
+       if (num > sdebug_store_sectors) {
+               mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+                               0);
+               return check_condition_result;
+       }
 
        write_lock_irqsave(&atomic_rw, iflags);
-       res = fetch_to_dev_buffer(SCpnt, fake_storep + (block * SECT_SIZE),
-                                 num * SECT_SIZE);
+       if ((lba + num) <= sdebug_store_sectors)
+               res = fetch_to_dev_buffer(SCpnt,
+                                         fake_storep + (lba * SECT_SIZE),
+                                         num * SECT_SIZE);
+       else {
+               /* modulo when one arg is 64 bits needs do_div() */
+               u = lba;
+               block = do_div(u, sdebug_store_sectors);
+               to_bottom = 0;
+               if ((block + num) > sdebug_store_sectors)
+                       to_bottom = (block + num) - sdebug_store_sectors;
+               res = fetch_to_dev_buffer(SCpnt,
+                                         fake_storep + (block * SECT_SIZE),
+                                         (num - to_bottom) * SECT_SIZE);
+               if ((0 == res) && (to_bottom > 0))
+                       res = fetch_to_dev_buffer(SCpnt, fake_storep,
+                                                 to_bottom * SECT_SIZE);
+       }
        write_unlock_irqrestore(&atomic_rw, iflags);
        if (-1 == res)
                return (DID_ERROR << 16);
        else if ((res < (num * SECT_SIZE)) &&
                 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
-               printk(KERN_INFO "scsi_debug: write: cdb indicated=%d, "
+               printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, "
                       " IO sent=%d bytes\n", num * SECT_SIZE, res);
        return 0;
 }
 
-#define SDEBUG_RLUN_ARR_SZ 128
+#define SDEBUG_RLUN_ARR_SZ 256
 
 static int resp_report_luns(struct scsi_cmnd * scp,
                            struct sdebug_dev_info * devip)
 {
        unsigned int alloc_len;
-       int lun_cnt, i, upper;
+       int lun_cnt, i, upper, num, n, wlun, lun;
        unsigned char *cmd = (unsigned char *)scp->cmnd;
        int select_report = (int)cmd[2];
        struct scsi_lun *one_lun;
        unsigned char arr[SDEBUG_RLUN_ARR_SZ];
+       unsigned char * max_addr;
 
        alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
-       if ((alloc_len < 16) || (select_report > 2)) {
+       if ((alloc_len < 4) || (select_report > 2)) {
                mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
                                0);
                return check_condition_result;
@@ -955,18 +1717,37 @@ static int resp_report_luns(struct scsi_cmnd * scp,
        /* can produce response with up to 16k luns (lun 0 to lun 16383) */
        memset(arr, 0, SDEBUG_RLUN_ARR_SZ);
        lun_cnt = scsi_debug_max_luns;
-       arr[2] = ((sizeof(struct scsi_lun) * lun_cnt) >> 8) & 0xff;
-       arr[3] = (sizeof(struct scsi_lun) * lun_cnt) & 0xff;
-       lun_cnt = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
-                           sizeof(struct scsi_lun)), lun_cnt);
+       if (1 == select_report)
+               lun_cnt = 0;
+       else if (scsi_debug_no_lun_0 && (lun_cnt > 0))
+               --lun_cnt;
+       wlun = (select_report > 0) ? 1 : 0;
+       num = lun_cnt + wlun;
+       arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff;
+       arr[3] = (sizeof(struct scsi_lun) * num) & 0xff;
+       n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
+                           sizeof(struct scsi_lun)), num);
+       if (n < num) {
+               wlun = 0;
+               lun_cnt = n;
+       }
        one_lun = (struct scsi_lun *) &arr[8];
-       for (i = 0; i < lun_cnt; i++) {
-               upper = (i >> 8) & 0x3f;
+       max_addr = arr + SDEBUG_RLUN_ARR_SZ;
+       for (i = 0, lun = (scsi_debug_no_lun_0 ? 1 : 0);
+             ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr));
+            i++, lun++) {
+               upper = (lun >> 8) & 0x3f;
                if (upper)
                        one_lun[i].scsi_lun[0] =
                            (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
-               one_lun[i].scsi_lun[1] = i & 0xff;
+               one_lun[i].scsi_lun[1] = lun & 0xff;
+       }
+       if (wlun) {
+               one_lun[i].scsi_lun[0] = (SAM2_WLUN_REPORT_LUNS >> 8) & 0xff;
+               one_lun[i].scsi_lun[1] = SAM2_WLUN_REPORT_LUNS & 0xff;
+               i++;
        }
+       alloc_len = (unsigned char *)(one_lun + i) - arr;
        return fill_from_dev_buffer(scp, arr,
                                    min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
 }
@@ -1002,7 +1783,8 @@ static void timer_intr_handler(unsigned long indx)
 static int scsi_debug_slave_alloc(struct scsi_device * sdp)
 {
        if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               sdev_printk(KERN_INFO, sdp, "scsi_debug: slave_alloc\n");
+               printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n",
+                      sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
        return 0;
 }
 
@@ -1011,7 +1793,8 @@ static int scsi_debug_slave_configure(struct scsi_device * sdp)
        struct sdebug_dev_info * devip;
 
        if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               sdev_printk(KERN_INFO, sdp, "scsi_debug: slave_configure\n");
+               printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %u>\n",
+                      sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
        if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN)
                sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN;
        devip = devInfoReg(sdp);
@@ -1019,6 +1802,7 @@ static int scsi_debug_slave_configure(struct scsi_device * sdp)
        if (sdp->host->cmd_per_lun)
                scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING,
                                        sdp->host->cmd_per_lun);
+       blk_queue_max_segment_size(sdp->request_queue, 256 * 1024);
        return 0;
 }
 
@@ -1028,7 +1812,8 @@ static void scsi_debug_slave_destroy(struct scsi_device * sdp)
                                (struct sdebug_dev_info *)sdp->hostdata;
 
        if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               sdev_printk(KERN_INFO, sdp, "scsi_debug: slave_destroy\n");
+               printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %u>\n",
+                      sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
        if (devip) {
                /* make this slot avaliable for re-use */
                devip->used = 0;
@@ -1085,6 +1870,8 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
                        open_devip->sense_buff[0] = 0x70;
                        open_devip->sense_buff[7] = 0xa;
                }
+               if (sdev->lun == SAM2_WLUN_REPORT_LUNS)
+                       open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff;
                return open_devip;
         }
         return NULL;
@@ -1273,7 +2060,7 @@ static void __init sdebug_build_parts(unsigned char * ramp)
                printk(KERN_WARNING "scsi_debug:build_parts: reducing "
                                    "partitions to %d\n", SDEBUG_MAX_PARTS);
        }
-       num_sectors = (int)(sdebug_store_size / SECT_SIZE);
+       num_sectors = (int)sdebug_store_sectors;
        sectors_per_part = (num_sectors - sdebug_sectors_per)
                           / scsi_debug_num_parts;
        heads_by_sects = sdebug_heads * sdebug_sectors_per;
@@ -1316,9 +2103,9 @@ static int schedule_resp(struct scsi_cmnd * cmnd,
                if (scsi_result) {
                        struct scsi_device * sdp = cmnd->device;
 
-                       sdev_printk(KERN_INFO, sdp,
-                               "non-zero result=0x%x\n",
-                               scsi_result);
+                       printk(KERN_INFO "scsi_debug:    <%u %u %u %u> "
+                              "non-zero result=0x%x\n", sdp->host->host_no,
+                              sdp->channel, sdp->id, sdp->lun, scsi_result);
                }
        }
        if (cmnd && devip) {
@@ -1365,21 +2152,19 @@ static int schedule_resp(struct scsi_cmnd * cmnd,
        }
 }
 
-/* Set 'perm' (4th argument) to 0 to disable module_param's definition
- * of sysfs parameters (which module_param doesn't yet support).
- * Sysfs parameters defined explicitly below.
- */
-module_param_named(add_host, scsi_debug_add_host, int, 0); /* perm=0644 */
-module_param_named(delay, scsi_debug_delay, int, 0); /* perm=0644 */
-module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, 0);
-module_param_named(dsense, scsi_debug_dsense, int, 0);
-module_param_named(every_nth, scsi_debug_every_nth, int, 0);
-module_param_named(max_luns, scsi_debug_max_luns, int, 0);
-module_param_named(num_parts, scsi_debug_num_parts, int, 0);
-module_param_named(num_tgts, scsi_debug_num_tgts, int, 0);
-module_param_named(opts, scsi_debug_opts, int, 0); /* perm=0644 */
-module_param_named(ptype, scsi_debug_ptype, int, 0);
-module_param_named(scsi_level, scsi_debug_scsi_level, int, 0);
+module_param_named(add_host, scsi_debug_add_host, int, S_IRUGO | S_IWUSR);
+module_param_named(delay, scsi_debug_delay, int, S_IRUGO | S_IWUSR);
+module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, S_IRUGO);
+module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR);
+module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR);
+module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR);
+module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR);
+module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO);
+module_param_named(num_tgts, scsi_debug_num_tgts, int, S_IRUGO | S_IWUSR);
+module_param_named(opts, scsi_debug_opts, int, S_IRUGO | S_IWUSR);
+module_param_named(ptype, scsi_debug_ptype, int, S_IRUGO | S_IWUSR);
+module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO);
+module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR);
 
 MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
 MODULE_DESCRIPTION("SCSI debug adapter driver");
@@ -1388,15 +2173,17 @@ MODULE_VERSION(SCSI_DEBUG_VERSION);
 
 MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)");
 MODULE_PARM_DESC(delay, "# of jiffies to delay response(def=1)");
-MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs");
-MODULE_PARM_DESC(dsense, "use descriptor sense format(def: fixed)");
+MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs(def=8)");
+MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)");
 MODULE_PARM_DESC(every_nth, "timeout every nth command(def=100)");
-MODULE_PARM_DESC(max_luns, "number of SCSI LUNs per target to simulate");
+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 SCSI targets per host to simulate");
-MODULE_PARM_DESC(opts, "1->noise, 2->medium_error, 4->...");
+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(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)");
 
 
 static char sdebug_info[256];
@@ -1548,6 +2335,24 @@ static ssize_t sdebug_dsense_store(struct device_driver * ddp,
 DRIVER_ATTR(dsense, S_IRUGO | S_IWUSR, sdebug_dsense_show,
            sdebug_dsense_store);
 
+static ssize_t sdebug_no_lun_0_show(struct device_driver * ddp, char * buf)
+{
+        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_no_lun_0);
+}
+static ssize_t sdebug_no_lun_0_store(struct device_driver * ddp,
+                                    const char * buf, size_t count)
+{
+        int n;
+
+       if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
+               scsi_debug_no_lun_0 = n;
+               return count;
+       }
+       return -EINVAL;
+}
+DRIVER_ATTR(no_lun_0, S_IRUGO | S_IWUSR, sdebug_no_lun_0_show,
+           sdebug_no_lun_0_store);
+
 static ssize_t sdebug_num_tgts_show(struct device_driver * ddp, char * buf)
 {
         return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts);
@@ -1623,6 +2428,29 @@ static ssize_t sdebug_scsi_level_show(struct device_driver * ddp, char * buf)
 }
 DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_show, NULL);
 
+static ssize_t sdebug_virtual_gb_show(struct device_driver * ddp, char * buf)
+{
+        return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_virtual_gb);
+}
+static ssize_t sdebug_virtual_gb_store(struct device_driver * ddp,
+                                      const char * buf, size_t count)
+{
+        int n;
+
+       if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
+               scsi_debug_virtual_gb = n;
+               if (scsi_debug_virtual_gb > 0) {
+                       sdebug_capacity = 2048 * 1024;
+                       sdebug_capacity *= scsi_debug_virtual_gb;
+               } else
+                       sdebug_capacity = sdebug_store_sectors;
+               return count;
+       }
+       return -EINVAL;
+}
+DRIVER_ATTR(virtual_gb, S_IRUGO | S_IWUSR, sdebug_virtual_gb_show,
+           sdebug_virtual_gb_store);
+
 static ssize_t sdebug_add_host_show(struct device_driver * ddp, char * buf)
 {
         return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host);
@@ -1692,14 +2520,19 @@ static void do_remove_driverfs_files(void)
 
 static int __init scsi_debug_init(void)
 {
-       unsigned long sz;
+       unsigned int sz;
        int host_to_add;
        int k;
 
        if (scsi_debug_dev_size_mb < 1)
                scsi_debug_dev_size_mb = 1;  /* force minimum 1 MB ramdisk */
-       sdebug_store_size = (unsigned long)scsi_debug_dev_size_mb * 1048576;
-       sdebug_capacity = sdebug_store_size / SECT_SIZE;
+       sdebug_store_size = (unsigned int)scsi_debug_dev_size_mb * 1048576;
+       sdebug_store_sectors = sdebug_store_size / SECT_SIZE;
+       if (scsi_debug_virtual_gb > 0) {
+               sdebug_capacity = 2048 * 1024;
+               sdebug_capacity *= scsi_debug_virtual_gb;
+       } else
+               sdebug_capacity = sdebug_store_sectors;
 
        /* play around with geometry, don't waste too much on track 0 */
        sdebug_heads = 8;
@@ -1813,7 +2646,7 @@ static int sdebug_add_adapter(void)
         struct sdebug_dev_info *sdbg_devinfo;
         struct list_head *lh, *lh_sf;
 
-        sdbg_host = kzalloc(sizeof(*sdbg_host), GFP_KERNEL);
+        sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL);
 
         if (NULL == sdbg_host) {
                 printk(KERN_ERR "%s: out of memory at line %d\n",
@@ -1825,7 +2658,7 @@ static int sdebug_add_adapter(void)
 
        devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns;
         for (k = 0; k < devs_per_host; k++) {
-                sdbg_devinfo = kzalloc(sizeof(*sdbg_devinfo), GFP_KERNEL);
+                sdbg_devinfo = kzalloc(sizeof(*sdbg_devinfo),GFP_KERNEL);
                 if (NULL == sdbg_devinfo) {
                         printk(KERN_ERR "%s: out of memory at line %d\n",
                                __FUNCTION__, __LINE__);
@@ -1906,7 +2739,7 @@ static int sdebug_driver_probe(struct device * dev)
                hpnt->max_id = scsi_debug_num_tgts + 1;
        else
                hpnt->max_id = scsi_debug_num_tgts;
-       hpnt->max_lun = scsi_debug_max_luns;
+       hpnt->max_lun = SAM2_WLUN_REPORT_LUNS;  /* = scsi_debug_max_luns; */
 
         error = scsi_add_host(hpnt, &sdbg_host->dev);
         if (error) {
@@ -1960,7 +2793,7 @@ static void sdebug_max_tgts_luns(void)
                        hpnt->max_id = scsi_debug_num_tgts + 1;
                else
                        hpnt->max_id = scsi_debug_num_tgts;
-               hpnt->max_lun = scsi_debug_max_luns;
+               hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* scsi_debug_max_luns; */
        }
        spin_unlock(&sdebug_host_list_lock);
 }
index fb5cb4c..3d0429b 100644 (file)
@@ -162,7 +162,7 @@ static struct {
        {"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_ATTACH_PQ3 | BLIST_SPARSELUN | BLIST_LARGELUN},
        {"HITACHI", "OPEN-E", "*", BLIST_ATTACH_PQ3 | BLIST_SPARSELUN | BLIST_LARGELUN},
        {"HP", "A6189A", NULL, BLIST_SPARSELUN | BLIST_LARGELUN},       /* HP VA7400 */
-       {"HP", "OPEN-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, /* HP XP Arrays */
+       {"HP", "OPEN-", "*", BLIST_REPORTLUN2}, /* HP XP Arrays */
        {"HP", "NetRAID-4M", NULL, BLIST_FORCELUN},
        {"HP", "HSV100", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
        {"HP", "C1557A", NULL, BLIST_FORCELUN},
index 6a7a60f..6683d59 100644 (file)
@@ -1672,7 +1672,9 @@ int
 scsi_reset_provider(struct scsi_device *dev, int flag)
 {
        struct scsi_cmnd *scmd = scsi_get_command(dev, GFP_KERNEL);
+       struct Scsi_Host *shost = dev->host;
        struct request req;
+       unsigned long flags;
        int rtn;
 
        scmd->request = &req;
@@ -1699,6 +1701,10 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
         */
        scmd->pid                       = 0;
 
+       spin_lock_irqsave(shost->host_lock, flags);
+       shost->tmf_in_progress = 1;
+       spin_unlock_irqrestore(shost->host_lock, flags);
+
        switch (flag) {
        case SCSI_TRY_RESET_DEVICE:
                rtn = scsi_try_bus_device_reset(scmd);
@@ -1717,6 +1723,22 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
                rtn = FAILED;
        }
 
+       spin_lock_irqsave(shost->host_lock, flags);
+       shost->tmf_in_progress = 0;
+       spin_unlock_irqrestore(shost->host_lock, flags);
+
+       /*
+        * be sure to wake up anyone who was sleeping or had their queue
+        * suspended while we performed the TMF.
+        */
+       SCSI_LOG_ERROR_RECOVERY(3,
+               printk("%s: waking up host to restart after TMF\n",
+               __FUNCTION__));
+
+       wake_up(&shost->host_wait);
+
+       scsi_run_host_queues(shost);
+
        scsi_next_command(scmd);
        return rtn;
 }
index 3d04a9f..bf5191f 100644 (file)
@@ -855,8 +855,7 @@ static void scsi_release_buffers(struct scsi_cmnd *cmd)
  *             b) We can just use scsi_requeue_command() here.  This would
  *                be used if we just wanted to retry, for example.
  */
-void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
-                       unsigned int block_bytes)
+void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 {
        int result = cmd->result;
        int this_count = cmd->bufflen;
@@ -921,87 +920,72 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
         * Next deal with any sectors which we were able to correctly
         * handle.
         */
-       if (good_bytes >= 0) {
-               SCSI_LOG_HLCOMPLETE(1, printk("%ld sectors total, %d bytes done.\n",
+       if (good_bytes > 0) {
+               SCSI_LOG_HLCOMPLETE(1, printk("%ld sectors total, "
+                                             "%d bytes done.\n",
                                              req->nr_sectors, good_bytes));
                SCSI_LOG_HLCOMPLETE(1, printk("use_sg is %d\n", cmd->use_sg));
 
                if (clear_errors)
                        req->errors = 0;
-               /*
-                * If multiple sectors are requested in one buffer, then
-                * they will have been finished off by the first command.
-                * If not, then we have a multi-buffer command.
-                *
-                * If block_bytes != 0, it means we had a medium error
-                * of some sort, and that we want to mark some number of
-                * sectors as not uptodate.  Thus we want to inhibit
-                * requeueing right here - we will requeue down below
-                * when we handle the bad sectors.
-                */
 
-               /*
-                * If the command completed without error, then either
-                * finish off the rest of the command, or start a new one.
+               /* A number of bytes were successfully read.  If there
+                * is leftovers and there is some kind of error
+                * (result != 0), retry the rest.
                 */
-               if (scsi_end_request(cmd, 1, good_bytes, result == 0) == NULL)
+               if (scsi_end_request(cmd, 1, good_bytes, !!result) == NULL)
                        return;
        }
-       /*
-        * Now, if we were good little boys and girls, Santa left us a request
-        * sense buffer.  We can extract information from this, so we
-        * can choose a block to remap, etc.
+
+       /* good_bytes = 0, or (inclusive) there were leftovers and
+        * result = 0, so scsi_end_request couldn't retry.
         */
        if (sense_valid && !sense_deferred) {
                switch (sshdr.sense_key) {
                case UNIT_ATTENTION:
                        if (cmd->device->removable) {
-                               /* detected disc change.  set a bit 
+                               /* Detected disc change.  Set a bit
                                 * and quietly refuse further access.
                                 */
                                cmd->device->changed = 1;
-                               scsi_end_request(cmd, 0,
-                                               this_count, 1);
+                               scsi_end_request(cmd, 0, this_count, 1);
                                return;
                        } else {
-                               /*
-                               * Must have been a power glitch, or a
-                               * bus reset.  Could not have been a
-                               * media change, so we just retry the
-                               * request and see what happens.  
-                               */
+                               /* Must have been a power glitch, or a
+                                * bus reset.  Could not have been a
+                                * media change, so we just retry the
+                                * request and see what happens.
+                                */
                                scsi_requeue_command(q, cmd);
                                return;
                        }
                        break;
                case ILLEGAL_REQUEST:
-                       /*
-                       * If we had an ILLEGAL REQUEST returned, then we may
-                       * have performed an unsupported command.  The only
-                       * thing this should be would be a ten byte read where
-                       * only a six byte read was supported.  Also, on a
-                       * system where READ CAPACITY failed, we may have read
-                       * past the end of the disk.
-                       */
+                       /* If we had an ILLEGAL REQUEST returned, then
+                        * we may have performed an unsupported
+                        * command.  The only thing this should be
+                        * would be a ten byte read where only a six
+                        * byte read was supported.  Also, on a system
+                        * where READ CAPACITY failed, we may have
+                        * read past the end of the disk.
+                        */
                        if ((cmd->device->use_10_for_rw &&
                            sshdr.asc == 0x20 && sshdr.ascq == 0x00) &&
                            (cmd->cmnd[0] == READ_10 ||
                             cmd->cmnd[0] == WRITE_10)) {
                                cmd->device->use_10_for_rw = 0;
-                               /*
-                                * This will cause a retry with a 6-byte
-                                * command.
+                               /* This will cause a retry with a
+                                * 6-byte command.
                                 */
                                scsi_requeue_command(q, cmd);
-                               result = 0;
+                               return;
                        } else {
                                scsi_end_request(cmd, 0, this_count, 1);
                                return;
                        }
                        break;
                case NOT_READY:
-                       /*
-                        * If the device is in the process of becoming
+                       /* If the device is in the process of becoming
                         * ready, or has a temporary blockage, retry.
                         */
                        if (sshdr.asc == 0x04) {
@@ -1021,7 +1005,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
                        }
                        if (!(req->flags & REQ_QUIET)) {
                                scmd_printk(KERN_INFO, cmd,
-                                          "Device not ready: ");
+                                           "Device not ready: ");
                                scsi_print_sense_hdr("", &sshdr);
                        }
                        scsi_end_request(cmd, 0, this_count, 1);
@@ -1029,21 +1013,21 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
                case VOLUME_OVERFLOW:
                        if (!(req->flags & REQ_QUIET)) {
                                scmd_printk(KERN_INFO, cmd,
-                                          "Volume overflow, CDB: ");
+                                           "Volume overflow, CDB: ");
                                __scsi_print_command(cmd->data_cmnd);
                                scsi_print_sense("", cmd);
                        }
-                       scsi_end_request(cmd, 0, block_bytes, 1);
+                       /* See SSC3rXX or current. */
+                       scsi_end_request(cmd, 0, this_count, 1);
                        return;
                default:
                        break;
                }
-       }                       /* driver byte != 0 */
+       }
        if (host_byte(result) == DID_RESET) {
-               /*
-                * Third party bus reset or reset for error
-                * recovery reasons.  Just retry the request
-                * and see what happens.  
+               /* Third party bus reset or reset for error recovery
+                * reasons.  Just retry the request and see what
+                * happens.
                 */
                scsi_requeue_command(q, cmd);
                return;
@@ -1051,21 +1035,13 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
        if (result) {
                if (!(req->flags & REQ_QUIET)) {
                        scmd_printk(KERN_INFO, cmd,
-                                  "SCSI error: return code = 0x%x\n", result);
-
+                                   "SCSI error: return code = 0x%08x\n",
+                                   result);
                        if (driver_byte(result) & DRIVER_SENSE)
                                scsi_print_sense("", cmd);
                }
-               /*
-                * Mark a single buffer as not uptodate.  Queue the remainder.
-                * We sometimes get this cruft in the event that a medium error
-                * isn't properly reported.
-                */
-               block_bytes = req->hard_cur_sectors << 9;
-               if (!block_bytes)
-                       block_bytes = req->data_len;
-               scsi_end_request(cmd, 0, block_bytes, 1);
        }
+       scsi_end_request(cmd, 0, this_count, !result);
 }
 EXPORT_SYMBOL(scsi_io_completion);
 
@@ -1169,7 +1145,7 @@ static void scsi_blk_pc_done(struct scsi_cmnd *cmd)
         * successfully. Since this is a REQ_BLOCK_PC command the
         * caller should check the request's errors value
         */
-       scsi_io_completion(cmd, cmd->bufflen, 0);
+       scsi_io_completion(cmd, cmd->bufflen);
 }
 
 static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
@@ -2050,6 +2026,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
                switch (oldstate) {
                case SDEV_CREATED:
                case SDEV_RUNNING:
+               case SDEV_QUIESCE:
                case SDEV_OFFLINE:
                case SDEV_BLOCK:
                        break;
@@ -2060,6 +2037,9 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
 
        case SDEV_DEL:
                switch (oldstate) {
+               case SDEV_CREATED:
+               case SDEV_RUNNING:
+               case SDEV_OFFLINE:
                case SDEV_CANCEL:
                        break;
                default:
index a1727a0..117c233 100644 (file)
@@ -117,7 +117,7 @@ extern struct bus_type scsi_bus_type;
  * classes.
  */
 
-#define SCSI_DEVICE_BLOCK_MAX_TIMEOUT  (HZ*60)
+#define SCSI_DEVICE_BLOCK_MAX_TIMEOUT  600     /* units in seconds */
 extern int scsi_internal_device_block(struct scsi_device *sdev);
 extern int scsi_internal_device_unblock(struct scsi_device *sdev);
 
index d76e6e3..e1edab4 100644 (file)
@@ -2,7 +2,8 @@
 #define _SCSI_SAS_INTERNAL_H
 
 #define SAS_HOST_ATTRS         0
-#define SAS_PORT_ATTRS         17
+#define SAS_PHY_ATTRS          17
+#define SAS_PORT_ATTRS         1
 #define SAS_RPORT_ATTRS                7
 #define SAS_END_DEV_ATTRS      3
 #define SAS_EXPANDER_ATTRS     7
@@ -13,12 +14,14 @@ struct sas_internal {
        struct sas_domain_function_template *dft;
 
        struct class_device_attribute private_host_attrs[SAS_HOST_ATTRS];
-       struct class_device_attribute private_phy_attrs[SAS_PORT_ATTRS];
+       struct class_device_attribute private_phy_attrs[SAS_PHY_ATTRS];
+       struct class_device_attribute private_port_attrs[SAS_PORT_ATTRS];
        struct class_device_attribute private_rphy_attrs[SAS_RPORT_ATTRS];
        struct class_device_attribute private_end_dev_attrs[SAS_END_DEV_ATTRS];
        struct class_device_attribute private_expander_attrs[SAS_EXPANDER_ATTRS];
 
        struct transport_container phy_attr_cont;
+       struct transport_container port_attr_cont;
        struct transport_container rphy_attr_cont;
        struct transport_container end_dev_attr_cont;
        struct transport_container expander_attr_cont;
@@ -28,7 +31,8 @@ struct sas_internal {
         * needed by scsi_sysfs.c
         */
        struct class_device_attribute *host_attrs[SAS_HOST_ATTRS + 1];
-       struct class_device_attribute *phy_attrs[SAS_PORT_ATTRS + 1];
+       struct class_device_attribute *phy_attrs[SAS_PHY_ATTRS + 1];
+       struct class_device_attribute *port_attrs[SAS_PORT_ATTRS + 1];
        struct class_device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1];
        struct class_device_attribute *end_dev_attrs[SAS_END_DEV_ATTRS + 1];
        struct class_device_attribute *expander_attrs[SAS_EXPANDER_ATTRS + 1];
index 0f7e6f9..4c31799 100644 (file)
@@ -810,6 +810,7 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
 
 static inline void scsi_destroy_sdev(struct scsi_device *sdev)
 {
+       scsi_device_set_state(sdev, SDEV_DEL);
        if (sdev->host->hostt->slave_destroy)
                sdev->host->hostt->slave_destroy(sdev);
        transport_destroy_device(&sdev->sdev_gendev);
index f2db7a4..b03aa85 100644 (file)
@@ -368,7 +368,7 @@ static DECLARE_TRANSPORT_CLASS(fc_rport_class,
  *   should insulate the loss of a remote port.
  *   The maximum will be capped by the value of SCSI_DEVICE_BLOCK_MAX_TIMEOUT.
  */
-static unsigned int fc_dev_loss_tmo = SCSI_DEVICE_BLOCK_MAX_TIMEOUT;
+static unsigned int fc_dev_loss_tmo = 60;              /* seconds */
 
 module_param_named(dev_loss_tmo, fc_dev_loss_tmo, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(dev_loss_tmo,
@@ -1284,7 +1284,9 @@ EXPORT_SYMBOL(fc_release_transport);
  * @work:      Work to queue for execution.
  *
  * Return value:
- *     0 on success / != 0 for error
+ *     1 - work queued for execution
+ *     0 - work is already queued
+ *     -EINVAL - work queue doesn't exist
  **/
 static int
 fc_queue_work(struct Scsi_Host *shost, struct work_struct *work)
@@ -1434,8 +1436,6 @@ fc_starget_delete(void *data)
        struct Scsi_Host *shost = rport_to_shost(rport);
        unsigned long flags;
 
-       scsi_target_unblock(&rport->dev);
-
        spin_lock_irqsave(shost->host_lock, flags);
        if (rport->flags & FC_RPORT_DEVLOSS_PENDING) {
                spin_unlock_irqrestore(shost->host_lock, flags);
@@ -1476,7 +1476,8 @@ fc_rport_final_delete(void *data)
        transport_remove_device(dev);
        device_del(dev);
        transport_destroy_device(dev);
-       put_device(&shost->shost_gendev);
+       put_device(&shost->shost_gendev);       /* for fc_host->rport list */
+       put_device(dev);                        /* for self-reference */
 }
 
 
@@ -1537,13 +1538,13 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
        else
                rport->scsi_target_id = -1;
        list_add_tail(&rport->peers, &fc_host->rports);
-       get_device(&shost->shost_gendev);
+       get_device(&shost->shost_gendev);       /* for fc_host->rport list */
 
        spin_unlock_irqrestore(shost->host_lock, flags);
 
        dev = &rport->dev;
-       device_initialize(dev);
-       dev->parent = get_device(&shost->shost_gendev);
+       device_initialize(dev);                 /* takes self reference */
+       dev->parent = get_device(&shost->shost_gendev); /* parent reference */
        dev->release = fc_rport_dev_release;
        sprintf(dev->bus_id, "rport-%d:%d-%d",
                shost->host_no, channel, rport->number);
@@ -1567,10 +1568,9 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
 
 delete_rport:
        transport_destroy_device(dev);
-       put_device(dev->parent);
        spin_lock_irqsave(shost->host_lock, flags);
        list_del(&rport->peers);
-       put_device(&shost->shost_gendev);
+       put_device(&shost->shost_gendev);       /* for fc_host->rport list */
        spin_unlock_irqrestore(shost->host_lock, flags);
        put_device(dev->parent);
        kfree(rport);
@@ -1707,6 +1707,8 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
 
                                spin_unlock_irqrestore(shost->host_lock, flags);
 
+                               scsi_target_unblock(&rport->dev);
+
                                return rport;
                        }
                }
@@ -1762,9 +1764,10 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
                                /* initiate a scan of the target */
                                rport->flags |= FC_RPORT_SCAN_PENDING;
                                scsi_queue_work(shost, &rport->scan_work);
-                       }
-
-                       spin_unlock_irqrestore(shost->host_lock, flags);
+                               spin_unlock_irqrestore(shost->host_lock, flags);
+                               scsi_target_unblock(&rport->dev);
+                       } else
+                               spin_unlock_irqrestore(shost->host_lock, flags);
 
                        return rport;
                }
@@ -1938,6 +1941,7 @@ fc_remote_port_rolechg(struct fc_rport  *rport, u32 roles)
                rport->flags |= FC_RPORT_SCAN_PENDING;
                scsi_queue_work(shost, &rport->scan_work);
                spin_unlock_irqrestore(shost->host_lock, flags);
+               scsi_target_unblock(&rport->dev);
        }
 }
 EXPORT_SYMBOL(fc_remote_port_rolechg);
@@ -1970,8 +1974,9 @@ fc_timeout_deleted_rport(void  *data)
                dev_printk(KERN_ERR, &rport->dev,
                        "blocked FC remote port time out: no longer"
                        " a FCP target, removing starget\n");
-               fc_queue_work(shost, &rport->stgt_delete_work);
                spin_unlock_irqrestore(shost->host_lock, flags);
+               scsi_target_unblock(&rport->dev);
+               fc_queue_work(shost, &rport->stgt_delete_work);
                return;
        }
 
@@ -2035,17 +2040,15 @@ fc_timeout_deleted_rport(void  *data)
         * went away and didn't come back - we'll remove
         * all attached scsi devices.
         */
-       fc_queue_work(shost, &rport->stgt_delete_work);
-
        spin_unlock_irqrestore(shost->host_lock, flags);
+
+       scsi_target_unblock(&rport->dev);
+       fc_queue_work(shost, &rport->stgt_delete_work);
 }
 
 /**
  * fc_scsi_scan_rport - called to perform a scsi scan on a remote port.
  *
- * Will unblock the target (in case it went away and has now come back),
- * then invoke a scan.
- *
  * @data:      remote port to be scanned.
  **/
 static void
@@ -2057,7 +2060,6 @@ fc_scsi_scan_rport(void *data)
 
        if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
            (rport->roles & FC_RPORT_ROLE_FCP_TARGET)) {
-               scsi_target_unblock(&rport->dev);
                scsi_scan_target(&rport->dev, rport->channel,
                        rport->scsi_target_id, SCAN_WILD_CARD, 1);
        }
index 1fe6b2d..dd07562 100644 (file)
@@ -174,11 +174,28 @@ static int sas_host_match(struct attribute_container *cont,
 
 static int do_sas_phy_delete(struct device *dev, void *data)
 {
-       if (scsi_is_sas_phy(dev))
+       int pass = (int)(unsigned long)data;
+
+       if (pass == 0 && scsi_is_sas_port(dev))
+               sas_port_delete(dev_to_sas_port(dev));
+       else if (pass == 1 && scsi_is_sas_phy(dev))
                sas_phy_delete(dev_to_phy(dev));
        return 0;
 }
 
+/**
+ * sas_remove_children  --  tear down a devices SAS data structures
+ * @dev:       device belonging to the sas object
+ *
+ * Removes all SAS PHYs and remote PHYs for a given object
+ */
+void sas_remove_children(struct device *dev)
+{
+       device_for_each_child(dev, (void *)0, do_sas_phy_delete);
+       device_for_each_child(dev, (void *)1, do_sas_phy_delete);
+}
+EXPORT_SYMBOL(sas_remove_children);
+
 /**
  * sas_remove_host  --  tear down a Scsi_Host's SAS data structures
  * @shost:     Scsi Host that is torn down
@@ -188,13 +205,13 @@ static int do_sas_phy_delete(struct device *dev, void *data)
  */
 void sas_remove_host(struct Scsi_Host *shost)
 {
-       device_for_each_child(&shost->shost_gendev, NULL, do_sas_phy_delete);
+       sas_remove_children(&shost->shost_gendev);
 }
 EXPORT_SYMBOL(sas_remove_host);
 
 
 /*
- * SAS Port attributes
+ * SAS Phy attributes
  */
 
 #define sas_phy_show_simple(field, name, format_string, cast)          \
@@ -310,7 +327,7 @@ sas_phy_protocol_attr(identify.target_port_protocols,
 sas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",
                unsigned long long);
 sas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
-sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", u8);
+//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", u8);
 sas_phy_linkspeed_attr(negotiated_linkrate);
 sas_phy_linkspeed_attr(minimum_linkrate_hw);
 sas_phy_linkspeed_attr(minimum_linkrate);
@@ -378,9 +395,10 @@ struct sas_phy *sas_phy_alloc(struct device *parent, int number)
        device_initialize(&phy->dev);
        phy->dev.parent = get_device(parent);
        phy->dev.release = sas_phy_release;
+       INIT_LIST_HEAD(&phy->port_siblings);
        if (scsi_is_sas_expander_device(parent)) {
                struct sas_rphy *rphy = dev_to_rphy(parent);
-               sprintf(phy->dev.bus_id, "phy-%d-%d:%d", shost->host_no,
+               sprintf(phy->dev.bus_id, "phy-%d:%d:%d", shost->host_no,
                        rphy->scsi_target_id, number);
        } else
                sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number);
@@ -440,8 +458,8 @@ sas_phy_delete(struct sas_phy *phy)
 {
        struct device *dev = &phy->dev;
 
-       if (phy->rphy)
-               sas_rphy_delete(phy->rphy);
+       /* this happens if the phy is still part of a port when deleted */
+       BUG_ON(!list_empty(&phy->port_siblings));
 
        transport_remove_device(dev);
        device_del(dev);
@@ -463,6 +481,258 @@ int scsi_is_sas_phy(const struct device *dev)
 }
 EXPORT_SYMBOL(scsi_is_sas_phy);
 
+/*
+ * SAS Port attributes
+ */
+#define sas_port_show_simple(field, name, format_string, cast)         \
+static ssize_t                                                         \
+show_sas_port_##name(struct class_device *cdev, char *buf)             \
+{                                                                      \
+       struct sas_port *port = transport_class_to_sas_port(cdev);      \
+                                                                       \
+       return snprintf(buf, 20, format_string, cast port->field);      \
+}
+
+#define sas_port_simple_attr(field, name, format_string, type)         \
+       sas_port_show_simple(field, name, format_string, (type))        \
+static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL)
+
+sas_port_simple_attr(num_phys, num_phys, "%d\n", int);
+
+static DECLARE_TRANSPORT_CLASS(sas_port_class,
+                              "sas_port", NULL, NULL, NULL);
+
+static int sas_port_match(struct attribute_container *cont, struct device *dev)
+{
+       struct Scsi_Host *shost;
+       struct sas_internal *i;
+
+       if (!scsi_is_sas_port(dev))
+               return 0;
+       shost = dev_to_shost(dev->parent);
+
+       if (!shost->transportt)
+               return 0;
+       if (shost->transportt->host_attrs.ac.class !=
+                       &sas_host_class.class)
+               return 0;
+
+       i = to_sas_internal(shost->transportt);
+       return &i->port_attr_cont.ac == cont;
+}
+
+
+static void sas_port_release(struct device *dev)
+{
+       struct sas_port *port = dev_to_sas_port(dev);
+
+       BUG_ON(!list_empty(&port->phy_list));
+
+       put_device(dev->parent);
+       kfree(port);
+}
+
+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");
+}
+
+static void sas_port_delete_link(struct sas_port *port,
+                                struct sas_phy *phy)
+{
+       sysfs_remove_link(&port->dev.kobj, phy->dev.bus_id);
+       sysfs_remove_link(&phy->dev.kobj, "port");
+}
+
+/** sas_port_alloc - allocate and initialize a SAS port structure
+ *
+ * @parent:    parent device
+ * @port_id:   port number
+ *
+ * Allocates a SAS port structure.  It will be added to the device tree
+ * below the device specified by @parent which must be either a Scsi_Host
+ * or a sas_expander_device.
+ *
+ * Returns %NULL on error
+ */
+struct sas_port *sas_port_alloc(struct device *parent, int port_id)
+{
+       struct Scsi_Host *shost = dev_to_shost(parent);
+       struct sas_port *port;
+
+       port = kzalloc(sizeof(*port), GFP_KERNEL);
+       if (!port)
+               return NULL;
+
+       port->port_identifier = port_id;
+
+       device_initialize(&port->dev);
+
+       port->dev.parent = get_device(parent);
+       port->dev.release = sas_port_release;
+
+       mutex_init(&port->phy_list_mutex);
+       INIT_LIST_HEAD(&port->phy_list);
+
+       if (scsi_is_sas_expander_device(parent)) {
+               struct sas_rphy *rphy = dev_to_rphy(parent);
+               sprintf(port->dev.bus_id, "port-%d:%d:%d", shost->host_no,
+                       rphy->scsi_target_id, port->port_identifier);
+       } else
+               sprintf(port->dev.bus_id, "port-%d:%d", shost->host_no,
+                       port->port_identifier);
+
+       transport_setup_device(&port->dev);
+
+       return port;
+}
+EXPORT_SYMBOL(sas_port_alloc);
+
+/**
+ * sas_port_add - add a SAS port to the device hierarchy
+ *
+ * @port:      port to be added
+ *
+ * publishes a port to the rest of the system
+ */
+int sas_port_add(struct sas_port *port)
+{
+       int error;
+
+       /* No phys should be added until this is made visible */
+       BUG_ON(!list_empty(&port->phy_list));
+
+       error = device_add(&port->dev);
+
+       if (error)
+               return error;
+
+       transport_add_device(&port->dev);
+       transport_configure_device(&port->dev);
+
+       return 0;
+}
+EXPORT_SYMBOL(sas_port_add);
+
+/**
+ * sas_port_free  --  free a SAS PORT
+ * @port:      SAS PORT to free
+ *
+ * Frees the specified SAS PORT.
+ *
+ * Note:
+ *   This function must only be called on a PORT that has not
+ *   sucessfully been added using sas_port_add().
+ */
+void sas_port_free(struct sas_port *port)
+{
+       transport_destroy_device(&port->dev);
+       put_device(&port->dev);
+}
+EXPORT_SYMBOL(sas_port_free);
+
+/**
+ * sas_port_delete  --  remove SAS PORT
+ * @port:      SAS PORT to remove
+ *
+ * Removes the specified SAS PORT.  If the SAS PORT has an
+ * associated phys, unlink them from the port as well.
+ */
+void sas_port_delete(struct sas_port *port)
+{
+       struct device *dev = &port->dev;
+       struct sas_phy *phy, *tmp_phy;
+
+       if (port->rphy) {
+               sas_rphy_delete(port->rphy);
+               port->rphy = NULL;
+       }
+
+       mutex_lock(&port->phy_list_mutex);
+       list_for_each_entry_safe(phy, tmp_phy, &port->phy_list,
+                                port_siblings) {
+               sas_port_delete_link(port, phy);
+               list_del_init(&phy->port_siblings);
+       }
+       mutex_unlock(&port->phy_list_mutex);
+
+       transport_remove_device(dev);
+       device_del(dev);
+       transport_destroy_device(dev);
+       put_device(dev);
+}
+EXPORT_SYMBOL(sas_port_delete);
+
+/**
+ * scsi_is_sas_port --  check if a struct device represents a SAS port
+ * @dev:       device to check
+ *
+ * Returns:
+ *     %1 if the device represents a SAS Port, %0 else
+ */
+int scsi_is_sas_port(const struct device *dev)
+{
+       return dev->release == sas_port_release;
+}
+EXPORT_SYMBOL(scsi_is_sas_port);
+
+/**
+ * sas_port_add_phy - add another phy to a port to form a wide port
+ * @port:      port to add the phy to
+ * @phy:       phy to add
+ *
+ * When a port is initially created, it is empty (has no phys).  All
+ * ports must have at least one phy to operated, and all wide ports
+ * must have at least two.  The current code makes no difference
+ * between ports and wide ports, but the only object that can be
+ * connected to a remote device is a port, so ports must be formed on
+ * all devices with phys if they're connected to anything.
+ */
+void sas_port_add_phy(struct sas_port *port, struct sas_phy *phy)
+{
+       mutex_lock(&port->phy_list_mutex);
+       if (unlikely(!list_empty(&phy->port_siblings))) {
+               /* make sure we're already on this port */
+               struct sas_phy *tmp;
+
+               list_for_each_entry(tmp, &port->phy_list, port_siblings)
+                       if (tmp == phy)
+                               break;
+               /* If this trips, you added a phy that was already
+                * part of a different port */
+               if (unlikely(tmp != phy)) {
+                       dev_printk(KERN_ERR, &port->dev, "trying to add phy %s fails: it's already part of another port\n", phy->dev.bus_id);
+                       BUG();
+               }
+       } else {
+               sas_port_create_link(port, phy);
+               list_add_tail(&phy->port_siblings, &port->phy_list);
+               port->num_phys++;
+       }
+       mutex_unlock(&port->phy_list_mutex);
+}
+EXPORT_SYMBOL(sas_port_add_phy);
+
+/**
+ * sas_port_delete_phy - remove a phy from a port or wide port
+ * @port:      port to remove the phy from
+ * @phy:       phy to remove
+ *
+ * This operation is used for tearing down ports again.  It must be
+ * done to every port or wide port before calling sas_port_delete.
+ */
+void sas_port_delete_phy(struct sas_port *port, struct sas_phy *phy)
+{
+       mutex_lock(&port->phy_list_mutex);
+       sas_port_delete_link(port, phy);
+       list_del_init(&phy->port_siblings);
+       port->num_phys--;
+       mutex_unlock(&port->phy_list_mutex);
+}
+EXPORT_SYMBOL(sas_port_delete_phy);
+
 /*
  * SAS remote PHY attributes.
  */
@@ -767,7 +1037,7 @@ static void sas_rphy_initialize(struct sas_rphy *rphy)
  * Returns:
  *     SAS PHY allocated or %NULL if the allocation failed.
  */
-struct sas_rphy *sas_end_device_alloc(struct sas_phy *parent)
+struct sas_rphy *sas_end_device_alloc(struct sas_port *parent)
 {
        struct Scsi_Host *shost = dev_to_shost(&parent->dev);
        struct sas_end_device *rdev;
@@ -780,8 +1050,13 @@ struct sas_rphy *sas_end_device_alloc(struct sas_phy *parent)
        device_initialize(&rdev->rphy.dev);
        rdev->rphy.dev.parent = get_device(&parent->dev);
        rdev->rphy.dev.release = sas_end_device_release;
-       sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d-%d",
-               shost->host_no, parent->port_identifier, parent->number);
+       if (scsi_is_sas_expander_device(parent->dev.parent)) {
+               struct sas_rphy *rphy = dev_to_rphy(parent->dev.parent);
+               sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d:%d",
+                       shost->host_no, rphy->scsi_target_id, parent->port_identifier);
+       } else
+               sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d",
+                       shost->host_no, parent->port_identifier);
        rdev->rphy.identify.device_type = SAS_END_DEVICE;
        sas_rphy_initialize(&rdev->rphy);
        transport_setup_device(&rdev->rphy.dev);
@@ -798,7 +1073,7 @@ EXPORT_SYMBOL(sas_end_device_alloc);
  * Returns:
  *     SAS PHY allocated or %NULL if the allocation failed.
  */
-struct sas_rphy *sas_expander_alloc(struct sas_phy *parent,
+struct sas_rphy *sas_expander_alloc(struct sas_port *parent,
                                    enum sas_device_type type)
 {
        struct Scsi_Host *shost = dev_to_shost(&parent->dev);
@@ -837,7 +1112,7 @@ EXPORT_SYMBOL(sas_expander_alloc);
  */
 int sas_rphy_add(struct sas_rphy *rphy)
 {
-       struct sas_phy *parent = dev_to_phy(rphy->dev.parent);
+       struct sas_port *parent = dev_to_sas_port(rphy->dev.parent);
        struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);
        struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
        struct sas_identify *identify = &rphy->identify;
@@ -910,7 +1185,7 @@ void
 sas_rphy_delete(struct sas_rphy *rphy)
 {
        struct device *dev = &rphy->dev;
-       struct sas_phy *parent = dev_to_phy(dev->parent);
+       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);
 
@@ -920,7 +1195,7 @@ sas_rphy_delete(struct sas_rphy *rphy)
                break;
        case SAS_EDGE_EXPANDER_DEVICE:
        case SAS_FANOUT_EXPANDER_DEVICE:
-               device_for_each_child(dev, NULL, do_sas_phy_delete);
+               sas_remove_children(dev);
                break;
        default:
                break;
@@ -967,7 +1242,7 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
 
        mutex_lock(&sas_host->lock);
        list_for_each_entry(rphy, &sas_host->rphy_list, list) {
-               struct sas_phy *parent = dev_to_phy(rphy->dev.parent);
+               struct sas_port *parent = dev_to_sas_port(rphy->dev.parent);
 
                if (rphy->identify.device_type != SAS_END_DEVICE ||
                    rphy->scsi_target_id == -1)
@@ -1003,16 +1278,19 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
 #define SETUP_OPTIONAL_RPORT_ATTRIBUTE(field, func)                    \
        SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, i->f->func)
 
-#define SETUP_PORT_ATTRIBUTE(field)                                    \
+#define SETUP_PHY_ATTRIBUTE(field)                                     \
        SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1)
 
-#define SETUP_OPTIONAL_PORT_ATTRIBUTE(field, func)                     \
+#define SETUP_PORT_ATTRIBUTE(field)                                    \
+       SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1)
+
+#define SETUP_OPTIONAL_PHY_ATTRIBUTE(field, func)                      \
        SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func)
 
-#define SETUP_PORT_ATTRIBUTE_WRONLY(field)                             \
+#define SETUP_PHY_ATTRIBUTE_WRONLY(field)                              \
        SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, 1)
 
-#define SETUP_OPTIONAL_PORT_ATTRIBUTE_WRONLY(field, func)              \
+#define SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(field, func)               \
        SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, i->f->func)
 
 #define SETUP_END_DEV_ATTRIBUTE(field)                                 \
@@ -1048,6 +1326,11 @@ sas_attach_transport(struct sas_function_template *ft)
        i->phy_attr_cont.ac.match = sas_phy_match;
        transport_container_register(&i->phy_attr_cont);
 
+       i->port_attr_cont.ac.class = &sas_port_class.class;
+       i->port_attr_cont.ac.attrs = &i->port_attrs[0];
+       i->port_attr_cont.ac.match = sas_port_match;
+       transport_container_register(&i->port_attr_cont);
+
        i->rphy_attr_cont.ac.class = &sas_rphy_class.class;
        i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0];
        i->rphy_attr_cont.ac.match = sas_rphy_match;
@@ -1066,29 +1349,34 @@ sas_attach_transport(struct sas_function_template *ft)
        i->f = ft;
 
        count = 0;
+       SETUP_PORT_ATTRIBUTE(num_phys);
        i->host_attrs[count] = NULL;
 
        count = 0;
-       SETUP_PORT_ATTRIBUTE(initiator_port_protocols);
-       SETUP_PORT_ATTRIBUTE(target_port_protocols);
-       SETUP_PORT_ATTRIBUTE(device_type);
-       SETUP_PORT_ATTRIBUTE(sas_address);
-       SETUP_PORT_ATTRIBUTE(phy_identifier);
-       SETUP_PORT_ATTRIBUTE(port_identifier);
-       SETUP_PORT_ATTRIBUTE(negotiated_linkrate);
-       SETUP_PORT_ATTRIBUTE(minimum_linkrate_hw);
-       SETUP_PORT_ATTRIBUTE(minimum_linkrate);
-       SETUP_PORT_ATTRIBUTE(maximum_linkrate_hw);
-       SETUP_PORT_ATTRIBUTE(maximum_linkrate);
-
-       SETUP_PORT_ATTRIBUTE(invalid_dword_count);
-       SETUP_PORT_ATTRIBUTE(running_disparity_error_count);
-       SETUP_PORT_ATTRIBUTE(loss_of_dword_sync_count);
-       SETUP_PORT_ATTRIBUTE(phy_reset_problem_count);
-       SETUP_OPTIONAL_PORT_ATTRIBUTE_WRONLY(link_reset, phy_reset);
-       SETUP_OPTIONAL_PORT_ATTRIBUTE_WRONLY(hard_reset, phy_reset);
+       SETUP_PHY_ATTRIBUTE(initiator_port_protocols);
+       SETUP_PHY_ATTRIBUTE(target_port_protocols);
+       SETUP_PHY_ATTRIBUTE(device_type);
+       SETUP_PHY_ATTRIBUTE(sas_address);
+       SETUP_PHY_ATTRIBUTE(phy_identifier);
+       //SETUP_PHY_ATTRIBUTE(port_identifier);
+       SETUP_PHY_ATTRIBUTE(negotiated_linkrate);
+       SETUP_PHY_ATTRIBUTE(minimum_linkrate_hw);
+       SETUP_PHY_ATTRIBUTE(minimum_linkrate);
+       SETUP_PHY_ATTRIBUTE(maximum_linkrate_hw);
+       SETUP_PHY_ATTRIBUTE(maximum_linkrate);
+
+       SETUP_PHY_ATTRIBUTE(invalid_dword_count);
+       SETUP_PHY_ATTRIBUTE(running_disparity_error_count);
+       SETUP_PHY_ATTRIBUTE(loss_of_dword_sync_count);
+       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);
        i->phy_attrs[count] = NULL;
 
+       count = 0;
+       SETUP_PORT_ATTRIBUTE(num_phys);
+       i->port_attrs[count] = NULL;
+
        count = 0;
        SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols);
        SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols);
@@ -1131,6 +1419,7 @@ void sas_release_transport(struct scsi_transport_template *t)
 
        transport_container_unregister(&i->t.host_attrs);
        transport_container_unregister(&i->phy_attr_cont);
+       transport_container_unregister(&i->port_attr_cont);
        transport_container_unregister(&i->rphy_attr_cont);
        transport_container_unregister(&i->end_dev_attr_cont);
        transport_container_unregister(&i->expander_attr_cont);
@@ -1149,9 +1438,12 @@ static __init int sas_transport_init(void)
        error = transport_class_register(&sas_phy_class);
        if (error)
                goto out_unregister_transport;
-       error = transport_class_register(&sas_rphy_class);
+       error = transport_class_register(&sas_port_class);
        if (error)
                goto out_unregister_phy;
+       error = transport_class_register(&sas_rphy_class);
+       if (error)
+               goto out_unregister_port;
        error = transport_class_register(&sas_end_dev_class);
        if (error)
                goto out_unregister_rphy;
@@ -1165,6 +1457,8 @@ static __init int sas_transport_init(void)
        transport_class_unregister(&sas_end_dev_class);
  out_unregister_rphy:
        transport_class_unregister(&sas_rphy_class);
+ out_unregister_port:
+       transport_class_unregister(&sas_port_class);
  out_unregister_phy:
        transport_class_unregister(&sas_phy_class);
  out_unregister_transport:
@@ -1178,6 +1472,7 @@ static void __exit sas_transport_exit(void)
 {
        transport_class_unregister(&sas_host_class);
        transport_class_unregister(&sas_phy_class);
+       transport_class_unregister(&sas_port_class);
        transport_class_unregister(&sas_rphy_class);
        transport_class_unregister(&sas_end_dev_class);
        transport_class_unregister(&sas_expander_class);
index b78354f..cd68a66 100644 (file)
@@ -57,6 +57,7 @@ EXPORT_SYMBOL(scsi_bios_ptable);
 int scsicam_bios_param(struct block_device *bdev, sector_t capacity, int *ip)
 {
        unsigned char *p;
+       u64 capacity64 = capacity;      /* Suppress gcc warning */
        int ret;
 
        p = scsi_bios_ptable(bdev);
@@ -68,7 +69,7 @@ int scsicam_bios_param(struct block_device *bdev, sector_t capacity, int *ip)
                               (unsigned int *)ip + 0, (unsigned int *)ip + 1);
        kfree(p);
 
-       if (ret == -1) {
+       if (ret == -1 && capacity64 < (1ULL << 32)) {
                /* pick some standard mapping with at most 1024 cylinders,
                   and at most 62 sectors per track - this works up to
                   7905 MB */
index 3541990..2e96c3d 100644 (file)
@@ -208,6 +208,23 @@ static ssize_t sd_store_cache_type(struct class_device *cdev, const char *buf,
        return count;
 }
 
+static ssize_t sd_store_allow_restart(struct class_device *cdev, const char *buf,
+                                     size_t count)
+{
+       struct scsi_disk *sdkp = to_scsi_disk(cdev);
+       struct scsi_device *sdp = sdkp->device;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
+
+       if (sdp->type != TYPE_DISK)
+               return -EINVAL;
+
+       sdp->allow_restart = simple_strtoul(buf, NULL, 10);
+
+       return count;
+}
+
 static ssize_t sd_show_cache_type(struct class_device *cdev, char *buf)
 {
        struct scsi_disk *sdkp = to_scsi_disk(cdev);
@@ -223,10 +240,19 @@ static ssize_t sd_show_fua(struct class_device *cdev, char *buf)
        return snprintf(buf, 20, "%u\n", sdkp->DPOFUA);
 }
 
+static ssize_t sd_show_allow_restart(struct class_device *cdev, char *buf)
+{
+       struct scsi_disk *sdkp = to_scsi_disk(cdev);
+
+       return snprintf(buf, 40, "%d\n", sdkp->device->allow_restart);
+}
+
 static struct class_device_attribute sd_disk_attrs[] = {
        __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type,
               sd_store_cache_type),
        __ATTR(FUA, S_IRUGO, sd_show_fua, NULL),
+       __ATTR(allow_restart, S_IRUGO|S_IWUSR, sd_show_allow_restart,
+              sd_store_allow_restart),
        __ATTR_NULL,
 };
 
@@ -891,11 +917,10 @@ static struct block_device_operations sd_fops = {
 static void sd_rw_intr(struct scsi_cmnd * SCpnt)
 {
        int result = SCpnt->result;
-       int this_count = SCpnt->request_bufflen;
-       int good_bytes = (result == 0 ? this_count : 0);
-       sector_t block_sectors = 1;
-       u64 first_err_block;
-       sector_t error_sector;
+       unsigned int xfer_size = SCpnt->request_bufflen;
+       unsigned int good_bytes = result ? 0 : xfer_size;
+       u64 start_lba = SCpnt->request->sector;
+       u64 bad_lba;
        struct scsi_sense_hdr sshdr;
        int sense_valid = 0;
        int sense_deferred = 0;
@@ -906,7 +931,6 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt)
                if (sense_valid)
                        sense_deferred = scsi_sense_is_deferred(&sshdr);
        }
-
 #ifdef CONFIG_SCSI_LOGGING
        SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: %s: res=0x%x\n", 
                                SCpnt->request->rq_disk->disk_name, result));
@@ -916,89 +940,72 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt)
                                sshdr.sense_key, sshdr.asc, sshdr.ascq));
        }
 #endif
-       /*
-          Handle MEDIUM ERRORs that indicate partial success.  Since this is a
-          relatively rare error condition, no care is taken to avoid
-          unnecessary additional work such as memcpy's that could be avoided.
-        */
-       if (driver_byte(result) != 0 &&
-                sense_valid && !sense_deferred) {
-               switch (sshdr.sense_key) {
-               case MEDIUM_ERROR:
-                       if (!blk_fs_request(SCpnt->request))
-                               break;
-                       info_valid = scsi_get_sense_info_fld(
-                               SCpnt->sense_buffer, SCSI_SENSE_BUFFERSIZE,
-                               &first_err_block);
-                       /*
-                        * May want to warn and skip if following cast results
-                        * in actual truncation (if sector_t < 64 bits)
-                        */
-                       error_sector = (sector_t)first_err_block;
-                       if (SCpnt->request->bio != NULL)
-                               block_sectors = bio_sectors(SCpnt->request->bio);
-                       switch (SCpnt->device->sector_size) {
-                       case 1024:
-                               error_sector <<= 1;
-                               if (block_sectors < 2)
-                                       block_sectors = 2;
-                               break;
-                       case 2048:
-                               error_sector <<= 2;
-                               if (block_sectors < 4)
-                                       block_sectors = 4;
-                               break;
-                       case 4096:
-                               error_sector <<=3;
-                               if (block_sectors < 8)
-                                       block_sectors = 8;
-                               break;
-                       case 256:
-                               error_sector >>= 1;
-                               break;
-                       default:
-                               break;
-                       }
+       if (driver_byte(result) != DRIVER_SENSE &&
+           (!sense_valid || sense_deferred))
+               goto out;
 
-                       error_sector &= ~(block_sectors - 1);
-                       good_bytes = (error_sector - SCpnt->request->sector) << 9;
-                       if (good_bytes < 0 || good_bytes >= this_count)
-                               good_bytes = 0;
+       switch (sshdr.sense_key) {
+       case HARDWARE_ERROR:
+       case MEDIUM_ERROR:
+               if (!blk_fs_request(SCpnt->request))
+                       goto out;
+               info_valid = scsi_get_sense_info_fld(SCpnt->sense_buffer,
+                                                    SCSI_SENSE_BUFFERSIZE,
+                                                    &bad_lba);
+               if (!info_valid)
+                       goto out;
+               if (xfer_size <= SCpnt->device->sector_size)
+                       goto out;
+               switch (SCpnt->device->sector_size) {
+               case 256:
+                       start_lba <<= 1;
                        break;
-
-               case RECOVERED_ERROR: /* an error occurred, but it recovered */
-               case NO_SENSE: /* LLDD got sense data */
-                       /*
-                        * Inform the user, but make sure that it's not treated
-                        * as a hard error.
-                        */
-                       scsi_print_sense("sd", SCpnt);
-                       SCpnt->result = 0;
-                       memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
-                       good_bytes = this_count;
+               case 512:
                        break;
-
-               case ILLEGAL_REQUEST:
-                       if (SCpnt->device->use_10_for_rw &&
-                           (SCpnt->cmnd[0] == READ_10 ||
-                            SCpnt->cmnd[0] == WRITE_10))
-                               SCpnt->device->use_10_for_rw = 0;
-                       if (SCpnt->device->use_10_for_ms &&
-                           (SCpnt->cmnd[0] == MODE_SENSE_10 ||
-                            SCpnt->cmnd[0] == MODE_SELECT_10))
-                               SCpnt->device->use_10_for_ms = 0;
+               case 1024:
+                       start_lba >>= 1;
+                       break;
+               case 2048:
+                       start_lba >>= 2;
+                       break;
+               case 4096:
+                       start_lba >>= 3;
                        break;
-
                default:
+                       /* Print something here with limiting frequency. */
+                       goto out;
                        break;
                }
+               /* This computation should always be done in terms of
+                * the resolution of the device's medium.
+                */
+               good_bytes = (bad_lba - start_lba)*SCpnt->device->sector_size;
+               break;
+       case RECOVERED_ERROR:
+       case NO_SENSE:
+               /* Inform the user, but make sure that it's not treated
+                * as a hard error.
+                */
+               scsi_print_sense("sd", SCpnt);
+               SCpnt->result = 0;
+               memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+               good_bytes = xfer_size;
+               break;
+       case ILLEGAL_REQUEST:
+               if (SCpnt->device->use_10_for_rw &&
+                   (SCpnt->cmnd[0] == READ_10 ||
+                    SCpnt->cmnd[0] == WRITE_10))
+                       SCpnt->device->use_10_for_rw = 0;
+               if (SCpnt->device->use_10_for_ms &&
+                   (SCpnt->cmnd[0] == MODE_SENSE_10 ||
+                    SCpnt->cmnd[0] == MODE_SELECT_10))
+                       SCpnt->device->use_10_for_ms = 0;
+               break;
+       default:
+               break;
        }
-       /*
-        * This calls the generic completion function, now that we know
-        * how many actual sectors finished, and how many sectors we need
-        * to say have failed.
-        */
-       scsi_io_completion(SCpnt, good_bytes, block_sectors << 9);
+ out:
+       scsi_io_completion(SCpnt, good_bytes);
 }
 
 static int media_not_present(struct scsi_disk *sdkp,
index ebf6579..fd94408 100644 (file)
@@ -292,7 +292,7 @@ static void rw_intr(struct scsi_cmnd * SCpnt)
         * how many actual sectors finished, and how many sectors we need
         * to say have failed.
         */
-       scsi_io_completion(SCpnt, good_bytes, block_sectors << 9);
+       scsi_io_completion(SCpnt, good_bytes);
 }
 
 static int sr_init_command(struct scsi_cmnd * SCpnt)
index e46cd40..371f70d 100644 (file)
@@ -143,7 +143,7 @@ struct scsi_cmnd {
 
 extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t);
 extern void scsi_put_command(struct scsi_cmnd *);
-extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int);
+extern void scsi_io_completion(struct scsi_cmnd *, unsigned int);
 extern void scsi_finish_command(struct scsi_cmnd *cmd);
 extern void scsi_req_abort_cmd(struct scsi_cmnd *cmd);
 
index a42efd6..b3dd90f 100644 (file)
@@ -542,6 +542,9 @@ struct Scsi_Host {
         */
        unsigned ordered_tag:1;
 
+       /* task mgmt function in progress */
+       unsigned tmf_in_progress:1;
+
        /*
         * Optional work queue to be utilized by the transport
         */
@@ -619,7 +622,8 @@ static inline int scsi_host_in_recovery(struct Scsi_Host *shost)
 {
        return shost->shost_state == SHOST_RECOVERY ||
                shost->shost_state == SHOST_CANCEL_RECOVERY ||
-               shost->shost_state == SHOST_DEL_RECOVERY;
+               shost->shost_state == SHOST_DEL_RECOVERY ||
+               shost->tmf_in_progress;
 }
 
 extern int scsi_queue_work(struct Scsi_Host *, struct work_struct *);
index 93cfb4b..e3c503c 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/transport_class.h>
 #include <linux/types.h>
+#include <linux/mutex.h>
 
 struct scsi_transport_template;
 struct sas_rphy;
@@ -55,7 +56,6 @@ struct sas_phy {
        enum sas_linkrate       minimum_linkrate;
        enum sas_linkrate       maximum_linkrate_hw;
        enum sas_linkrate       maximum_linkrate;
-       u8                      port_identifier;
 
        /* internal state */
        unsigned int            local_attached : 1;
@@ -66,8 +66,8 @@ struct sas_phy {
        u32                     loss_of_dword_sync_count;
        u32                     phy_reset_problem_count;
 
-       /* the other end of the link */
-       struct sas_rphy         *rphy;
+       /* for the list of phys belonging to a port */
+       struct list_head        port_siblings;
 };
 
 #define dev_to_phy(d) \
@@ -124,6 +124,24 @@ struct sas_expander_device {
 #define rphy_to_expander_device(r) \
        container_of((r), struct sas_expander_device, rphy)
 
+struct sas_port {
+       struct device           dev;
+
+       u8                      port_identifier;
+       int                     num_phys;
+
+       /* the other end of the link */
+       struct sas_rphy         *rphy;
+
+       struct mutex            phy_list_mutex;
+       struct list_head        phy_list;
+};
+
+#define dev_to_sas_port(d) \
+       container_of((d), struct sas_port, dev)
+#define transport_class_to_sas_port(cdev) \
+       dev_to_sas_port((cdev)->dev)
+
 /* The functions by which the transport class and the driver communicate */
 struct sas_function_template {
        int (*get_linkerrors)(struct sas_phy *);
@@ -133,6 +151,7 @@ struct sas_function_template {
 };
 
 
+void sas_remove_children(struct device *);
 extern void sas_remove_host(struct Scsi_Host *);
 
 extern struct sas_phy *sas_phy_alloc(struct device *, int);
@@ -141,13 +160,21 @@ extern int sas_phy_add(struct sas_phy *);
 extern void sas_phy_delete(struct sas_phy *);
 extern int scsi_is_sas_phy(const struct device *);
 
-extern struct sas_rphy *sas_end_device_alloc(struct sas_phy *);
-extern struct sas_rphy *sas_expander_alloc(struct sas_phy *, enum sas_device_type);
+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_delete(struct sas_rphy *);
 extern int scsi_is_sas_rphy(const struct device *);
 
+struct sas_port *sas_port_alloc(struct device *, int);
+int sas_port_add(struct sas_port *);
+void sas_port_free(struct sas_port *);
+void sas_port_delete(struct sas_port *);
+void sas_port_add_phy(struct sas_port *, struct sas_phy *);
+void sas_port_delete_phy(struct sas_port *, struct sas_phy *);
+int scsi_is_sas_port(const struct device *);
+
 extern struct scsi_transport_template *
 sas_attach_transport(struct sas_function_template *);
 extern void sas_release_transport(struct scsi_transport_template *);