summaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/message/fusion')
-rw-r--r--drivers/message/fusion/Kconfig2
-rw-r--r--drivers/message/fusion/Makefile7
-rw-r--r--drivers/message/fusion/lsi/mpi.h7
-rw-r--r--drivers/message/fusion/lsi/mpi_cnfg.h131
-rw-r--r--drivers/message/fusion/lsi/mpi_history.txt77
-rw-r--r--drivers/message/fusion/lsi/mpi_init.h7
-rw-r--r--drivers/message/fusion/lsi/mpi_ioc.h75
-rw-r--r--drivers/message/fusion/lsi/mpi_log_sas.h284
-rw-r--r--drivers/message/fusion/lsi/mpi_sas.h9
-rw-r--r--drivers/message/fusion/mptbase.c875
-rw-r--r--drivers/message/fusion/mptbase.h47
-rw-r--r--drivers/message/fusion/mptctl.c165
-rw-r--r--drivers/message/fusion/mptctl.h2
-rw-r--r--drivers/message/fusion/mptfc.c53
-rw-r--r--drivers/message/fusion/mptlan.c1
-rw-r--r--drivers/message/fusion/mptlan.h1
-rw-r--r--drivers/message/fusion/mptsas.c718
-rw-r--r--drivers/message/fusion/mptscsih.c997
-rw-r--r--drivers/message/fusion/mptscsih.h44
-rw-r--r--drivers/message/fusion/mptspi.c527
20 files changed, 2674 insertions, 1355 deletions
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig
index ea31d8470510..71037f91c222 100644
--- a/drivers/message/fusion/Kconfig
+++ b/drivers/message/fusion/Kconfig
@@ -66,7 +66,7 @@ config FUSION_MAX_SGE
config FUSION_CTL
tristate "Fusion MPT misc device (ioctl) driver"
- depends on FUSION_SPI || FUSION_FC
+ depends on FUSION_SPI || FUSION_FC || FUSION_SAS
---help---
The Fusion MPT misc device driver provides specialized control
of MPT adapters via system ioctl calls. Use of ioctl calls to
diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile
index 341691390e86..6003b46c8438 100644
--- a/drivers/message/fusion/Makefile
+++ b/drivers/message/fusion/Makefile
@@ -8,6 +8,9 @@
#EXTRA_CFLAGS += -DMPT_DEBUG_INIT
#EXTRA_CFLAGS += -DMPT_DEBUG_EXIT
#EXTRA_CFLAGS += -DMPT_DEBUG_FAIL
+#EXTRA_CFLAGS += -DMPT_DEBUG_DV
+#EXTRA_CFLAGS += -DMPT_DEBUG_TM
+#EXTRA_CFLAGS += -DMPT_DEBUG_REPLY
#
# driver/module specifics...
@@ -20,11 +23,7 @@
#CFLAGS_mptbase.o += -DMPT_DEBUG_RESET
#
# For mptscsih:
-#CFLAGS_mptscsih.o += -DMPT_DEBUG_DV
-#CFLAGS_mptscsih.o += -DMPT_DEBUG_NEGO
-#CFLAGS_mptscsih.o += -DMPT_DEBUG_TM
#CFLAGS_mptscsih.o += -DMPT_DEBUG_SCSI
-#CFLAGS_mptscsih.o += -DMPT_DEBUG_REPLY
#
# For mptctl:
#CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL
diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h
index 81ad77622dac..75223bf24ae8 100644
--- a/drivers/message/fusion/lsi/mpi.h
+++ b/drivers/message/fusion/lsi/mpi.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2005 LSI Logic Corporation.
+ * Copyright (c) 2000-2006 LSI Logic Corporation.
*
*
* Name: mpi.h
* Title: MPI Message independent structures and definitions
* Creation Date: July 27, 2000
*
- * mpi.h Version: 01.05.11
+ * mpi.h Version: 01.05.12
*
* Version History
* ---------------
@@ -77,6 +77,7 @@
* 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT.
* 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target.
* 03-27-06 01.05.11 Bumped MPI_HEADER_VERSION_UNIT.
+ * 10-11-06 01.05.12 Bumped MPI_HEADER_VERSION_UNIT.
* --------------------------------------------------------------------------
*/
@@ -107,7 +108,7 @@
/* Note: The major versions of 0xe0 through 0xff are reserved */
/* versioning for this MPI header set */
-#define MPI_HEADER_VERSION_UNIT (0x0D)
+#define MPI_HEADER_VERSION_UNIT (0x0E)
#define MPI_HEADER_VERSION_DEV (0x00)
#define MPI_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI_HEADER_VERSION_UNIT_SHIFT (8)
diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h
index 47e13e360c10..0e4c8e77a81d 100644
--- a/drivers/message/fusion/lsi/mpi_cnfg.h
+++ b/drivers/message/fusion/lsi/mpi_cnfg.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2005 LSI Logic Corporation.
+ * Copyright (c) 2000-2006 LSI Logic Corporation.
*
*
* Name: mpi_cnfg.h
* Title: MPI Config message, structures, and Pages
* Creation Date: July 27, 2000
*
- * mpi_cnfg.h Version: 01.05.12
+ * mpi_cnfg.h Version: 01.05.13
*
* Version History
* ---------------
@@ -276,6 +276,23 @@
* Added AdditionalControlFlags, MaxTargetPortConnectTime,
* ReportDeviceMissingDelay, and IODeviceMissingDelay
* fields to SAS IO Unit Page 1.
+ * 10-11-06 01.05.13 Added NumForceWWID field and ForceWWID array to
+ * Manufacturing Page 5.
+ * Added Manufacturing pages 8 through 10.
+ * Added defines for supported metadata size bits in
+ * CapabilitiesFlags field of IOC Page 6.
+ * Added defines for metadata size bits in VolumeSettings
+ * field of RAID Volume Page 0.
+ * Added SATA Link Reset settings, Enable SATA Asynchronous
+ * Notification bit, and HideNonZeroAttachedPhyIdentifiers
+ * bit to AdditionalControlFlags field of SAS IO Unit
+ * Page 1.
+ * Added defines for Enclosure Devices Unmapped and
+ * Device Limit Exceeded bits in Status field of SAS IO
+ * Unit Page 2.
+ * Added more AccessStatus values for SAS Device Page 0.
+ * Added bit for SATA Asynchronous Notification Support in
+ * Flags field of SAS Device Page 0.
* --------------------------------------------------------------------------
*/
@@ -654,17 +671,24 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4
#define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA (0x01)
+#ifndef MPI_MANPAGE5_NUM_FORCEWWID
+#define MPI_MANPAGE5_NUM_FORCEWWID (1)
+#endif
+
typedef struct _CONFIG_PAGE_MANUFACTURING_5
{
CONFIG_PAGE_HEADER Header; /* 00h */
U64 BaseWWID; /* 04h */
U8 Flags; /* 0Ch */
- U8 Reserved1; /* 0Dh */
+ U8 NumForceWWID; /* 0Dh */
U16 Reserved2; /* 0Eh */
+ U32 Reserved3; /* 10h */
+ U32 Reserved4; /* 14h */
+ U64 ForceWWID[MPI_MANPAGE5_NUM_FORCEWWID]; /* 18h */
} CONFIG_PAGE_MANUFACTURING_5, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_5,
ManufacturingPage5_t, MPI_POINTER pManufacturingPage5_t;
-#define MPI_MANUFACTURING5_PAGEVERSION (0x01)
+#define MPI_MANUFACTURING5_PAGEVERSION (0x02)
/* defines for the Flags field */
#define MPI_MANPAGE5_TWO_WWID_PER_PHY (0x01)
@@ -740,6 +764,36 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_7
#define MPI_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001)
+typedef struct _CONFIG_PAGE_MANUFACTURING_8
+{
+ CONFIG_PAGE_HEADER Header; /* 00h */
+ U32 ProductSpecificInfo;/* 04h */
+} CONFIG_PAGE_MANUFACTURING_8, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_8,
+ ManufacturingPage8_t, MPI_POINTER pManufacturingPage8_t;
+
+#define MPI_MANUFACTURING8_PAGEVERSION (0x00)
+
+
+typedef struct _CONFIG_PAGE_MANUFACTURING_9
+{
+ CONFIG_PAGE_HEADER Header; /* 00h */
+ U32 ProductSpecificInfo;/* 04h */
+} CONFIG_PAGE_MANUFACTURING_9, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_9,
+ ManufacturingPage9_t, MPI_POINTER pManufacturingPage9_t;
+
+#define MPI_MANUFACTURING6_PAGEVERSION (0x00)
+
+
+typedef struct _CONFIG_PAGE_MANUFACTURING_10
+{
+ CONFIG_PAGE_HEADER Header; /* 00h */
+ U32 ProductSpecificInfo;/* 04h */
+} CONFIG_PAGE_MANUFACTURING_10, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_10,
+ ManufacturingPage10_t, MPI_POINTER pManufacturingPage10_t;
+
+#define MPI_MANUFACTURING10_PAGEVERSION (0x00)
+
+
/****************************************************************************
* IO Unit Config Pages
****************************************************************************/
@@ -1080,10 +1134,14 @@ typedef struct _CONFIG_PAGE_IOC_6
} CONFIG_PAGE_IOC_6, MPI_POINTER PTR_CONFIG_PAGE_IOC_6,
IOCPage6_t, MPI_POINTER pIOCPage6_t;
-#define MPI_IOCPAGE6_PAGEVERSION (0x00)
+#define MPI_IOCPAGE6_PAGEVERSION (0x01)
/* IOC Page 6 Capabilities Flags */
+#define MPI_IOCPAGE6_CAP_FLAGS_MASK_METADATA_SIZE (0x00000006)
+#define MPI_IOCPAGE6_CAP_FLAGS_64MB_METADATA_SIZE (0x00000000)
+#define MPI_IOCPAGE6_CAP_FLAGS_512MB_METADATA_SIZE (0x00000002)
+
#define MPI_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE (0x00000001)
@@ -2160,6 +2218,11 @@ typedef struct _RAID_VOL0_SETTINGS
#define MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE (0x0004)
#define MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC (0x0008)
#define MPI_RAIDVOL0_SETTING_FAST_DATA_SCRUBBING_0102 (0x0020) /* obsolete */
+
+#define MPI_RAIDVOL0_SETTING_MASK_METADATA_SIZE (0x00C0)
+#define MPI_RAIDVOL0_SETTING_64MB_METADATA_SIZE (0x0000)
+#define MPI_RAIDVOL0_SETTING_512MB_METADATA_SIZE (0x0040)
+
#define MPI_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX (0x0010)
#define MPI_RAIDVOL0_SETTING_USE_DEFAULTS (0x8000)
@@ -2203,7 +2266,7 @@ typedef struct _CONFIG_PAGE_RAID_VOL_0
} CONFIG_PAGE_RAID_VOL_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_0,
RaidVolumePage0_t, MPI_POINTER pRaidVolumePage0_t;
-#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x06)
+#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x07)
/* values for RAID Volume Page 0 InactiveStatus field */
#define MPI_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00)
@@ -2518,7 +2581,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
} CONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1,
SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t;
-#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x06)
+#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x07)
/* values for SAS IO Unit Page 1 ControlFlags */
#define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000)
@@ -2544,7 +2607,13 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001)
/* values for SAS IO Unit Page 1 AdditionalControlFlags */
-#define MPI_SAS_IOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001)
+#define MPI_SAS_IOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION (0x0040)
+#define MPI_SAS_IOUNIT1_ACONTROL_HIDE_NONZERO_ATTACHED_PHY_IDENT (0x0020)
+#define MPI_SAS_IOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET (0x0010)
+#define MPI_SAS_IOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET (0x0008)
+#define MPI_SAS_IOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET (0x0004)
+#define MPI_SAS_IOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET (0x0002)
+#define MPI_SAS_IOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001)
/* defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */
#define MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK (0x7F)
@@ -2585,9 +2654,11 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
} CONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2,
SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t;
-#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x05)
+#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x06)
/* values for SAS IO Unit Page 2 Status field */
+#define MPI_SAS_IOUNIT2_STATUS_DEVICE_LIMIT_EXCEEDED (0x08)
+#define MPI_SAS_IOUNIT2_STATUS_ENCLOSURE_DEVICES_UNMAPPED (0x04)
#define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02)
#define MPI_SAS_IOUNIT2_STATUS_FULL_PERSISTENT_MAPPINGS (0x01)
@@ -2739,24 +2810,38 @@ typedef struct _CONFIG_PAGE_SAS_DEVICE_0
} CONFIG_PAGE_SAS_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_0,
SasDevicePage0_t, MPI_POINTER pSasDevicePage0_t;
-#define MPI_SASDEVICE0_PAGEVERSION (0x04)
+#define MPI_SASDEVICE0_PAGEVERSION (0x05)
/* values for SAS Device Page 0 AccessStatus field */
-#define MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00)
-#define MPI_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01)
-#define MPI_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02)
+#define MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00)
+#define MPI_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01)
+#define MPI_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02)
+#define MPI_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT (0x03)
+/* specific values for SATA Init failures */
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN (0x10)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT (0x11)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_DIAG (0x12)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION (0x13)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER (0x14)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_PIO_SN (0x15)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN (0x16)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN (0x17)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION (0x18)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE (0x19)
+#define MPI_SAS_DEVICE0_ASTATUS_SIF_MAX (0x1F)
/* values for SAS Device Page 0 Flags field */
-#define MPI_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE (0x0200)
-#define MPI_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE (0x0100)
-#define MPI_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED (0x0080)
-#define MPI_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED (0x0040)
-#define MPI_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020)
-#define MPI_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010)
-#define MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008)
-#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT (0x0004)
-#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED (0x0002)
-#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY (0x0400)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE (0x0200)
+#define MPI_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE (0x0100)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED (0x0080)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED (0x0040)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010)
+#define MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008)
+#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT (0x0004)
+#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED (0x0002)
+#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001)
/* see mpi_sas.h for values for SAS Device Page 0 DeviceInfo values */
diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt
index 582cfe7c2aa1..d6b4c607453b 100644
--- a/drivers/message/fusion/lsi/mpi_history.txt
+++ b/drivers/message/fusion/lsi/mpi_history.txt
@@ -3,28 +3,28 @@
MPI Header File Change History
==============================
- Copyright (c) 2000-2005 LSI Logic Corporation.
+ Copyright (c) 2000-2006 LSI Logic Corporation.
---------------------------------------
- Header Set Release Version: 01.05.13
- Header Set Release Date: 03-27-06
+ Header Set Release Version: 01.05.14
+ Header Set Release Date: 10-11-06
---------------------------------------
Filename Current version Prior version
---------- --------------- -------------
- mpi.h 01.05.11 01.05.10
- mpi_ioc.h 01.05.11 01.05.10
- mpi_cnfg.h 01.05.12 01.05.11
- mpi_init.h 01.05.07 01.05.06
- mpi_targ.h 01.05.06 01.05.05
+ mpi.h 01.05.12 01.05.11
+ mpi_ioc.h 01.05.12 01.05.11
+ mpi_cnfg.h 01.05.13 01.05.12
+ mpi_init.h 01.05.08 01.05.07
+ mpi_targ.h 01.05.06 01.05.06
mpi_fc.h 01.05.01 01.05.01
mpi_lan.h 01.05.01 01.05.01
mpi_raid.h 01.05.02 01.05.02
mpi_tool.h 01.05.03 01.05.03
mpi_inb.h 01.05.01 01.05.01
- mpi_sas.h 01.05.03 01.05.02
+ mpi_sas.h 01.05.04 01.05.03
mpi_type.h 01.05.02 01.05.02
- mpi_history.txt 01.05.13 01.05.12
+ mpi_history.txt 01.05.14 01.05.13
* Date Version Description
@@ -94,6 +94,7 @@ mpi.h
* 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT.
* 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target.
* 03-27-06 01.05.11 Bumped MPI_HEADER_VERSION_UNIT.
+ * 10-11-06 01.05.12 Bumped MPI_HEADER_VERSION_UNIT.
* --------------------------------------------------------------------------
mpi_ioc.h
@@ -182,6 +183,14 @@ mpi_ioc.h
* Added MPI_EVENT_SAS_INIT_TABLE_OVERFLOW and event
* data structure.
* Added MPI_EXT_IMAGE_TYPE_INITIALIZATION.
+ * 10-11-06 01.05.12 Added MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED.
+ * Added MaxInitiators field to PortFacts reply.
+ * Added SAS Device Status Change ReasonCode for
+ * asynchronous notificaiton.
+ * Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event
+ * data structure.
+ * Added new ImageType values for FWDownload and FWUpload
+ * requests.
* --------------------------------------------------------------------------
mpi_cnfg.h
@@ -447,6 +456,23 @@ mpi_cnfg.h
* Added AdditionalControlFlags, MaxTargetPortConnectTime,
* ReportDeviceMissingDelay, and IODeviceMissingDelay
* fields to SAS IO Unit Page 1.
+ * 10-11-06 01.05.13 Added NumForceWWID field and ForceWWID array to
+ * Manufacturing Page 5.
+ * Added Manufacturing pages 8 through 10.
+ * Added defines for supported metadata size bits in
+ * CapabilitiesFlags field of IOC Page 6.
+ * Added defines for metadata size bits in VolumeSettings
+ * field of RAID Volume Page 0.
+ * Added SATA Link Reset settings, Enable SATA Asynchronous
+ * Notification bit, and HideNonZeroAttachedPhyIdentifiers
+ * bit to AdditionalControlFlags field of SAS IO Unit
+ * Page 1.
+ * Added defines for Enclosure Devices Unmapped and
+ * Device Limit Exceeded bits in Status field of SAS IO
+ * Unit Page 2.
+ * Added more AccessStatus values for SAS Device Page 0.
+ * Added bit for SATA Asynchronous Notification Support in
+ * Flags field of SAS Device Page 0.
* --------------------------------------------------------------------------
mpi_init.h
@@ -490,6 +516,7 @@ mpi_init.h
* 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
* unique in the first 32 characters.
* 03-27-06 01.05.07 Added Task Management type of Clear ACA.
+ * 10-11-06 01.05.08 Shortened define for Task Management type of Clear ACA.
* --------------------------------------------------------------------------
mpi_targ.h
@@ -638,6 +665,8 @@ mpi_sas.h
* and Remove Device operations to SAS IO Unit Control.
* Added DevHandle field to SAS IO Unit Control request and
* reply.
+ * 10-11-06 01.05.04 Fixed the name of a define for Operation field of SAS IO
+ * Unit Control request.
* --------------------------------------------------------------------------
mpi_type.h
@@ -653,20 +682,20 @@ mpi_type.h
mpi_history.txt Parts list history
-Filename 01.05.13 01.05.12 01.05.11 01.05.10 01.05.09
----------- -------- -------- -------- -------- --------
-mpi.h 01.05.11 01.05.10 01.05.09 01.05.08 01.05.07
-mpi_ioc.h 01.05.11 01.05.10 01.05.09 01.05.09 01.05.08
-mpi_cnfg.h 01.05.12 01.05.11 01.05.10 01.05.09 01.05.08
-mpi_init.h 01.05.07 01.05.06 01.05.06 01.05.05 01.05.04
-mpi_targ.h 01.05.06 01.05.05 01.05.05 01.05.05 01.05.04
-mpi_fc.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
-mpi_lan.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
-mpi_raid.h 01.05.02 01.05.02 01.05.02 01.05.02 01.05.02
-mpi_tool.h 01.05.03 01.05.03 01.05.03 01.05.03 01.05.03
-mpi_inb.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
-mpi_sas.h 01.05.03 01.05.02 01.05.01 01.05.01 01.05.01
-mpi_type.h 01.05.02 01.05.02 01.05.01 01.05.01 01.05.01
+Filename 01.05.13 01.05.13 01.05.12 01.05.11 01.05.10 01.05.09
+---------- -------- -------- -------- -------- -------- --------
+mpi.h 01.05.12 01.05.11 01.05.10 01.05.09 01.05.08 01.05.07
+mpi_ioc.h 01.05.12 01.05.11 01.05.10 01.05.09 01.05.09 01.05.08
+mpi_cnfg.h 01.05.13 01.05.12 01.05.11 01.05.10 01.05.09 01.05.08
+mpi_init.h 01.05.08 01.05.07 01.05.06 01.05.06 01.05.05 01.05.04
+mpi_targ.h 01.05.06 01.05.06 01.05.05 01.05.05 01.05.05 01.05.04
+mpi_fc.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_lan.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_raid.h 01.05.02 01.05.02 01.05.02 01.05.02 01.05.02 01.05.02
+mpi_tool.h 01.05.03 01.05.03 01.05.03 01.05.03 01.05.03 01.05.03
+mpi_inb.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_sas.h 01.05.04 01.05.03 01.05.02 01.05.01 01.05.01 01.05.01
+mpi_type.h 01.05.02 01.05.02 01.05.02 01.05.01 01.05.01 01.05.01
Filename 01.05.08 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03
---------- -------- -------- -------- -------- -------- --------
diff --git a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h
index c1c678989a23..ec9dff2249a7 100644
--- a/drivers/message/fusion/lsi/mpi_init.h
+++ b/drivers/message/fusion/lsi/mpi_init.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2005 LSI Logic Corporation.
+ * Copyright (c) 2000-2006 LSI Logic Corporation.
*
*
* Name: mpi_init.h
* Title: MPI initiator mode messages and structures
* Creation Date: June 8, 2000
*
- * mpi_init.h Version: 01.05.07
+ * mpi_init.h Version: 01.05.08
*
* Version History
* ---------------
@@ -53,6 +53,7 @@
* 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
* unique in the first 32 characters.
* 03-27-06 01.05.07 Added Task Management type of Clear ACA.
+ * 10-11-06 01.05.08 Shortened define for Task Management type of Clear ACA.
* --------------------------------------------------------------------------
*/
@@ -428,7 +429,7 @@ typedef struct _MSG_SCSI_TASK_MGMT
#define MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05)
#define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06)
#define MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07)
-#define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_ACA (0x08)
+#define MPI_SCSITASKMGMT_TASKTYPE_CLR_ACA (0x08)
/* MsgFlags bits */
#define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION (0x00)
diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h
index 18ba407fd399..6c33e3353375 100644
--- a/drivers/message/fusion/lsi/mpi_ioc.h
+++ b/drivers/message/fusion/lsi/mpi_ioc.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2005 LSI Logic Corporation.
+ * Copyright (c) 2000-2006 LSI Logic Corporation.
*
*
* Name: mpi_ioc.h
* Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
* Creation Date: August 11, 2000
*
- * mpi_ioc.h Version: 01.05.11
+ * mpi_ioc.h Version: 01.05.12
*
* Version History
* ---------------
@@ -98,6 +98,14 @@
* Added MPI_EVENT_SAS_INIT_TABLE_OVERFLOW and event
* data structure.
* Added MPI_EXT_IMAGE_TYPE_INITIALIZATION.
+ * 10-11-06 01.05.12 Added MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED.
+ * Added MaxInitiators field to PortFacts reply.
+ * Added SAS Device Status Change ReasonCode for
+ * asynchronous notificaiton.
+ * Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event
+ * data structure.
+ * Added new ImageType values for FWDownload and FWUpload
+ * requests.
* --------------------------------------------------------------------------
*/
@@ -264,6 +272,7 @@ typedef struct _MSG_IOC_FACTS_REPLY
#define MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002)
#define MPI_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004)
#define MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL (0x0008)
+#define MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED (0x0010)
#define MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT (0x01)
#define MPI_IOCFACTS_FLAGS_REPLY_FIFO_HOST_SIGNAL (0x02)
@@ -328,7 +337,8 @@ typedef struct _MSG_PORT_FACTS_REPLY
U16 MaxPostedCmdBuffers; /* 1Ch */
U16 MaxPersistentIDs; /* 1Eh */
U16 MaxLanBuckets; /* 20h */
- U16 Reserved4; /* 22h */
+ U8 MaxInitiators; /* 22h */
+ U8 Reserved4; /* 23h */
U32 Reserved5; /* 24h */
} MSG_PORT_FACTS_REPLY, MPI_POINTER PTR_MSG_PORT_FACTS_REPLY,
PortFactsReply_t, MPI_POINTER pPortFactsReply_t;
@@ -487,6 +497,7 @@ typedef struct _MSG_EVENT_ACK_REPLY
#define MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x00000018)
#define MPI_EVENT_SAS_INIT_TABLE_OVERFLOW (0x00000019)
#define MPI_EVENT_SAS_SMP_ERROR (0x0000001A)
+#define MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE (0x0000001B)
#define MPI_EVENT_LOG_ENTRY_ADDED (0x00000021)
/* AckRequired field values */
@@ -593,6 +604,7 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
#define MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A)
#define MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B)
#define MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C)
+#define MPI_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION (0x0D)
/* SCSI Event data for Queue Full event */
@@ -895,6 +907,54 @@ typedef struct _EVENT_DATA_SAS_INIT_TABLE_OVERFLOW
MpiEventDataSasInitTableOverflow_t,
MPI_POINTER pMpiEventDataSasInitTableOverflow_t;
+/* SAS Expander Status Change Event data */
+
+typedef struct _EVENT_DATA_SAS_EXPANDER_STATUS_CHANGE
+{
+ U8 ReasonCode; /* 00h */
+ U8 Reserved1; /* 01h */
+ U16 Reserved2; /* 02h */
+ U8 PhysicalPort; /* 04h */
+ U8 Reserved3; /* 05h */
+ U16 EnclosureHandle; /* 06h */
+ U64 SASAddress; /* 08h */
+ U32 DiscoveryStatus; /* 10h */
+ U16 DevHandle; /* 14h */
+ U16 ParentDevHandle; /* 16h */
+ U16 ExpanderChangeCount; /* 18h */
+ U16 ExpanderRouteIndexes; /* 1Ah */
+ U8 NumPhys; /* 1Ch */
+ U8 SASLevel; /* 1Dh */
+ U8 Flags; /* 1Eh */
+ U8 Reserved4; /* 1Fh */
+} EVENT_DATA_SAS_EXPANDER_STATUS_CHANGE,
+ MPI_POINTER PTR_EVENT_DATA_SAS_EXPANDER_STATUS_CHANGE,
+ MpiEventDataSasExpanderStatusChange_t,
+ MPI_POINTER pMpiEventDataSasExpanderStatusChange_t;
+
+/* values for ReasonCode field of SAS Expander Status Change Event data */
+#define MPI_EVENT_SAS_EXP_RC_ADDED (0x00)
+#define MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING (0x01)
+
+/* values for DiscoveryStatus field of SAS Expander Status Change Event data */
+#define MPI_EVENT_SAS_EXP_DS_LOOP_DETECTED (0x00000001)
+#define MPI_EVENT_SAS_EXP_DS_UNADDRESSABLE_DEVICE (0x00000002)
+#define MPI_EVENT_SAS_EXP_DS_MULTIPLE_PORTS (0x00000004)
+#define MPI_EVENT_SAS_EXP_DS_EXPANDER_ERR (0x00000008)
+#define MPI_EVENT_SAS_EXP_DS_SMP_TIMEOUT (0x00000010)
+#define MPI_EVENT_SAS_EXP_DS_OUT_ROUTE_ENTRIES (0x00000020)
+#define MPI_EVENT_SAS_EXP_DS_INDEX_NOT_EXIST (0x00000040)
+#define MPI_EVENT_SAS_EXP_DS_SMP_FUNCTION_FAILED (0x00000080)
+#define MPI_EVENT_SAS_EXP_DS_SMP_CRC_ERROR (0x00000100)
+#define MPI_EVENT_SAS_EXP_DS_SUBTRACTIVE_LINK (0x00000200)
+#define MPI_EVENT_SAS_EXP_DS_TABLE_LINK (0x00000400)
+#define MPI_EVENT_SAS_EXP_DS_UNSUPPORTED_DEVICE (0x00000800)
+
+/* values for Flags field of SAS Expander Status Change Event data */
+#define MPI_EVENT_SAS_EXP_FLAGS_ROUTE_TABLE_CONFIG (0x02)
+#define MPI_EVENT_SAS_EXP_FLAGS_CONFIG_IN_PROGRESS (0x01)
+
+
/*****************************************************************************
*
@@ -926,6 +986,10 @@ typedef struct _MSG_FW_DOWNLOAD
#define MPI_FW_DOWNLOAD_ITYPE_BIOS (0x02)
#define MPI_FW_DOWNLOAD_ITYPE_NVDATA (0x03)
#define MPI_FW_DOWNLOAD_ITYPE_BOOTLOADER (0x04)
+#define MPI_FW_DOWNLOAD_ITYPE_MANUFACTURING (0x06)
+#define MPI_FW_DOWNLOAD_ITYPE_CONFIG_1 (0x07)
+#define MPI_FW_DOWNLOAD_ITYPE_CONFIG_2 (0x08)
+#define MPI_FW_DOWNLOAD_ITYPE_MEGARAID (0x09)
typedef struct _FWDownloadTCSGE
@@ -980,6 +1044,11 @@ typedef struct _MSG_FW_UPLOAD
#define MPI_FW_UPLOAD_ITYPE_NVDATA (0x03)
#define MPI_FW_UPLOAD_ITYPE_BOOTLOADER (0x04)
#define MPI_FW_UPLOAD_ITYPE_FW_BACKUP (0x05)
+#define MPI_FW_UPLOAD_ITYPE_MANUFACTURING (0x06)
+#define MPI_FW_UPLOAD_ITYPE_CONFIG_1 (0x07)
+#define MPI_FW_UPLOAD_ITYPE_CONFIG_2 (0x08)
+#define MPI_FW_UPLOAD_ITYPE_MEGARAID (0x09)
+#define MPI_FW_UPLOAD_ITYPE_COMPLETE (0x0A)
typedef struct _FWUploadTCSGE
{
diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h
index 871ebc08b706..635bbe04513e 100644
--- a/drivers/message/fusion/lsi/mpi_log_sas.h
+++ b/drivers/message/fusion/lsi/mpi_log_sas.h
@@ -1,4 +1,3 @@
-
/***************************************************************************
* *
* Copyright 2003 LSI Logic Corporation. All rights reserved. *
@@ -14,7 +13,7 @@
#define IOPI_IOCLOGINFO_H_INCLUDED
#define SAS_LOGINFO_NEXUS_LOSS 0x31170000
-#define SAS_LOGINFO_MASK 0xFFFF0000
+#define SAS_LOGINFO_MASK 0xFFFF0000
/****************************************************************************/
/* IOC LOGINFO defines, 0x00000000 - 0x0FFFFFFF */
@@ -43,129 +42,172 @@
/****************************************************************************/
/* IOP LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IOP */
/****************************************************************************/
-#define IOP_LOGINFO_CODE_INVALID_SAS_ADDRESS (0x00010000)
-#define IOP_LOGINFO_CODE_UNUSED2 (0x00020000)
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x00030000)
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_RT (0x00030100) /* Route Table Entry not found */
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PN (0x00030200) /* Invalid Page Number */
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x00030300) /* Invalid FORM */
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x00030400) /* Invalid Page Type */
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM (0x00030500) /* Device Not Mapped */
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST (0x00030600) /* Persistent Page not found */
-#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */
-
-#define IOP_LOGINFO_CODE_DIAG_MSG_ERROR (0x00040000) /* Error handling diag msg - or'd with diag status */
-
-#define IOP_LOGINFO_CODE_TASK_TERMINATED (0x00050000)
-
-#define IOP_LOGINFO_CODE_ENCL_MGMT_READ_ACTION_ERR0R (0x00060001) /* Read Action not supported for SEP msg */
-#define IOP_LOGINFO_CODE_ENCL_MGMT_INVALID_BUS_ID_ERR0R (0x00060002) /* Invalid Bus/ID in SEP msg */
-
-#define IOP_LOGINFO_CODE_TARGET_ASSIST_TERMINATED (0x00070001)
-#define IOP_LOGINFO_CODE_TARGET_STATUS_SEND_TERMINATED (0x00070002)
-#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_ALL_IO (0x00070003)
-#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO (0x00070004)
-#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO_REQ (0x00070005)
+#define IOP_LOGINFO_CODE_INVALID_SAS_ADDRESS (0x00010000)
+#define IOP_LOGINFO_CODE_UNUSED2 (0x00020000)
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x00030000)
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_RT (0x00030100) /* Route Table Entry not found */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PN (0x00030200) /* Invalid Page Number */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x00030300) /* Invalid FORM */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x00030400) /* Invalid Page Type */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM (0x00030500) /* Device Not Mapped */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST (0x00030600) /* Persistent Page not found */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */
+
+#define IOP_LOGINFO_CODE_FWUPLOAD_NO_FLASH_AVAILABLE (0x0003E000) /* Tried to upload from flash, but there is none */
+#define IOP_LOGINFO_CODE_FWUPLOAD_UNKNOWN_IMAGE_TYPE (0x0003E001) /* ImageType field contents were invalid */
+#define IOP_LOGINFO_CODE_FWUPLOAD_WRONG_IMAGE_SIZE (0x0003E002) /* ImageSize field in TCSGE was bad/offset in MfgPg 4 was wrong */
+#define IOP_LOGINFO_CODE_FWUPLOAD_ENTIRE_FLASH_UPLOAD_FAILED (0x0003E003) /* Error occured while attempting to upload the entire flash */
+#define IOP_LOGINFO_CODE_FWUPLOAD_REGION_UPLOAD_FAILED (0x0003E004) /* Error occured while attempting to upload single flash region */
+#define IOP_LOGINFO_CODE_FWUPLOAD_DMA_FAILURE (0x0003E005) /* Problem occured while DMAing FW to host memory */
+
+#define IOP_LOGINFO_CODE_DIAG_MSG_ERROR (0x00040000) /* Error handling diag msg - or'd with diag status */
+
+#define IOP_LOGINFO_CODE_TASK_TERMINATED (0x00050000)
+
+#define IOP_LOGINFO_CODE_ENCL_MGMT_READ_ACTION_ERR0R (0x00060001) /* Read Action not supported for SEP msg */
+#define IOP_LOGINFO_CODE_ENCL_MGMT_INVALID_BUS_ID_ERR0R (0x00060002) /* Invalid Bus/ID in SEP msg */
+
+#define IOP_LOGINFO_CODE_TARGET_ASSIST_TERMINATED (0x00070001)
+#define IOP_LOGINFO_CODE_TARGET_STATUS_SEND_TERMINATED (0x00070002)
+#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_ALL_IO (0x00070003)
+#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO (0x00070004)
+#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO_REQ (0x00070005)
/****************************************************************************/
/* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL */
/****************************************************************************/
-#define PL_LOGINFO_CODE_OPEN_FAILURE (0x00010000)
-#define PL_LOG_INFO_CODE_OPEN_FAILURE_NO_DEST_TIME_OUT (0x00010001)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_BAD_DESTINATION (0x00010011)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_PROTOCOL_NOT_SUPPORTED (0x00010013)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_STP_RESOURCES_BSY (0x00010018)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_WRONG_DESTINATION (0x00010019)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_ORR_TIMEOUT (0X0001001A)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_PATHWAY_BLOCKED (0x0001001B)
-#define PL_LOGINFO_CODE_OPEN_FAILURE_AWT_MAXED (0x0001001C)
-#define PL_LOGINFO_CODE_INVALID_SGL (0x00020000)
-#define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00030000)
-#define PL_LOGINFO_CODE_FRAME_XFER_ERROR (0x00040000)
-#define PL_LOGINFO_CODE_TX_FM_CONNECTED_LOW (0x00050000)
-#define PL_LOGINFO_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00060000)
-#define PL_LOGINFO_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00070000)
-#define PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00080000)
-#define PL_LOGINFO_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00090000)
-#define PL_LOGINFO_CODE_RX_FM_INVALID_MESSAGE (0x000A0000)
-#define PL_LOGINFO_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x000B0000)
-#define PL_LOGINFO_CODE_RX_FM_CURRENT_FRAME_ERROR (0x000C0000)
-#define PL_LOGINFO_CODE_SATA_LINK_DOWN (0x000D0000)
-#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS (0x000E0000)
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x000F0000)
-#define PL_LOGINFO_CODE_CONFIG_PL_NOT_INITIALIZED (0x000F0001) /* PL not yet initialized, can't do config page req. */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x000F0100) /* Invalid Page Type */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS (0x000F0200) /* Invalid Number of Phys */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP (0x000F0300) /* Case Not Handled */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_DEV (0x000F0400) /* No Device Found */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x000F0500) /* Invalid FORM */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY (0x000F0600) /* Invalid Phy */
-#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER (0x000F0700) /* No Owner Found */
-#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00100000)
-#define PL_LOGINFO_CODE_RESET (0x00110000) /* See Sub-Codes below */
-#define PL_LOGINFO_CODE_ABORT (0x00120000) /* See Sub-Codes below */
-#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000)
-#define PL_LOGINFO_CODE_IO_EXECUTED (0x00140000)
-#define PL_LOGINFO_CODE_PERS_RESV_OUT_NOT_AFFIL_OWNER (0x00150000)
-#define PL_LOGINFO_CODE_OPEN_TXDMA_ABORT (0x00160000)
-#define PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY (0x00170000)
-#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE (0x00000100)
-#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_NO_DEST_TIMEOUT (0x00000101)
-#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ORR_TIMEOUT (0x0000011A) /* Open Reject (Retry) Timeout */
-#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_PATHWAY_BLOCKED (0x0000011B)
-#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_AWT_MAXED (0x0000011C) /* Arbitration Wait Timer Maxed */
-
-#define PL_LOGINFO_SUB_CODE_TARGET_BUS_RESET (0x00000120)
-#define PL_LOGINFO_SUB_CODE_TRANSPORT_LAYER (0x00000130) /* Leave lower nibble (1-f) reserved. */
-#define PL_LOGINFO_SUB_CODE_PORT_LAYER (0x00000140) /* Leave lower nibble (1-f) reserved. */
-
-
-#define PL_LOGINFO_SUB_CODE_INVALID_SGL (0x00000200)
-#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300)
-#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400)
-#define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW (0x00000500)
-#define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00000600)
-#define PL_LOGINFO_SUB_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00000700)
-#define PL_LOGINFO_SUB_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00000800)
-#define PL_LOGINFO_SUB_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00000900)
-#define PL_LOGINFO_SUB_CODE_RX_FM_INVALID_MESSAGE (0x00000A00)
-#define PL_LOGINFO_SUB_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x00000B00)
-#define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR (0x00000C00)
-#define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN (0x00000D00)
-#define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS (0x00000E00)
-#define PL_LOGINFO_SUB_CODE_DISCOVERY_REMOTE_SEP_RESET (0x00000E01)
-#define PL_LOGINFO_SUB_CODE_SECOND_OPEN (0x00000F00)
-#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00001000)
-
-
-#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200010) /* Error occured on SMP Read */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200020) /* Error occured on SMP Write */
-#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200040) /* Encl Mgmt services not available for this WWID */
-#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200050) /* Address Mode not suppored */
-#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200060) /* Invalid Slot Number in SEP Msg */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200070) /* SGPIO not present/enabled */
-#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_NOT_CONFIGURED (0x00200080) /* GPIO not configured */
-#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_FRAME_ERROR (0x00200090) /* GPIO can't allocate a frame */
-#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_CONFIG_PAGE_ERROR (0x002000A0) /* GPIO failed config page request */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SES_FRAME_ALLOC_ERROR (0x002000B0) /* Can't get frame for SES command */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SES_IO_ERROR (0x002000C0) /* I/O execution error */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SES_RETRIES_EXHAUSTED (0x002000D0) /* SEP I/O retries exhausted */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_ALLOC_ERROR (0x002000E0) /* Can't get frame for SMP command */
-
-#define PL_LOGINFO_DA_SEP_NOT_PRESENT (0x00200100) /* SEP not present when msg received */
-#define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR (0x00200101) /* Can only accept 1 msg at a time */
-#define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE (0x00200102) /* ISTWI interrupt recvd. while IDLE */
-#define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE (0x00200103) /* SEP NACK'd, it is busy */
-#define PL_LOGINFO_DA_SEP_DID_NOT_RECEIVE_ACK (0x00200104) /* SEP didn't rcv. ACK (Last Rcvd Bit = 1) */
-#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200105) /* SEP stopped or sent bad chksum in Hdr */
-#define PL_LOGINFO_DA_SEP_STOP_ON_DATA (0x00200106) /* SEP stopped while transfering data */
-#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA (0x00200107) /* SEP stopped while transfering sense data */
-#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200108) /* SEP returned unknown scsi status */
-#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200109) /* SEP returned unknown scsi status */
-#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x0020010A) /* SEP returned bad chksum after STOP */
-#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x0020010B) /* SEP returned bad chksum after STOP while gettin data*/
-#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND (0x0020010C) /* SEP doesn't support CDB opcode */
+#define PL_LOGINFO_CODE_OPEN_FAILURE (0x00010000) /* see SUB_CODE_OPEN_FAIL_ below */
+
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_NO_DEST_TIME_OUT (0x00000001)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_PATHWAY_BLOCKED (0x00000002)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_CONTINUE0 (0x00000003)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_CONTINUE1 (0x00000004)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_INITIALIZE0 (0x00000005)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_INITIALIZE1 (0x00000006)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_STOP0 (0x00000007)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_STOP1 (0x00000008)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RETRY (0x00000009)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_BREAK (0x0000000A)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_UNUSED_0B (0x0000000B)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_OPEN_TIMEOUT_EXP (0x0000000C)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_UNUSED_0D (0x0000000D)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_DVTBLE_ACCSS_FAIL (0x0000000E)
+#define PL_LOGINFO_SUB CODE_OPEN_FAIL_BAD_DEST (0x00000011)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RATE_NOT_SUPP (0x00000012)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_PROT_NOT_SUPP (0x00000013)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON0 (0x00000014)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON1 (0x00000015)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON2 (0x00000016)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON3 (0x00000017)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_STP_RESOURCES_BSY (0x00000018)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_WRONG_DESTINATION (0x00000019)
+
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_PATH_BLOCKED (0x0000001B) /* Retry Timeout */
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_AWT_MAXED (0x0000001C) /* Retry Timeout */
+
+
+
+#define PL_LOGINFO_CODE_INVALID_SGL (0x00020000)
+#define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00030000)
+#define PL_LOGINFO_CODE_FRAME_XFER_ERROR (0x00040000)
+#define PL_LOGINFO_CODE_TX_FM_CONNECTED_LOW (0x00050000)
+#define PL_LOGINFO_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00060000)
+#define PL_LOGINFO_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00070000)
+#define PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00080000)
+#define PL_LOGINFO_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00090000)
+#define PL_LOGINFO_CODE_RX_FM_INVALID_MESSAGE (0x000A0000)
+#define PL_LOGINFO_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x000B0000)
+#define PL_LOGINFO_CODE_RX_FM_CURRENT_FRAME_ERROR (0x000C0000)
+#define PL_LOGINFO_CODE_SATA_LINK_DOWN (0x000D0000)
+#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS (0x000E0000)
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x000F0000)
+#define PL_LOGINFO_CODE_CONFIG_PL_NOT_INITIALIZED (0x000F0001) /* PL not yet initialized, can't do config page req. */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x000F0100) /* Invalid Page Type */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS (0x000F0200) /* Invalid Number of Phys */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP (0x000F0300) /* Case Not Handled */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_DEV (0x000F0400) /* No Device Found */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x000F0500) /* Invalid FORM */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY (0x000F0600) /* Invalid Phy */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER (0x000F0700) /* No Owner Found */
+#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00100000)
+#define PL_LOGINFO_CODE_RESET (0x00110000) /* See Sub-Codes below (PL_LOGINFO_SUB_CODE) */
+#define PL_LOGINFO_CODE_ABORT (0x00120000) /* See Sub-Codes below (PL_LOGINFO_SUB_CODE)*/
+#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000)
+#define PL_LOGINFO_CODE_IO_EXECUTED (0x00140000)
+#define PL_LOGINFO_CODE_PERS_RESV_OUT_NOT_AFFIL_OWNER (0x00150000)
+#define PL_LOGINFO_CODE_OPEN_TXDMA_ABORT (0x00160000)
+#define PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY (0x00170000)
+#define PL_LOGINFO_CODE_IO_CANCELLED_DUE_TO_R_ERR (0x00180000)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE (0x00000100)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_NO_DEST_TIMEOUT (0x00000101)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_SATA_NEG_RATE_2HI (0x00000102)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_RATE_NOT_SUPPORTED (0x00000103)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_BREAK (0x00000104)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ZONE_VIOLATION (0x00000114)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON0 (0x00000114) /* Open Reject (Zone Violation) - available on SAS-2 devices */
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON1 (0x00000115)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON2 (0x00000116)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON3 (0x00000117)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ORR_TIMEOUT (0x0000011A) /* Open Reject (Retry) Timeout */
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_PATH_BLOCKED (0x0000011B)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_AWT_MAXED (0x0000011C) /* Arbitration Wait Timer Maxed */
+
+#define PL_LOGINFO_SUB_CODE_TARGET_BUS_RESET (0x00000120)
+#define PL_LOGINFO_SUB_CODE_TRANSPORT_LAYER (0x00000130) /* Leave lower nibble (1-f) reserved. */
+#define PL_LOGINFO_SUB_CODE_PORT_LAYER (0x00000140) /* Leave lower nibble (1-f) reserved. */
+
+
+#define PL_LOGINFO_SUB_CODE_INVALID_SGL (0x00000200)
+#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300)
+#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400) /* Bits 0-3 encode Transport Status Register (offset 0x08) */
+ /* Bit 0 is Status Bit 0: FrameXferErr */
+ /* Bit 1 & 2 are Status Bits 16 and 17: FrameXmitErrStatus */
+ /* Bit 3 is Status Bit 18 WriteDataLenghtGTDataLengthErr */
+
+#define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW (0x00000500)
+#define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00000600)
+#define PL_LOGINFO_SUB_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00000700)
+#define PL_LOGINFO_SUB_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00000800)
+#define PL_LOGINFO_SUB_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00000900)
+#define PL_LOGINFO_SUB_CODE_RX_FM_INVALID_MESSAGE (0x00000A00)
+#define PL_LOGINFO_SUB_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x00000B00)
+#define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR (0x00000C00)
+#define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN (0x00000D00)
+#define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS (0x00000E00)
+#define PL_LOGINFO_SUB_CODE_DISCOVERY_REMOTE_SEP_RESET (0x00000E01)
+#define PL_LOGINFO_SUB_CODE_SECOND_OPEN (0x00000F00)
+#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00001000)
+
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200010) /* Error occured on SMP Read */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200020) /* Error occured on SMP Write */
+#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200040) /* Encl Mgmt services not available for this WWID */
+#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200050) /* Address Mode not suppored */
+#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200060) /* Invalid Slot Number in SEP Msg */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200070) /* SGPIO not present/enabled */
+#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_NOT_CONFIGURED (0x00200080) /* GPIO not configured */
+#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_FRAME_ERROR (0x00200090) /* GPIO can't allocate a frame */
+#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_CONFIG_PAGE_ERROR (0x002000A0) /* GPIO failed config page request */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SES_FRAME_ALLOC_ERROR (0x002000B0) /* Can't get frame for SES command */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SES_IO_ERROR (0x002000C0) /* I/O execution error */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SES_RETRIES_EXHAUSTED (0x002000D0) /* SEP I/O retries exhausted */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_ALLOC_ERROR (0x002000E0) /* Can't get frame for SMP command */
+
+#define PL_LOGINFO_DA_SEP_NOT_PRESENT (0x00200100) /* SEP not present when msg received */
+#define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR (0x00200101) /* Can only accept 1 msg at a time */
+#define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE (0x00200102) /* ISTWI interrupt recvd. while IDLE */
+#define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE (0x00200103) /* SEP NACK'd, it is busy */
+#define PL_LOGINFO_DA_SEP_DID_NOT_RECEIVE_ACK (0x00200104) /* SEP didn't rcv. ACK (Last Rcvd Bit = 1) */
+#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200105) /* SEP stopped or sent bad chksum in Hdr */
+#define PL_LOGINFO_DA_SEP_STOP_ON_DATA (0x00200106) /* SEP stopped while transfering data */
+#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA (0x00200107) /* SEP stopped while transfering sense data */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200108) /* SEP returned unknown scsi status */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200109) /* SEP returned unknown scsi status */
+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x0020010A) /* SEP returned bad chksum after STOP */
+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x0020010B) /* SEP returned bad chksum after STOP while gettin data*/
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND (0x0020010C) /* SEP doesn't support CDB opcode f/w location 1 */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND_2 (0x0020010D) /* SEP doesn't support CDB opcode f/w location 2 */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND_3 (0x0020010E) /* SEP doesn't support CDB opcode f/w location 3 */
/****************************************************************************/
diff --git a/drivers/message/fusion/lsi/mpi_sas.h b/drivers/message/fusion/lsi/mpi_sas.h
index 50b8f0a8f456..8e990a0fa7a2 100644
--- a/drivers/message/fusion/lsi/mpi_sas.h
+++ b/drivers/message/fusion/lsi/mpi_sas.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2004 LSI Logic Corporation.
+ * Copyright (c) 2004-2006 LSI Logic Corporation.
*
*
* Name: mpi_sas.h
* Title: MPI Serial Attached SCSI structures and definitions
* Creation Date: August 19, 2004
*
- * mpi_sas.h Version: 01.05.03
+ * mpi_sas.h Version: 01.05.04
*
* Version History
* ---------------
@@ -21,6 +21,8 @@
* and Remove Device operations to SAS IO Unit Control.
* Added DevHandle field to SAS IO Unit Control request and
* reply.
+ * 10-11-06 01.05.04 Fixed the name of a define for Operation field of SAS IO
+ * Unit Control request.
* --------------------------------------------------------------------------
*/
@@ -237,7 +239,8 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST
#define MPI_SAS_OP_SEND_PRIMITIVE (0x0A)
#define MPI_SAS_OP_FORCE_FULL_DISCOVERY (0x0B)
#define MPI_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C)
-#define MPI_SAS_OP_TRANSMIT_REMOVE_DEVICE (0x0D)
+#define MPI_SAS_OP_TRANSMIT_REMOVE_DEVICE (0x0D) /* obsolete name */
+#define MPI_SAS_OP_REMOVE_DEVICE (0x0D)
/* values for the PrimFlags field */
#define MPI_SAS_PRIMFLAGS_SINGLE (0x08)
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index b3f28a03b6a9..083acfd91d8b 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -6,7 +6,7 @@
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Copyright (c) 1999-2007 LSI Logic Corporation
- * (mailto:mpt_linux_developer@lsil.com)
+ * (mailto:mpt_linux_developer@lsi.com)
*
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -82,6 +82,10 @@ static int mpt_msi_enable;
module_param(mpt_msi_enable, int, 0);
MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
+static int mpt_channel_mapping;
+module_param(mpt_channel_mapping, int, 0);
+MODULE_PARM_DESC(mpt_channel_mapping, " Mapping id's to channels (default=0)");
+
#ifdef MFCNT
static int mfcounter = 0;
#define PRINT_MF_COUNT 20000
@@ -173,11 +177,14 @@ static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
//int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
-static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
+#ifdef MPT_DEBUG_REPLY
+static void mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
+#endif
static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
+static void mpt_inactive_raid_list_free(MPT_ADAPTER *ioc);
/* module entry point */
static int __init fusion_init (void);
@@ -319,13 +326,11 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
else if (ioc->bus_type == SAS)
mpt_sas_log_info(ioc, log_info);
}
- if (ioc_stat & MPI_IOCSTATUS_MASK) {
- if (ioc->bus_type == SPI &&
- cb_idx != mpt_stm_index &&
- cb_idx != mpt_lan_index)
- mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
- }
+#ifdef MPT_DEBUG_REPLY
+ if (ioc_stat & MPI_IOCSTATUS_MASK)
+ mpt_iocstatus_info(ioc, (u32)ioc_stat, mf);
+#endif
/* Check for (valid) IO callback! */
if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
@@ -911,7 +916,7 @@ mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
int
mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
{
- int r = 0;
+ int r = 0;
u8 *req_as_bytes;
int ii;
@@ -1811,6 +1816,13 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
* and we try GetLanConfigPages again...
*/
if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
+
+ /*
+ * Initalize link list for inactive raid volumes.
+ */
+ init_MUTEX(&ioc->raid_data.inactive_list_mutex);
+ INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
+
if (ioc->bus_type == SAS) {
/* clear persistency table */
@@ -2017,6 +2029,8 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
}
kfree(ioc->spi_data.nvram);
+ mpt_inactive_raid_list_free(ioc);
+ kfree(ioc->raid_data.pIocPg2);
kfree(ioc->raid_data.pIocPg3);
ioc->spi_data.nvram = NULL;
ioc->raid_data.pIocPg3 = NULL;
@@ -2413,6 +2427,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
facts->ProductID = le16_to_cpu(facts->ProductID);
+ if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
+ > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
+ ioc->ir_firmware = 1;
facts->CurrentHostMfaHighAddr =
le32_to_cpu(facts->CurrentHostMfaHighAddr);
facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
@@ -2505,6 +2522,7 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
int ii;
int req_sz;
int reply_sz;
+ int max_id;
/* IOC *must* NOT be in RESET state! */
if (ioc->last_state == MPI_IOC_STATE_RESET) {
@@ -2552,6 +2570,21 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
+ max_id = (ioc->bus_type == SAS) ? pfacts->PortSCSIID :
+ pfacts->MaxDevices;
+ ioc->devices_per_bus = (max_id > 255) ? 256 : max_id;
+ ioc->number_of_buses = (ioc->devices_per_bus < 256) ? 1 : max_id/256;
+
+ /*
+ * Place all the devices on channels
+ *
+ * (for debuging)
+ */
+ if (mpt_channel_mapping) {
+ ioc->devices_per_bus = 1;
+ ioc->number_of_buses = (max_id > 255) ? 255 : max_id;
+ }
+
return 0;
}
@@ -2592,13 +2625,8 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
ioc->name, ioc->upload_fw, ioc->facts.Flags));
- if(ioc->bus_type == SAS)
- ioc_init.MaxDevices = ioc->facts.MaxDevices;
- else if(ioc->bus_type == FC)
- ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
- else
- ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
- ioc_init.MaxBuses = MPT_MAX_BUS;
+ ioc_init.MaxDevices = (U8)ioc->devices_per_bus;
+ ioc_init.MaxBuses = (U8)ioc->number_of_buses;
dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
ioc->name, ioc->facts.MsgVersion));
if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
@@ -2720,9 +2748,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
/* RAID FW may take a long time to enable
*/
- if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
- > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) ||
- (ioc->bus_type == SAS)) {
+ if (ioc->ir_firmware || ioc->bus_type == SAS) {
rc = mpt_handshake_req_reply_wait(ioc, req_sz,
(u32*)&port_enable, reply_sz, (u16*)&reply_buf,
300 /*seconds*/, sleepFlag);
@@ -3193,6 +3219,9 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
u32 diag1val = 0;
#endif
+ /* Clear any existing interrupts */
+ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+
if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
"address=%p\n", ioc->name, __FUNCTION__,
@@ -3212,7 +3241,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
" count=%d\n",
ioc->name, doorbell, count));
if (doorbell == MPI_IOC_STATE_READY) {
- return 0;
+ return 1;
}
/* wait 1 sec */
@@ -3224,9 +3253,6 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
return -1;
}
- /* Clear any existing interrupts */
- CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
-
/* Use "Diagnostic reset" method! (only thing available!) */
diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
@@ -3942,7 +3968,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
}
} else {
while (--cntdn) {
- mdelay (1);
+ udelay (1000);
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
break;
@@ -3994,7 +4020,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
break;
- mdelay(1);
+ udelay (1000);
count++;
}
}
@@ -4310,8 +4336,8 @@ mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
(reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
- printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n",
- ioc->name, disk);
+ printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d id=%d\n",
+ ioc->name, disk, volume);
} else {
printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
ioc->name, volume);
@@ -4712,7 +4738,187 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
return 0;
}
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mpt_inactive_raid_list_free
+ *
+ * This clears this link list.
+ *
+ * @ioc - pointer to per adapter structure
+ *
+ **/
+static void
+mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
+{
+ struct inactive_raid_component_info *component_info, *pNext;
+
+ if (list_empty(&ioc->raid_data.inactive_list))
+ return;
+
+ down(&ioc->raid_data.inactive_list_mutex);
+ list_for_each_entry_safe(component_info, pNext,
+ &ioc->raid_data.inactive_list, list) {
+ list_del(&component_info->list);
+ kfree(component_info);
+ }
+ up(&ioc->raid_data.inactive_list_mutex);
+}
+
+/**
+ * mpt_inactive_raid_volumes
+ *
+ * This sets up link list of phy_disk_nums for devices belonging in an inactive volume
+ *
+ * @ioc - pointer to per adapter structure
+ * @channel - volume channel
+ * @id - volume target id
+ *
+ *
+ **/
+static void
+mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
+{
+ CONFIGPARMS cfg;
+ ConfigPageHeader_t hdr;
+ dma_addr_t dma_handle;
+ pRaidVolumePage0_t buffer = NULL;
+ int i;
+ RaidPhysDiskPage0_t phys_disk;
+ struct inactive_raid_component_info *component_info;
+ int handle_inactive_volumes;
+
+ memset(&cfg, 0 , sizeof(CONFIGPARMS));
+ memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+ hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
+ cfg.pageAddr = (channel << 8) + id;
+ cfg.cfghdr.hdr = &hdr;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+
+ if (mpt_config(ioc, &cfg) != 0)
+ goto out;
+
+ if (!hdr.PageLength)
+ goto out;
+
+ buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
+ &dma_handle);
+
+ if (!buffer)
+ goto out;
+
+ cfg.physAddr = dma_handle;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+ if (mpt_config(ioc, &cfg) != 0)
+ goto out;
+
+ if (!buffer->NumPhysDisks)
+ goto out;
+
+ handle_inactive_volumes =
+ (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE ||
+ (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) == 0 ||
+ buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_FAILED ||
+ buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_MISSING) ? 1 : 0;
+
+ if (!handle_inactive_volumes)
+ goto out;
+
+ down(&ioc->raid_data.inactive_list_mutex);
+ for (i = 0; i < buffer->NumPhysDisks; i++) {
+ if(mpt_raid_phys_disk_pg0(ioc,
+ buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
+ continue;
+
+ if ((component_info = kmalloc(sizeof (*component_info),
+ GFP_KERNEL)) == NULL)
+ continue;
+
+ component_info->volumeID = id;
+ component_info->volumeBus = channel;
+ component_info->d.PhysDiskNum = phys_disk.PhysDiskNum;
+ component_info->d.PhysDiskBus = phys_disk.PhysDiskBus;
+ component_info->d.PhysDiskID = phys_disk.PhysDiskID;
+ component_info->d.PhysDiskIOC = phys_disk.PhysDiskIOC;
+
+ list_add_tail(&component_info->list,
+ &ioc->raid_data.inactive_list);
+ }
+ up(&ioc->raid_data.inactive_list_mutex);
+
+ out:
+ if (buffer)
+ pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
+ dma_handle);
+}
+
+/**
+ * mpt_raid_phys_disk_pg0 - returns phys disk page zero
+ * @ioc: Pointer to a Adapter Structure
+ * @phys_disk_num: io unit unique phys disk num generated by the ioc
+ * @phys_disk: requested payload data returned
+ *
+ * Return:
+ * 0 on success
+ * -EFAULT if read of config page header fails or data pointer not NULL
+ * -ENOMEM if pci_alloc failed
+ **/
+int
+mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk)
+{
+ CONFIGPARMS cfg;
+ ConfigPageHeader_t hdr;
+ dma_addr_t dma_handle;
+ pRaidPhysDiskPage0_t buffer = NULL;
+ int rc;
+
+ memset(&cfg, 0 , sizeof(CONFIGPARMS));
+ memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+
+ hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
+ cfg.cfghdr.hdr = &hdr;
+ cfg.physAddr = -1;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+
+ if (mpt_config(ioc, &cfg) != 0) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ if (!hdr.PageLength) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
+ &dma_handle);
+
+ if (!buffer) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ cfg.physAddr = dma_handle;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+ cfg.pageAddr = phys_disk_num;
+
+ if (mpt_config(ioc, &cfg) != 0) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ rc = 0;
+ memcpy(phys_disk, buffer, sizeof(*buffer));
+ phys_disk->MaxLBA = le32_to_cpu(buffer->MaxLBA);
+
+ out:
+
+ if (buffer)
+ pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
+ dma_handle);
+
+ return rc;
+}
+
/**
* mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
* @ioc: Pointer to a Adapter Strucutre
@@ -4722,21 +4928,27 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
* 0 on success
* -EFAULT if read of config page header fails or data pointer not NULL
* -ENOMEM if pci_alloc failed
- */
+ **/
int
mpt_findImVolumes(MPT_ADAPTER *ioc)
{
IOCPage2_t *pIoc2;
u8 *mem;
- ConfigPageIoc2RaidVol_t *pIocRv;
dma_addr_t ioc2_dma;
CONFIGPARMS cfg;
ConfigPageHeader_t header;
- int jj;
int rc = 0;
int iocpage2sz;
- u8 nVols, nPhys;
- u8 vid, vbus, vioc;
+ int i;
+
+ if (!ioc->ir_firmware)
+ return 0;
+
+ /* Free the old page
+ */
+ kfree(ioc->raid_data.pIocPg2);
+ ioc->raid_data.pIocPg2 = NULL;
+ mpt_inactive_raid_list_free(ioc);
/* Read IOCP2 header then the page.
*/
@@ -4764,55 +4976,23 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
cfg.physAddr = ioc2_dma;
if (mpt_config(ioc, &cfg) != 0)
- goto done_and_free;
+ goto out;
+
+ mem = kmalloc(iocpage2sz, GFP_KERNEL);
+ if (!mem)
+ goto out;
- if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
- mem = kmalloc(iocpage2sz, GFP_ATOMIC);
- if (mem) {
- ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
- } else {
- goto done_and_free;
- }
- }
memcpy(mem, (u8 *)pIoc2, iocpage2sz);
+ ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
- /* Identify RAID Volume Id's */
- nVols = pIoc2->NumActiveVolumes;
- if ( nVols == 0) {
- /* No RAID Volume.
- */
- goto done_and_free;
- } else {
- /* At least 1 RAID Volume
- */
- pIocRv = pIoc2->RaidVolume;
- ioc->raid_data.isRaid = 0;
- for (jj = 0; jj < nVols; jj++, pIocRv++) {
- vid = pIocRv->VolumeID;
- vbus = pIocRv->VolumeBus;
- vioc = pIocRv->VolumeIOC;
-
- /* find the match
- */
- if (vbus == 0) {
- ioc->raid_data.isRaid |= (1 << vid);
- } else {
- /* Error! Always bus 0
- */
- }
- }
- }
+ mpt_read_ioc_pg_3(ioc);
- /* Identify Hidden Physical Disk Id's */
- nPhys = pIoc2->NumActivePhysDisks;
- if (nPhys == 0) {
- /* No physical disks.
- */
- } else {
- mpt_read_ioc_pg_3(ioc);
- }
+ for (i = 0; i < pIoc2->NumActiveVolumes ; i++)
+ mpt_inactive_raid_volumes(ioc,
+ pIoc2->RaidVolume[i].VolumeBus,
+ pIoc2->RaidVolume[i].VolumeID);
-done_and_free:
+ out:
pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
return rc;
@@ -4865,7 +5045,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
cfg.physAddr = ioc3_dma;
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
if (mpt_config(ioc, &cfg) == 0) {
- mem = kmalloc(iocpage3sz, GFP_ATOMIC);
+ mem = kmalloc(iocpage3sz, GFP_KERNEL);
if (mem) {
memcpy(mem, (u8 *)pIoc3, iocpage3sz);
ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
@@ -5679,8 +5859,6 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
return rc;
}
-# define EVENT_DESCR_STR_SZ 100
-
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
static void
EventDescriptionStr(u8 event, u32 evData0, char *evStr)
@@ -5708,9 +5886,6 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
break;
case MPI_EVENT_RESCAN:
ds = "Bus Rescan Event";
- /* Ok, do we need to do anything here? As far as
- I can tell, this is when a new device gets added
- to the loop. */
break;
case MPI_EVENT_LINK_STATUS_CHANGE:
if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
@@ -5787,48 +5962,63 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
{
u8 id = (u8)(evData0);
+ u8 channel = (u8)(evData0 >> 8);
u8 ReasonCode = (u8)(evData0 >> 16);
switch (ReasonCode) {
case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
snprintf(evStr, EVENT_DESCR_STR_SZ,
- "SAS Device Status Change: Added: id=%d", id);
+ "SAS Device Status Change: Added: "
+ "id=%d channel=%d", id, channel);
break;
case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
snprintf(evStr, EVENT_DESCR_STR_SZ,
- "SAS Device Status Change: Deleted: id=%d", id);
+ "SAS Device Status Change: Deleted: "
+ "id=%d channel=%d", id, channel);
break;
case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
snprintf(evStr, EVENT_DESCR_STR_SZ,
- "SAS Device Status Change: SMART Data: id=%d",
- id);
+ "SAS Device Status Change: SMART Data: "
+ "id=%d channel=%d", id, channel);
break;
case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
snprintf(evStr, EVENT_DESCR_STR_SZ,
- "SAS Device Status Change: No Persistancy: id=%d", id);
+ "SAS Device Status Change: No Persistancy: "
+ "id=%d channel=%d", id, channel);
+ break;
+ case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS Device Status Change: Unsupported Device "
+ "Discovered : id=%d channel=%d", id, channel);
break;
case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
snprintf(evStr, EVENT_DESCR_STR_SZ,
- "SAS Device Status Change: Internal Device Reset : id=%d", id);
+ "SAS Device Status Change: Internal Device "
+ "Reset : id=%d channel=%d", id, channel);
break;
case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
snprintf(evStr, EVENT_DESCR_STR_SZ,
- "SAS Device Status Change: Internal Task Abort : id=%d", id);
+ "SAS Device Status Change: Internal Task "
+ "Abort : id=%d channel=%d", id, channel);
break;
case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
snprintf(evStr, EVENT_DESCR_STR_SZ,
- "SAS Device Status Change: Internal Abort Task Set : id=%d", id);
+ "SAS Device Status Change: Internal Abort "
+ "Task Set : id=%d channel=%d", id, channel);
break;
case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
snprintf(evStr, EVENT_DESCR_STR_SZ,
- "SAS Device Status Change: Internal Clear Task Set : id=%d", id);
+ "SAS Device Status Change: Internal Clear "
+ "Task Set : id=%d channel=%d", id, channel);
break;
case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
snprintf(evStr, EVENT_DESCR_STR_SZ,
- "SAS Device Status Change: Internal Query Task : id=%d", id);
+ "SAS Device Status Change: Internal Query "
+ "Task : id=%d channel=%d", id, channel);
break;
default:
snprintf(evStr, EVENT_DESCR_STR_SZ,
- "SAS Device Status Change: Unknown: id=%d", id);
+ "SAS Device Status Change: Unknown: "
+ "id=%d channel=%d", id, channel);
break;
}
break;
@@ -5837,8 +6027,16 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
ds = "Bus Timer Expired";
break;
case MPI_EVENT_QUEUE_FULL:
- ds = "Queue Full";
+ {
+ u16 curr_depth = (u16)(evData0 >> 16);
+ u8 channel = (u8)(evData0 >> 8);
+ u8 id = (u8)(evData0);
+
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "Queue Full: channel=%d id=%d depth=%d",
+ channel, id, curr_depth);
break;
+ }
case MPI_EVENT_SAS_SES:
ds = "SAS SES Event";
break;
@@ -5942,6 +6140,76 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
ds = "SAS Log Entry Added";
break;
+ case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
+ {
+ u8 phy_num = (u8)(evData0);
+ u8 port_num = (u8)(evData0 >> 8);
+ u8 port_width = (u8)(evData0 >> 16);
+ u8 primative = (u8)(evData0 >> 24);
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS Broadcase Primative: phy=%d port=%d "
+ "width=%d primative=0x%02x",
+ phy_num, port_num, port_width, primative);
+ break;
+ }
+
+ case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
+ {
+ u8 reason = (u8)(evData0);
+ u8 port_num = (u8)(evData0 >> 8);
+ u16 handle = le16_to_cpu(evData0 >> 16);
+
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS Initiator Device Status Change: reason=0x%02x "
+ "port=%d handle=0x%04x",
+ reason, port_num, handle);
+ break;
+ }
+
+ case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW:
+ {
+ u8 max_init = (u8)(evData0);
+ u8 current_init = (u8)(evData0 >> 8);
+
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS Initiator Device Table Overflow: max initiators=%02d "
+ "current initators=%02d",
+ max_init, current_init);
+ break;
+ }
+ case MPI_EVENT_SAS_SMP_ERROR:
+ {
+ u8 status = (u8)(evData0);
+ u8 port_num = (u8)(evData0 >> 8);
+ u8 result = (u8)(evData0 >> 16);
+
+ if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID)
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS SMP Error: port=%d result=0x%02x",
+ port_num, result);
+ else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR)
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS SMP Error: port=%d : CRC Error",
+ port_num);
+ else if (status == MPI_EVENT_SAS_SMP_TIMEOUT)
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS SMP Error: port=%d : Timeout",
+ port_num);
+ else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION)
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS SMP Error: port=%d : No Destination",
+ port_num);
+ else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION)
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS SMP Error: port=%d : Bad Destination",
+ port_num);
+ else
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS SMP Error: port=%d : status=0x%02x",
+ port_num, status);
+ break;
+ }
+
/*
* MPT base "custom" events may be added here...
*/
@@ -6205,10 +6473,11 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
"Abort", /* 12h */
"IO Not Yet Executed", /* 13h */
"IO Executed", /* 14h */
- "Persistent Reservation Out Not Affiliation Owner", /* 15h */
+ "Persistent Reservation Out Not Affiliation "
+ "Owner", /* 15h */
"Open Transmit DMA Abort", /* 16h */
"IO Device Missing Delay Retry", /* 17h */
- NULL, /* 18h */
+ "IO Cancelled Due to Recieve Error", /* 18h */
NULL, /* 19h */
NULL, /* 1Ah */
NULL, /* 1Bh */
@@ -6218,6 +6487,96 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
NULL, /* 1Fh */
"Enclosure Management" /* 20h */
};
+ static char *ir_code_str[] = {
+ "Raid Action Error", /* 00h */
+ NULL, /* 00h */
+ NULL, /* 01h */
+ NULL, /* 02h */
+ NULL, /* 03h */
+ NULL, /* 04h */
+ NULL, /* 05h */
+ NULL, /* 06h */
+ NULL /* 07h */
+ };
+ static char *raid_sub_code_str[] = {
+ NULL, /* 00h */
+ "Volume Creation Failed: Data Passed too "
+ "Large", /* 01h */
+ "Volume Creation Failed: Duplicate Volumes "
+ "Attempted", /* 02h */
+ "Volume Creation Failed: Max Number "
+ "Supported Volumes Exceeded", /* 03h */
+ "Volume Creation Failed: DMA Error", /* 04h */
+ "Volume Creation Failed: Invalid Volume Type", /* 05h */
+ "Volume Creation Failed: Error Reading "
+ "MFG Page 4", /* 06h */
+ "Volume Creation Failed: Creating Internal "
+ "Structures", /* 07h */
+ NULL, /* 08h */
+ NULL, /* 09h */
+ NULL, /* 0Ah */
+ NULL, /* 0Bh */
+ NULL, /* 0Ch */
+ NULL, /* 0Dh */
+ NULL, /* 0Eh */
+ NULL, /* 0Fh */
+ "Activation failed: Already Active Volume", /* 10h */
+ "Activation failed: Unsupported Volume Type", /* 11h */
+ "Activation failed: Too Many Active Volumes", /* 12h */
+ "Activation failed: Volume ID in Use", /* 13h */
+ "Activation failed: Reported Failure", /* 14h */
+ "Activation failed: Importing a Volume", /* 15h */
+ NULL, /* 16h */
+ NULL, /* 17h */
+ NULL, /* 18h */
+ NULL, /* 19h */
+ NULL, /* 1Ah */
+ NULL, /* 1Bh */
+ NULL, /* 1Ch */
+ NULL, /* 1Dh */
+ NULL, /* 1Eh */
+ NULL, /* 1Fh */
+ "Phys Disk failed: Too Many Phys Disks", /* 20h */
+ "Phys Disk failed: Data Passed too Large", /* 21h */
+ "Phys Disk failed: DMA Error", /* 22h */
+ "Phys Disk failed: Invalid <channel:id>", /* 23h */
+ "Phys Disk failed: Creating Phys Disk Config "
+ "Page", /* 24h */
+ NULL, /* 25h */
+ NULL, /* 26h */
+ NULL, /* 27h */
+ NULL, /* 28h */
+ NULL, /* 29h */
+ NULL, /* 2Ah */
+ NULL, /* 2Bh */
+ NULL, /* 2Ch */
+ NULL, /* 2Dh */
+ NULL, /* 2Eh */
+ NULL, /* 2Fh */
+ "Compatibility Error: IR Disabled", /* 30h */
+ "Compatibility Error: Inquiry Comand Failed", /* 31h */
+ "Compatibility Error: Device not Direct Access "
+ "Device ", /* 32h */
+ "Compatibility Error: Removable Device Found", /* 33h */
+ "Compatibility Error: Device SCSI Version not "
+ "2 or Higher", /* 34h */
+ "Compatibility Error: SATA Device, 48 BIT LBA "
+ "not Supported", /* 35h */
+ "Compatibility Error: Device doesn't have "
+ "512 Byte Block Sizes", /* 36h */
+ "Compatibility Error: Volume Type Check Failed", /* 37h */
+ "Compatibility Error: Volume Type is "
+ "Unsupported by FW", /* 38h */
+ "Compatibility Error: Disk Drive too Small for "
+ "use in Volume", /* 39h */
+ "Compatibility Error: Phys Disk for Create "
+ "Volume not Found", /* 3Ah */
+ "Compatibility Error: Too Many or too Few "
+ "Disks for Volume Type", /* 3Bh */
+ "Compatibility Error: Disk stripe Sizes "
+ "Must be 64KB", /* 3Ch */
+ "Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */
+ };
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
@@ -6226,7 +6585,7 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
* @log_info: U32 LogInfo reply word from the IOC
*
* Refer to lsi/mpi_log_sas.h.
- */
+ **/
static void
mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
{
@@ -6240,56 +6599,165 @@ union loginfo_type {
}dw;
};
union loginfo_type sas_loginfo;
+ char *originator_desc = NULL;
char *code_desc = NULL;
+ char *sub_code_desc = NULL;
sas_loginfo.loginfo = log_info;
if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
(sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
return;
- if ((sas_loginfo.dw.originator == 0 /*IOP*/) &&
- (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) {
- code_desc = iop_code_str[sas_loginfo.dw.code];
- }else if ((sas_loginfo.dw.originator == 1 /*PL*/) &&
- (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) {
- code_desc = pl_code_str[sas_loginfo.dw.code];
+
+ originator_desc = originator_str[sas_loginfo.dw.originator];
+
+ switch (sas_loginfo.dw.originator) {
+
+ case 0: /* IOP */
+ if (sas_loginfo.dw.code <
+ sizeof(iop_code_str)/sizeof(char*))
+ code_desc = iop_code_str[sas_loginfo.dw.code];
+ break;
+ case 1: /* PL */
+ if (sas_loginfo.dw.code <
+ sizeof(pl_code_str)/sizeof(char*))
+ code_desc = pl_code_str[sas_loginfo.dw.code];
+ break;
+ case 2: /* IR */
+ if (sas_loginfo.dw.code >=
+ sizeof(ir_code_str)/sizeof(char*))
+ break;
+ code_desc = ir_code_str[sas_loginfo.dw.code];
+ if (sas_loginfo.dw.subcode >=
+ sizeof(raid_sub_code_str)/sizeof(char*))
+ break;
+ if (sas_loginfo.dw.code == 0)
+ sub_code_desc =
+ raid_sub_code_str[sas_loginfo.dw.subcode];
+ break;
+ default:
+ return;
}
- if (code_desc != NULL)
+ if (sub_code_desc != NULL)
+ printk(MYIOC_s_INFO_FMT
+ "LogInfo(0x%08x): Originator={%s}, Code={%s},"
+ " SubCode={%s}\n",
+ ioc->name, log_info, originator_desc, code_desc,
+ sub_code_desc);
+ else if (code_desc != NULL)
printk(MYIOC_s_INFO_FMT
"LogInfo(0x%08x): Originator={%s}, Code={%s},"
" SubCode(0x%04x)\n",
- ioc->name,
- log_info,
- originator_str[sas_loginfo.dw.originator],
- code_desc,
+ ioc->name, log_info, originator_desc, code_desc,
sas_loginfo.dw.subcode);
else
printk(MYIOC_s_INFO_FMT
"LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
" SubCode(0x%04x)\n",
- ioc->name,
- log_info,
- originator_str[sas_loginfo.dw.originator],
- sas_loginfo.dw.code,
- sas_loginfo.dw.subcode);
+ ioc->name, log_info, originator_desc,
+ sas_loginfo.dw.code, sas_loginfo.dw.subcode);
}
+#ifdef MPT_DEBUG_REPLY
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
- * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
+ * mpt_iocstatus_info_config - IOCSTATUS information for config pages
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * ioc_status: U32 IOCStatus word from IOC
+ * @mf: Pointer to MPT request frame
+ *
+ * Refer to lsi/mpi.h.
+ **/
+static void
+mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
+{
+ Config_t *pReq = (Config_t *)mf;
+ char extend_desc[EVENT_DESCR_STR_SZ];
+ char *desc = NULL;
+ u32 form;
+ u8 page_type;
+
+ if (pReq->Header.PageType == MPI_CONFIG_PAGETYPE_EXTENDED)
+ page_type = pReq->ExtPageType;
+ else
+ page_type = pReq->Header.PageType;
+
+ /*
+ * ignore invalid page messages for GET_NEXT_HANDLE
+ */
+ form = le32_to_cpu(pReq->PageAddress);
+ if (ioc_status == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
+ if (page_type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE ||
+ page_type == MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER ||
+ page_type == MPI_CONFIG_EXTPAGETYPE_ENCLOSURE) {
+ if ((form >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT) ==
+ MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE)
+ return;
+ }
+ if (page_type == MPI_CONFIG_PAGETYPE_FC_DEVICE)
+ if ((form & MPI_FC_DEVICE_PGAD_FORM_MASK) ==
+ MPI_FC_DEVICE_PGAD_FORM_NEXT_DID)
+ return;
+ }
+
+ snprintf(extend_desc, EVENT_DESCR_STR_SZ,
+ "type=%02Xh, page=%02Xh, action=%02Xh, form=%08Xh",
+ page_type, pReq->Header.PageNumber, pReq->Action, form);
+
+ switch (ioc_status) {
+
+ case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
+ desc = "Config Page Invalid Action";
+ break;
+
+ case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
+ desc = "Config Page Invalid Type";
+ break;
+
+ case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
+ desc = "Config Page Invalid Page";
+ break;
+
+ case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
+ desc = "Config Page Invalid Data";
+ break;
+
+ case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
+ desc = "Config Page No Defaults";
+ break;
+
+ case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
+ desc = "Config Page Can't Commit";
+ break;
+ }
+
+ if (!desc)
+ return;
+
+ printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n",
+ ioc->name, ioc_status, desc, extend_desc);
+}
+
+/**
+ * mpt_iocstatus_info - IOCSTATUS information returned from IOC.
* @ioc: Pointer to MPT_ADAPTER structure
* @ioc_status: U32 IOCStatus word from IOC
* @mf: Pointer to MPT request frame
*
* Refer to lsi/mpi.h.
- */
+ **/
static void
-mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
+mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
{
u32 status = ioc_status & MPI_IOCSTATUS_MASK;
char *desc = NULL;
switch (status) {
+
+/****************************************************************************/
+/* Common IOCStatus values for all replies */
+/****************************************************************************/
+
case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
desc = "Invalid Function";
break;
@@ -6322,84 +6790,180 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
desc = "Invalid State";
break;
+/****************************************************************************/
+/* Config IOCStatus values */
+/****************************************************************************/
+
case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
- /* No message for Config IOCStatus values */
+ mpt_iocstatus_info_config(ioc, status, mf);
break;
+/****************************************************************************/
+/* SCSIIO Reply (SPI, FCP, SAS) initiator values */
+/* */
+/* Look at mptscsih_iocstatus_info_scsiio in mptscsih.c */
+/* */
+/****************************************************************************/
+
case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
- /* No message for recovered error
- desc = "SCSI Recovered Error";
- */
+ case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
+ case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
+ case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
+ case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
+ case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
+ case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
+ case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
+ case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
+ case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
+ case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
+ case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
+ case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
break;
- case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
- desc = "SCSI Invalid Bus";
+/****************************************************************************/
+/* SCSI Target values */
+/****************************************************************************/
+
+ case MPI_IOCSTATUS_TARGET_PRIORITY_IO: /* 0x0060 */
+ desc = "Target: Priority IO";
break;
- case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
- desc = "SCSI Invalid TargetID";
+ case MPI_IOCSTATUS_TARGET_INVALID_PORT: /* 0x0061 */
+ desc = "Target: Invalid Port";
break;
- case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
- {
- SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
- U8 cdb = pScsiReq->CDB[0];
- if (cdb != 0x12) { /* Inquiry is issued for device scanning */
- desc = "SCSI Device Not There";
- }
+ case MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX: /* 0x0062 */
+ desc = "Target Invalid IO Index:";
break;
- }
- case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
- desc = "SCSI Data Overrun";
+ case MPI_IOCSTATUS_TARGET_ABORTED: /* 0x0063 */
+ desc = "Target: Aborted";
break;
- case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
- /* This error is checked in scsi_io_done(). Skip.
- desc = "SCSI Data Underrun";
- */
+ case MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: /* 0x0064 */
+ desc = "Target: No Conn Retryable";
break;
- case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
- desc = "SCSI I/O Data Error";
+ case MPI_IOCSTATUS_TARGET_NO_CONNECTION: /* 0x0065 */
+ desc = "Target: No Connection";
break;
- case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
- desc = "SCSI Protocol Error";
+ case MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: /* 0x006A */
+ desc = "Target: Transfer Count Mismatch";
break;
- case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
- desc = "SCSI Task Terminated";
+ case MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT: /* 0x006B */
+ desc = "Target: STS Data not Sent";
break;
- case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
- desc = "SCSI Residual Mismatch";
+ case MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: /* 0x006D */
+ desc = "Target: Data Offset Error";
break;
- case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
- desc = "SCSI Task Management Failed";
+ case MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: /* 0x006E */
+ desc = "Target: Too Much Write Data";
break;
- case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
- desc = "SCSI IOC Terminated";
+ case MPI_IOCSTATUS_TARGET_IU_TOO_SHORT: /* 0x006F */
+ desc = "Target: IU Too Short";
break;
- case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
- desc = "SCSI Ext Terminated";
+ case MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: /* 0x0070 */
+ desc = "Target: ACK NAK Timeout";
+ break;
+
+ case MPI_IOCSTATUS_TARGET_NAK_RECEIVED: /* 0x0071 */
+ desc = "Target: Nak Received";
+ break;
+
+/****************************************************************************/
+/* Fibre Channel Direct Access values */
+/****************************************************************************/
+
+ case MPI_IOCSTATUS_FC_ABORTED: /* 0x0066 */
+ desc = "FC: Aborted";
+ break;
+
+ case MPI_IOCSTATUS_FC_RX_ID_INVALID: /* 0x0067 */
+ desc = "FC: RX ID Invalid";
+ break;
+
+ case MPI_IOCSTATUS_FC_DID_INVALID: /* 0x0068 */
+ desc = "FC: DID Invalid";
+ break;
+
+ case MPI_IOCSTATUS_FC_NODE_LOGGED_OUT: /* 0x0069 */
+ desc = "FC: Node Logged Out";
+ break;
+
+ case MPI_IOCSTATUS_FC_EXCHANGE_CANCELED: /* 0x006C */
+ desc = "FC: Exchange Canceled";
+ break;
+
+/****************************************************************************/
+/* LAN values */
+/****************************************************************************/
+
+ case MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND: /* 0x0080 */
+ desc = "LAN: Device not Found";
+ break;
+
+ case MPI_IOCSTATUS_LAN_DEVICE_FAILURE: /* 0x0081 */
+ desc = "LAN: Device Failure";
+ break;
+
+ case MPI_IOCSTATUS_LAN_TRANSMIT_ERROR: /* 0x0082 */
+ desc = "LAN: Transmit Error";
+ break;
+
+ case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED: /* 0x0083 */
+ desc = "LAN: Transmit Aborted";
+ break;
+
+ case MPI_IOCSTATUS_LAN_RECEIVE_ERROR: /* 0x0084 */
+ desc = "LAN: Receive Error";
+ break;
+
+ case MPI_IOCSTATUS_LAN_RECEIVE_ABORTED: /* 0x0085 */
+ desc = "LAN: Receive Aborted";
+ break;
+
+ case MPI_IOCSTATUS_LAN_PARTIAL_PACKET: /* 0x0086 */
+ desc = "LAN: Partial Packet";
+ break;
+
+ case MPI_IOCSTATUS_LAN_CANCELED: /* 0x0087 */
+ desc = "LAN: Canceled";
+ break;
+
+/****************************************************************************/
+/* Serial Attached SCSI values */
+/****************************************************************************/
+
+ case MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED: /* 0x0090 */
+ desc = "SAS: SMP Request Failed";
+ break;
+
+ case MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN: /* 0x0090 */
+ desc = "SAS: SMP Data Overrun";
break;
default:
desc = "Others";
break;
}
- if (desc != NULL)
- printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
+
+ if (!desc)
+ return;
+
+ printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s\n", ioc->name, status, desc);
}
+#endif
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
EXPORT_SYMBOL(mpt_attach);
@@ -6434,6 +6998,7 @@ EXPORT_SYMBOL(mpt_findImVolumes);
EXPORT_SYMBOL(mpt_alloc_fw_memory);
EXPORT_SYMBOL(mpt_free_fw_memory);
EXPORT_SYMBOL(mptbase_sas_persist_operation);
+EXPORT_SYMBOL(mpt_raid_phys_disk_pg0);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index e316708f76bd..e3a39272aad6 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -6,7 +6,7 @@
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Copyright (c) 1999-2007 LSI Logic Corporation
- * (mailto:mpt_linux_developer@lsil.com)
+ * (mailto:mpt_linux_developer@lsi.com)
*
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -75,8 +75,8 @@
#define COPYRIGHT "Copyright (c) 1999-2007 " MODULEAUTHOR
#endif
-#define MPT_LINUX_VERSION_COMMON "3.04.03"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.03"
+#define MPT_LINUX_VERSION_COMMON "3.04.04"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.04"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
@@ -172,6 +172,9 @@
#define MPT_SCSI_SG_DEPTH 40
#endif
+/* debug print string length used for events and iocstatus */
+# define EVENT_DESCR_STR_SZ 100
+
#ifdef __KERNEL__ /* { */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -334,8 +337,8 @@ typedef struct _VirtTarget {
struct scsi_target *starget;
u8 tflags;
u8 ioc_id;
- u8 target_id;
- u8 bus_id;
+ u8 id;
+ u8 channel;
u8 minSyncFactor; /* 0xFF is async */
u8 maxOffset; /* 0 if async */
u8 maxWidth; /* 0 if narrow, 1 if wide */
@@ -344,13 +347,12 @@ typedef struct _VirtTarget {
u8 type; /* byte 0 of Inquiry data */
u8 deleted; /* target in process of being removed */
u32 num_luns;
- u32 luns[8]; /* Max LUNs is 256 */
} VirtTarget;
typedef struct _VirtDevice {
VirtTarget *vtarget;
u8 configured_lun;
- u32 lun;
+ int lun;
} VirtDevice;
/*
@@ -412,7 +414,7 @@ typedef struct _MPT_IOCTL {
u8 rsvd;
u8 status; /* current command status */
u8 reset; /* 1 if bus reset allowed */
- u8 target; /* target for reset */
+ u8 id; /* target for reset */
struct mutex ioctl_mutex;
} MPT_IOCTL;
@@ -483,10 +485,24 @@ typedef struct _SasCfgData {
*/
}SasCfgData;
+/*
+ * Inactive volume link list of raid component data
+ * @inactive_list
+ */
+struct inactive_raid_component_info {
+ struct list_head list;
+ u8 volumeID; /* volume target id */
+ u8 volumeBus; /* volume channel */
+ IOC_3_PHYS_DISK d; /* phys disk info */
+};
+
typedef struct _RaidCfgData {
IOCPage2_t *pIocPg2; /* table of Raid Volumes */
IOCPage3_t *pIocPg3; /* table of physical disks */
- int isRaid; /* bit field, 1 if RAID */
+ struct semaphore inactive_list_mutex;
+ struct list_head inactive_list; /* link list for physical
+ disk that belong in
+ inactive volumes */
}RaidCfgData;
typedef struct _FcCfgData {
@@ -528,6 +544,8 @@ typedef struct _MPT_ADAPTER
u32 mem_phys; /* == f4020000 (mmap) */
u32 pio_mem_phys; /* Programmed IO (downloadboot) */
int mem_size; /* mmap memory size */
+ int number_of_buses;
+ int devices_per_bus;
int alloc_total;
u32 last_state;
int active;
@@ -607,6 +625,8 @@ typedef struct _MPT_ADAPTER
u8 persist_reply_frame[MPT_DEFAULT_FRAME_SIZE]; /* persist reply */
LANPage0_t lan_cnfg_page0;
LANPage1_t lan_cnfg_page1;
+
+ u8 ir_firmware; /* =1 if IR firmware detected */
/*
* Description: errata_flag_1064
* If a PCIX read occurs within 1 or 2 cycles after the chip receives
@@ -790,12 +810,6 @@ typedef struct _mpt_sge {
#define ddvprintk(x)
#endif
-#ifdef MPT_DEBUG_NEGO
-#define dnegoprintk(x) printk x
-#else
-#define dnegoprintk(x)
-#endif
-
#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
#define ddvtprintk(x) printk x
#else
@@ -957,7 +971,6 @@ typedef struct _MPT_SCSI_HOST {
int port;
u32 pad0;
struct scsi_cmnd **ScsiLookup;
- VirtTarget **Targets;
MPT_LOCAL_REPLY *pLocal; /* used for internal commands */
struct timer_list timer;
/* Pool of memory for holding SCpnts before doing
@@ -981,6 +994,7 @@ typedef struct _MPT_SCSI_HOST {
int scandv_wait_done;
long last_queue_full;
u16 tm_iocstatus;
+ struct list_head target_reset_list;
} MPT_SCSI_HOST;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1046,6 +1060,7 @@ extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size);
extern void mpt_free_fw_memory(MPT_ADAPTER *ioc);
extern int mpt_findImVolumes(MPT_ADAPTER *ioc);
extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
+extern int mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk);
/*
* Public data decl's...
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 504632da4347..9d0f30478e46 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -5,7 +5,7 @@
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Copyright (c) 1999-2007 LSI Logic Corporation
- * (mailto:mpt_linux_developer@lsil.com)
+ * (mailto:mpt_linux_developer@lsi.com)
*
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -313,7 +313,7 @@ static void mptctl_timeout_expired (MPT_IOCTL *ioctl)
*/
dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
ioctl->ioc->name));
- mpt_HardResetHandler(ioctl->ioc, NO_SLEEP);
+ mpt_HardResetHandler(ioctl->ioc, CAN_SLEEP);
}
return;
@@ -361,7 +361,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
ioctl->ioc->name, mf));
pScsiTm = (SCSITaskMgmt_t *) mf;
- pScsiTm->TargetID = ioctl->target;
+ pScsiTm->TargetID = ioctl->id;
pScsiTm->Bus = hd->port; /* 0 */
pScsiTm->ChainOffset = 0;
pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
@@ -1159,15 +1159,12 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
struct mpt_ioctl_iocinfo *karg;
MPT_ADAPTER *ioc;
struct pci_dev *pdev;
- struct Scsi_Host *sh;
- MPT_SCSI_HOST *hd;
int iocnum;
- int numDevices = 0;
- unsigned int max_id;
- int ii;
unsigned int port;
int cim_rev;
u8 revision;
+ struct scsi_device *sdev;
+ VirtDevice *vdev;
dctlprintk((": mptctl_getiocinfo called.\n"));
/* Add of PCI INFO results in unaligned access for
@@ -1257,23 +1254,16 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
/* Get number of devices
*/
- if ((sh = ioc->sh) != NULL) {
- /* sh->max_id = maximum target ID + 1
- */
- max_id = sh->max_id - 1;
- hd = (MPT_SCSI_HOST *) sh->hostdata;
-
- /* Check all of the target structures and
- * keep a counter.
- */
- if (hd && hd->Targets) {
- for (ii = 0; ii <= max_id; ii++) {
- if (hd->Targets[ii])
- numDevices++;
- }
+ karg->numDevices = 0;
+ if (ioc->sh) {
+ shost_for_each_device(sdev, ioc->sh) {
+ vdev = sdev->hostdata;
+ if (vdev->vtarget->tflags &
+ MPT_TARGET_FLAGS_RAID_COMPONENT)
+ continue;
+ karg->numDevices++;
}
}
- karg->numDevices = numDevices;
/* Set the BIOS and FW Version
*/
@@ -1319,21 +1309,16 @@ mptctl_gettargetinfo (unsigned long arg)
struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
struct mpt_ioctl_targetinfo karg;
MPT_ADAPTER *ioc;
- struct Scsi_Host *sh;
- MPT_SCSI_HOST *hd;
- VirtTarget *vdev;
+ VirtDevice *vdev;
char *pmem;
int *pdata;
- IOCPage2_t *pIoc2;
- IOCPage3_t *pIoc3;
int iocnum;
int numDevices = 0;
- unsigned int max_id;
- int id, jj, indexed_lun, lun_index;
- u32 lun;
+ int lun;
int maxWordsLeft;
int numBytes;
- u8 port, devType, bus_id;
+ u8 port;
+ struct scsi_device *sdev;
dctlprintk(("mptctl_gettargetinfo called.\n"));
if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) {
@@ -1389,74 +1374,22 @@ mptctl_gettargetinfo (unsigned long arg)
/* Get number of devices
*/
- if ((sh = ioc->sh) != NULL) {
-
- max_id = sh->max_id - 1;
- hd = (MPT_SCSI_HOST *) sh->hostdata;
-
- /* Check all of the target structures.
- * Save the Id and increment the counter,
- * if ptr non-null.
- * sh->max_id = maximum target ID + 1
- */
- if (hd && hd->Targets) {
- mpt_findImVolumes(ioc);
- pIoc2 = ioc->raid_data.pIocPg2;
- for ( id = 0; id <= max_id; ) {
- if ( pIoc2 && pIoc2->NumActiveVolumes ) {
- if ( id == pIoc2->RaidVolume[0].VolumeID ) {
- if (maxWordsLeft <= 0) {
- printk(KERN_ERR "mptctl_gettargetinfo - "
- "buffer is full but volume is available on ioc %d\n, numDevices=%d", iocnum, numDevices);
- goto data_space_full;
- }
- if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 )
- devType = 0x80;
- else
- devType = 0xC0;
- bus_id = pIoc2->RaidVolume[0].VolumeBus;
- numDevices++;
- *pdata = ( (devType << 24) | (bus_id << 8) | id );
- dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
- "volume ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
- pdata++;
- --maxWordsLeft;
- goto next_id;
- } else {
- pIoc3 = ioc->raid_data.pIocPg3;
- for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) {
- if ( pIoc3->PhysDisk[jj].PhysDiskID == id )
- goto next_id;
- }
- }
- }
- if ( (vdev = hd->Targets[id]) ) {
- for (jj = 0; jj <= MPT_LAST_LUN; jj++) {
- lun_index = (jj >> 5);
- indexed_lun = (jj % 32);
- lun = (1 << indexed_lun);
- if (vdev->luns[lun_index] & lun) {
- if (maxWordsLeft <= 0) {
- printk(KERN_ERR "mptctl_gettargetinfo - "
- "buffer is full but more targets are available on ioc %d numDevices=%d\n", iocnum, numDevices);
- goto data_space_full;
- }
- bus_id = vdev->bus_id;
- numDevices++;
- *pdata = ( (jj << 16) | (bus_id << 8) | id );
- dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
- "target ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
- pdata++;
- --maxWordsLeft;
- }
- }
- }
-next_id:
- id++;
- }
+ if (ioc->sh){
+ shost_for_each_device(sdev, ioc->sh) {
+ if (!maxWordsLeft)
+ continue;
+ vdev = sdev->hostdata;
+ if (vdev->vtarget->tflags &
+ MPT_TARGET_FLAGS_RAID_COMPONENT)
+ continue;
+ lun = (vdev->vtarget->raidVolume) ? 0x80 : vdev->lun;
+ *pdata = (((u8)lun << 16) + (vdev->vtarget->channel << 8) +
+ (vdev->vtarget->id ));
+ pdata++;
+ numDevices++;
+ --maxWordsLeft;
}
}
-data_space_full:
karg.numDevices = numDevices;
/* Copy part of the data from kernel memory to user memory
@@ -1821,6 +1754,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
int msgContext;
u16 req_idx;
ulong timeout;
+ struct scsi_device *sdev;
dctlprintk(("mptctl_do_mpt_command called.\n"));
bufIn.kptr = bufOut.kptr = NULL;
@@ -1902,14 +1836,13 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
case MPI_FUNCTION_SCSI_IO_REQUEST:
if (ioc->sh) {
SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
- VirtTarget *pTarget = NULL;
- MPT_SCSI_HOST *hd = NULL;
int qtag = MPI_SCSIIO_CONTROL_UNTAGGED;
int scsidir = 0;
- int target = (int) pScsiReq->TargetID;
int dataSize;
+ u32 id;
- if ((target < 0) || (target >= ioc->sh->max_id)) {
+ id = (ioc->devices_per_bus == 0) ? 256 : ioc->devices_per_bus;
+ if (pScsiReq->TargetID > id) {
printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
"Target ID out of bounds. \n",
__FILE__, __LINE__);
@@ -1917,6 +1850,14 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
goto done_free_mem;
}
+ if (pScsiReq->Bus >= ioc->number_of_buses) {
+ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+ "Target Bus out of bounds. \n",
+ __FILE__, __LINE__);
+ rc = -ENODEV;
+ goto done_free_mem;
+ }
+
pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
pScsiReq->MsgFlags |= mpt_msg_flags();
@@ -1936,13 +1877,15 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
cpu_to_le32(ioc->sense_buf_low_dma
+ (req_idx * MPT_SENSE_BUFFER_ALLOC));
- if ((hd = (MPT_SCSI_HOST *) ioc->sh->hostdata)) {
- if (hd->Targets)
- pTarget = hd->Targets[target];
- }
+ shost_for_each_device(sdev, ioc->sh) {
+ struct scsi_target *starget = scsi_target(sdev);
+ VirtTarget *vtarget = starget->hostdata;
- if (pTarget &&(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
- qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;
+ if ((pScsiReq->TargetID == vtarget->id) &&
+ (pScsiReq->Bus == vtarget->channel) &&
+ (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
+ qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;
+ }
/* Have the IOCTL driver set the direction based
* on the dataOutSize (ordering issue with Sparc).
@@ -1959,7 +1902,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
pScsiReq->DataLength = cpu_to_le32(dataSize);
ioc->ioctl->reset = MPTCTL_RESET_OK;
- ioc->ioctl->target = target;
+ ioc->ioctl->id = pScsiReq->TargetID;
} else {
printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
@@ -2038,7 +1981,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
pScsiReq->DataLength = cpu_to_le32(dataSize);
ioc->ioctl->reset = MPTCTL_RESET_OK;
- ioc->ioctl->target = pScsiReq->TargetID;
+ ioc->ioctl->id = pScsiReq->TargetID;
} else {
printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
"SCSI driver is not loaded. \n",
@@ -2719,7 +2662,7 @@ mptctl_hp_targetinfo(unsigned long arg)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static struct file_operations mptctl_fops = {
+static const struct file_operations mptctl_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.release = mptctl_release,
diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h
index e65a1cf5eb0b..f7e72c5e47de 100644
--- a/drivers/message/fusion/mptctl.h
+++ b/drivers/message/fusion/mptctl.h
@@ -6,7 +6,7 @@
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Copyright (c) 1999-2007 LSI Logic Corporation
- * (mailto:mpt_linux_developer@lsil.com)
+ * (mailto:mpt_linux_developer@lsi.com)
*
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index c819c23b55b1..b7d4c7265ec6 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -4,7 +4,7 @@
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Copyright (c) 1999-2007 LSI Logic Corporation
- * (mailto:mpt_linux_developer@lsil.com)
+ * (mailto:mpt_linux_developer@lsi.com)
*
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -86,6 +86,12 @@ MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
" return following a device loss event."
" Default=60.");
+/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
+#define MPTFC_MAX_LUN (16895)
+static int max_lun = MPTFC_MAX_LUN;
+module_param(max_lun, int, 0);
+MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
+
static int mptfcDoneCtx = -1;
static int mptfcTaskCtx = -1;
static int mptfcInternalCtx = -1; /* Used only for internal commands */
@@ -292,10 +298,9 @@ mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
U32 port_id = 0xffffff;
int num_targ = 0;
int max_bus = ioc->facts.MaxBuses;
- int max_targ = ioc->facts.MaxDevices;
+ int max_targ;
- if (max_bus == 0 || max_targ == 0)
- goto out;
+ max_targ = (ioc->facts.MaxDevices == 0) ? 256 : ioc->facts.MaxDevices;
data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
p_p0 = p0_array = kzalloc(data_sz, GFP_KERNEL);
@@ -467,8 +472,8 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
if (ri->starget) {
vtarget = ri->starget->hostdata;
if (vtarget) {
- vtarget->target_id = pg0->CurrentTargetID;
- vtarget->bus_id = pg0->CurrentBus;
+ vtarget->id = pg0->CurrentTargetID;
+ vtarget->channel = pg0->CurrentBus;
}
}
*((struct mptfc_rport_info **)rport->dd_data) = ri;
@@ -540,8 +545,8 @@ mptfc_target_alloc(struct scsi_target *starget)
if (rport) {
ri = *((struct mptfc_rport_info **)rport->dd_data);
if (ri) { /* better be! */
- vtarget->target_id = ri->pg0.CurrentTargetID;
- vtarget->bus_id = ri->pg0.CurrentBus;
+ vtarget->id = ri->pg0.CurrentTargetID;
+ vtarget->channel = ri->pg0.CurrentBus;
ri->starget = starget;
rc = 0;
}
@@ -592,7 +597,6 @@ mptfc_slave_alloc(struct scsi_device *sdev)
if (vtarget->num_luns == 0) {
vtarget->ioc_id = hd->ioc->id;
vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
- hd->Targets[sdev->id] = vtarget;
}
vdev->vtarget = vtarget;
@@ -630,16 +634,17 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
struct mptfc_rport_info *ri;
struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
int err;
+ VirtDevice *vdev = SCpnt->device->hostdata;
- err = fc_remote_port_chkready(rport);
- if (unlikely(err)) {
- SCpnt->result = err;
+ if (!vdev || !vdev->vtarget) {
+ SCpnt->result = DID_NO_CONNECT << 16;
done(SCpnt);
return 0;
}
- if (!SCpnt->device->hostdata) { /* vdev */
- SCpnt->result = DID_NO_CONNECT << 16;
+ err = fc_remote_port_chkready(rport);
+ if (unlikely(err)) {
+ SCpnt->result = err;
done(SCpnt);
return 0;
}
@@ -1143,7 +1148,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
printk(MYIOC_s_WARN_FMT
"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
ioc->name, ioc);
- return -ENODEV;
+ return 0;
}
sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
@@ -1173,10 +1178,9 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* set 16 byte cdb's */
sh->max_cmd_len = 16;
- sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
+ sh->max_id = ioc->pfacts->MaxDevices;
+ sh->max_lun = max_lun;
- sh->max_lun = MPT_LAST_LUN + 1;
- sh->max_channel = 0;
sh->this_id = ioc->pfacts[0].PortSCSIID;
/* Required entry.
@@ -1230,19 +1234,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
ioc->name, hd->ScsiLookup));
- /* Allocate memory for the device structures.
- * A non-Null pointer at an offset
- * indicates a device exists.
- * max_id = 1 + maximum id (hosts.h)
- */
- hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
- if (!hd->Targets) {
- error = -ENOMEM;
- goto out_mptfc_probe;
- }
-
- dprintk((KERN_INFO " vdev @ %p\n", hd->Targets));
-
/* Clear the TM flags
*/
hd->tmPending = 0;
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index 2936204d8ad6..b691292ff599 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -5,6 +5,7 @@
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Copyright (c) 2000-2007 LSI Logic Corporation
+ * (mailto:mpt_linux_developer@lsi.com)
*
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h
index 70ab75e7c263..fe438bf119f6 100644
--- a/drivers/message/fusion/mptlan.h
+++ b/drivers/message/fusion/mptlan.h
@@ -5,6 +5,7 @@
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Copyright (c) 2000-2007 LSI Logic Corporation
+ * (mailto:mpt_linux_developer@lsi.com)
*
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 09e9a9d96410..84b8b485e95b 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -4,7 +4,7 @@
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Copyright (c) 1999-2007 LSI Logic Corporation
- * (mailto:mpt_linux_developer@lsil.com)
+ * (mailto:mpt_linux_developer@lsi.com)
* Copyright (c) 2005-2007 Dell
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -83,17 +83,31 @@ MODULE_PARM_DESC(mpt_pt_clear,
" Clear persistency table: enable=1 "
"(default=MPTSCSIH_PT_CLEAR=0)");
+/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
+#define MPTSAS_MAX_LUN (16895)
+static int max_lun = MPTSAS_MAX_LUN;
+module_param(max_lun, int, 0);
+MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
+
static int mptsasDoneCtx = -1;
static int mptsasTaskCtx = -1;
static int mptsasInternalCtx = -1; /* Used only for internal commands */
static int mptsasMgmtCtx = -1;
+static void mptsas_hotplug_work(struct work_struct *work);
+
+struct mptsas_target_reset_event {
+ struct list_head list;
+ EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data;
+ u8 target_reset_issued;
+};
enum mptsas_hotplug_action {
MPTSAS_ADD_DEVICE,
MPTSAS_DEL_DEVICE,
MPTSAS_ADD_RAID,
MPTSAS_DEL_RAID,
+ MPTSAS_ADD_INACTIVE_VOLUME,
MPTSAS_IGNORE_EVENT,
};
@@ -102,14 +116,15 @@ struct mptsas_hotplug_event {
MPT_ADAPTER *ioc;
enum mptsas_hotplug_action event_type;
u64 sas_address;
- u32 channel;
- u32 id;
+ u8 channel;
+ u8 id;
u32 device_info;
u16 handle;
u16 parent_handle;
u8 phy_id;
- u8 phys_disk_num;
- u8 phys_disk_num_valid;
+ u8 phys_disk_num_valid; /* hrc (hidden raid component) */
+ u8 phys_disk_num; /* hrc - unique index*/
+ u8 hidden_raid_component; /* hrc - don't expose*/
};
struct mptsas_discovery_event {
@@ -134,6 +149,7 @@ struct mptsas_devinfo {
u8 port_id; /* sas physical port this device
is assoc'd with */
u8 id; /* logical target id of this device */
+ u32 phys_disk_num; /* phys disk id, for csmi-ioctls */
u8 channel; /* logical bus number of this device */
u64 sas_address; /* WWN of this device,
SATA is assigned by HBA,expander */
@@ -153,6 +169,7 @@ struct mptsas_portinfo_details{
};
struct mptsas_phyinfo {
+ u16 handle; /* unique id to address this */
u8 phy_id; /* phy index */
u8 port_id; /* firmware port identifier */
u8 negotiated_link_rate; /* nego'd link rate for this phy */
@@ -168,7 +185,6 @@ struct mptsas_phyinfo {
struct mptsas_portinfo {
struct list_head list;
- u16 handle; /* unique id to address this */
u16 num_phys; /* number of phys */
struct mptsas_phyinfo *phy_info;
};
@@ -561,22 +577,273 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
mutex_unlock(&ioc->sas_topology_mutex);
}
+/**
+ * csmisas_find_vtarget
+ *
+ * @ioc
+ * @volume_id
+ * @volume_bus
+ *
+ **/
+static VirtTarget *
+mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
+{
+ struct scsi_device *sdev;
+ VirtDevice *vdev;
+ VirtTarget *vtarget = NULL;
+
+ shost_for_each_device(sdev, ioc->sh) {
+ if ((vdev = sdev->hostdata) == NULL)
+ continue;
+ if (vdev->vtarget->id == id &&
+ vdev->vtarget->channel == channel)
+ vtarget = vdev->vtarget;
+ }
+ return vtarget;
+}
+
+/**
+ * mptsas_target_reset
+ *
+ * Issues TARGET_RESET to end device using handshaking method
+ *
+ * @ioc
+ * @channel
+ * @id
+ *
+ * Returns (1) success
+ * (0) failure
+ *
+ **/
+static int
+mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
+{
+ MPT_FRAME_HDR *mf;
+ SCSITaskMgmt_t *pScsiTm;
+
+ if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
+ dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n",
+ ioc->name,__FUNCTION__, __LINE__));
+ return 0;
+ }
+
+ /* Format the Request
+ */
+ pScsiTm = (SCSITaskMgmt_t *) mf;
+ memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
+ pScsiTm->TargetID = id;
+ pScsiTm->Bus = channel;
+ pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
+ pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
+ pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
+
+ DBG_DUMP_TM_REQUEST_FRAME(mf);
+
+ if (mpt_send_handshake_request(ioc->TaskCtx, ioc,
+ sizeof(SCSITaskMgmt_t), (u32 *)mf, NO_SLEEP)) {
+ mpt_free_msg_frame(ioc, mf);
+ dfailprintk((MYIOC_s_WARN_FMT "%s, tm handshake failed @%d!!\n",
+ ioc->name,__FUNCTION__, __LINE__));
+ return 0;
+ }
+
+ return 1;
+}
+
+/**
+ * mptsas_target_reset_queue
+ *
+ * Receive request for TARGET_RESET after recieving an firmware
+ * event NOT_RESPONDING_EVENT, then put command in link list
+ * and queue if task_queue already in use.
+ *
+ * @ioc
+ * @sas_event_data
+ *
+ **/
static void
-mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget)
+mptsas_target_reset_queue(MPT_ADAPTER *ioc,
+ EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
{
- MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+ VirtTarget *vtarget = NULL;
+ struct mptsas_target_reset_event *target_reset_list;
+ u8 id, channel;
- if (mptscsih_TMHandler(hd,
- MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
- vtarget->bus_id, vtarget->target_id, 0, 0, 5) < 0) {
- hd->tmPending = 0;
- hd->tmState = TM_STATE_NONE;
- printk(MYIOC_s_WARN_FMT
- "Error processing TaskMgmt id=%d TARGET_RESET\n",
- ioc->name, vtarget->target_id);
+ id = sas_event_data->TargetID;
+ channel = sas_event_data->Bus;
+
+ if (!(vtarget = mptsas_find_vtarget(ioc, channel, id)))
+ return;
+
+ vtarget->deleted = 1; /* block IO */
+
+ target_reset_list = kzalloc(sizeof(*target_reset_list),
+ GFP_ATOMIC);
+ if (!target_reset_list) {
+ dfailprintk((MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
+ ioc->name,__FUNCTION__, __LINE__));
+ return;
+ }
+
+ memcpy(&target_reset_list->sas_event_data, sas_event_data,
+ sizeof(*sas_event_data));
+ list_add_tail(&target_reset_list->list, &hd->target_reset_list);
+
+ if (hd->resetPending)
+ return;
+
+ if (mptsas_target_reset(ioc, channel, id)) {
+ target_reset_list->target_reset_issued = 1;
+ hd->resetPending = 1;
}
}
+/**
+ * mptsas_dev_reset_complete
+ *
+ * Completion for TARGET_RESET after NOT_RESPONDING_EVENT,
+ * enable work queue to finish off removing device from upper layers.
+ * then send next TARGET_RESET in the queue.
+ *
+ * @ioc
+ *
+ **/
+static void
+mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
+{
+ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+ struct list_head *head = &hd->target_reset_list;
+ struct mptsas_target_reset_event *target_reset_list;
+ struct mptsas_hotplug_event *ev;
+ EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
+ u8 id, channel;
+ __le64 sas_address;
+
+ if (list_empty(head))
+ return;
+
+ target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, list);
+
+ sas_event_data = &target_reset_list->sas_event_data;
+ id = sas_event_data->TargetID;
+ channel = sas_event_data->Bus;
+ hd->resetPending = 0;
+
+ /*
+ * retry target reset
+ */
+ if (!target_reset_list->target_reset_issued) {
+ if (mptsas_target_reset(ioc, channel, id)) {
+ target_reset_list->target_reset_issued = 1;
+ hd->resetPending = 1;
+ }
+ return;
+ }
+
+ /*
+ * enable work queue to remove device from upper layers
+ */
+ list_del(&target_reset_list->list);
+
+ ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
+ if (!ev) {
+ dfailprintk((MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
+ ioc->name,__FUNCTION__, __LINE__));
+ return;
+ }
+
+ INIT_WORK(&ev->work, mptsas_hotplug_work);
+ ev->ioc = ioc;
+ ev->handle = le16_to_cpu(sas_event_data->DevHandle);
+ ev->parent_handle =
+ le16_to_cpu(sas_event_data->ParentDevHandle);
+ ev->channel = channel;
+ ev->id =id;
+ ev->phy_id = sas_event_data->PhyNum;
+ memcpy(&sas_address, &sas_event_data->SASAddress,
+ sizeof(__le64));
+ ev->sas_address = le64_to_cpu(sas_address);
+ ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo);
+ ev->event_type = MPTSAS_DEL_DEVICE;
+ schedule_work(&ev->work);
+ kfree(target_reset_list);
+
+ /*
+ * issue target reset to next device in the queue
+ */
+
+ head = &hd->target_reset_list;
+ if (list_empty(head))
+ return;
+
+ target_reset_list = list_entry(head->next, struct mptsas_target_reset_event,
+ list);
+
+ sas_event_data = &target_reset_list->sas_event_data;
+ id = sas_event_data->TargetID;
+ channel = sas_event_data->Bus;
+
+ if (mptsas_target_reset(ioc, channel, id)) {
+ target_reset_list->target_reset_issued = 1;
+ hd->resetPending = 1;
+ }
+}
+
+/**
+ * mptsas_taskmgmt_complete
+ *
+ * @ioc
+ * @mf
+ * @mr
+ *
+ **/
+static int
+mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
+{
+ mptsas_dev_reset_complete(ioc);
+ return mptscsih_taskmgmt_complete(ioc, mf, mr);
+}
+
+/**
+ * mptscsih_ioc_reset
+ *
+ * @ioc
+ * @reset_phase
+ *
+ **/
+static int
+mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
+{
+ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+ struct mptsas_target_reset_event *target_reset_list, *n;
+ int rc;
+
+ rc = mptscsih_ioc_reset(ioc, reset_phase);
+
+ if (ioc->bus_type != SAS)
+ goto out;
+
+ if (reset_phase != MPT_IOC_POST_RESET)
+ goto out;
+
+ if (!hd || !hd->ioc)
+ goto out;
+
+ if (list_empty(&hd->target_reset_list))
+ goto out;
+
+ /* flush the target_reset_list */
+ list_for_each_entry_safe(target_reset_list, n,
+ &hd->target_reset_list, list) {
+ list_del(&target_reset_list->list);
+ kfree(target_reset_list);
+ }
+
+ out:
+ return rc;
+}
+
static int
mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
u32 form, u32 form_specific)
@@ -661,8 +928,7 @@ mptsas_target_alloc(struct scsi_target *starget)
struct Scsi_Host *host = dev_to_shost(&starget->dev);
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
VirtTarget *vtarget;
- u32 target_id;
- u32 channel;
+ u8 id, channel;
struct sas_rphy *rphy;
struct mptsas_portinfo *p;
int i;
@@ -673,15 +939,19 @@ mptsas_target_alloc(struct scsi_target *starget)
vtarget->starget = starget;
vtarget->ioc_id = hd->ioc->id;
- vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
-
- target_id = starget->id;
+ vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
+ id = starget->id;
channel = 0;
- hd->Targets[target_id] = vtarget;
-
- if (starget->channel == MPTSAS_RAID_CHANNEL)
+ /*
+ * RAID volumes placed beyond the last expected port.
+ */
+ if (starget->channel == MPTSAS_RAID_CHANNEL) {
+ for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
+ if (id == hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
+ channel = hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
goto out;
+ }
rphy = dev_to_rphy(starget->dev.parent);
mutex_lock(&hd->ioc->sas_topology_mutex);
@@ -690,18 +960,19 @@ mptsas_target_alloc(struct scsi_target *starget)
if (p->phy_info[i].attached.sas_address !=
rphy->identify.sas_address)
continue;
- target_id = p->phy_info[i].attached.id;
+ id = p->phy_info[i].attached.id;
channel = p->phy_info[i].attached.channel;
mptsas_set_starget(&p->phy_info[i], starget);
/*
* Exposing hidden raid components
*/
- if (mptscsih_is_phys_disk(hd->ioc, target_id)) {
- target_id = mptscsih_raid_id_to_num(hd,
- target_id);
+ if (mptscsih_is_phys_disk(hd->ioc, channel, id)) {
+ id = mptscsih_raid_id_to_num(hd->ioc,
+ channel, id);
vtarget->tflags |=
MPT_TARGET_FLAGS_RAID_COMPONENT;
+ p->phy_info[i].attached.phys_disk_num = id;
}
mutex_unlock(&hd->ioc->sas_topology_mutex);
goto out;
@@ -713,8 +984,8 @@ mptsas_target_alloc(struct scsi_target *starget)
return -ENXIO;
out:
- vtarget->target_id = target_id;
- vtarget->bus_id = channel;
+ vtarget->id = id;
+ vtarget->channel = channel;
starget->hostdata = vtarget;
return 0;
}
@@ -786,7 +1057,8 @@ mptsas_slave_alloc(struct scsi_device *sdev)
* Exposing hidden raid components
*/
if (mptscsih_is_phys_disk(hd->ioc,
- p->phy_info[i].attached.id))
+ p->phy_info[i].attached.channel,
+ p->phy_info[i].attached.id))
sdev->no_uld_attach = 1;
mutex_unlock(&hd->ioc->sas_topology_mutex);
goto out;
@@ -808,13 +1080,14 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
{
VirtDevice *vdev = SCpnt->device->hostdata;
-// scsi_print_command(SCpnt);
- if (vdev->vtarget->deleted) {
+ if (!vdev || !vdev->vtarget || vdev->vtarget->deleted) {
SCpnt->result = DID_NO_CONNECT << 16;
done(SCpnt);
return 0;
}
+// scsi_print_command(SCpnt);
+
return mptscsih_qcmd(SCpnt,done);
}
@@ -1114,9 +1387,6 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
goto out_free_consistent;
}
- if (port_info->num_phys)
- port_info->handle =
- le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
for (i = 0; i < port_info->num_phys; i++) {
mptsas_print_phy_data(&buffer->PhyData[i]);
port_info->phy_info[i].phy_id = i;
@@ -1125,6 +1395,8 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
port_info->phy_info[i].negotiated_link_rate =
buffer->PhyData[i].NegotiatedLinkRate;
port_info->phy_info[i].portinfo = port_info;
+ port_info->phy_info[i].handle =
+ le16_to_cpu(buffer->PhyData[i].ControllerDevHandle);
}
out_free_consistent:
@@ -1261,6 +1533,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
device_info->phy_id = buffer->PhyNum;
device_info->port_id = buffer->PhysicalPort;
device_info->id = buffer->TargetID;
+ device_info->phys_disk_num = ~0;
device_info->channel = buffer->Bus;
memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
device_info->sas_address = le64_to_cpu(sas_address);
@@ -1325,7 +1598,6 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
/* save config data */
port_info->num_phys = buffer->NumPhys;
- port_info->handle = le16_to_cpu(buffer->DevHandle);
port_info->phy_info = kcalloc(port_info->num_phys,
sizeof(*port_info->phy_info),GFP_KERNEL);
if (!port_info->phy_info) {
@@ -1333,8 +1605,11 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
goto out_free_consistent;
}
- for (i = 0; i < port_info->num_phys; i++)
+ for (i = 0; i < port_info->num_phys; i++) {
port_info->phy_info[i].portinfo = port_info;
+ port_info->phy_info[i].handle =
+ le16_to_cpu(buffer->DevHandle);
+ }
out_free_consistent:
pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
@@ -1702,7 +1977,6 @@ static int
mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
{
struct mptsas_portinfo *port_info, *hba;
- u32 handle = 0xFFFF;
int error = -ENOMEM, i;
hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
@@ -1714,34 +1988,36 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
goto out_free_port_info;
mutex_lock(&ioc->sas_topology_mutex);
- ioc->handle = hba->handle;
- port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle);
+ ioc->handle = hba->phy_info[0].handle;
+ port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle);
if (!port_info) {
port_info = hba;
list_add_tail(&port_info->list, &ioc->sas_topology);
} else {
- port_info->handle = hba->handle;
- for (i = 0; i < hba->num_phys; i++)
+ for (i = 0; i < hba->num_phys; i++) {
port_info->phy_info[i].negotiated_link_rate =
hba->phy_info[i].negotiated_link_rate;
+ port_info->phy_info[i].handle =
+ hba->phy_info[i].handle;
+ port_info->phy_info[i].port_id =
+ hba->phy_info[i].port_id;
+ }
kfree(hba->phy_info);
kfree(hba);
hba = NULL;
}
mutex_unlock(&ioc->sas_topology_mutex);
-
for (i = 0; i < port_info->num_phys; i++) {
mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
(MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
- (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
- MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
+ (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+ MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+ port_info->phy_info[i].handle);
port_info->phy_info[i].identify.phy_id =
- port_info->phy_info[i].phy_id;
- handle = port_info->phy_info[i].identify.handle;
-
+ port_info->phy_info[i].phy_id = i;
if (port_info->phy_info[i].attached.handle)
mptsas_sas_device_pg0(ioc,
&port_info->phy_info[i].attached,
@@ -1777,12 +2053,12 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
goto out;
error = mptsas_sas_expander_pg0(ioc, ex,
- (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
- MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
+ (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
+ MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
if (error)
goto out_free_port_info;
- *handle = ex->handle;
+ *handle = ex->phy_info[0].handle;
mutex_lock(&ioc->sas_topology_mutex);
port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
@@ -1790,7 +2066,12 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
port_info = ex;
list_add_tail(&port_info->list, &ioc->sas_topology);
} else {
- port_info->handle = ex->handle;
+ for (i = 0; i < ex->num_phys; i++) {
+ port_info->phy_info[i].handle =
+ ex->phy_info[i].handle;
+ port_info->phy_info[i].port_id =
+ ex->phy_info[i].port_id;
+ }
kfree(ex->phy_info);
kfree(ex);
ex = NULL;
@@ -1868,8 +2149,6 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
struct mptsas_portinfo buffer;
struct mptsas_portinfo *port_info, *n, *parent;
struct mptsas_phyinfo *phy_info;
- struct scsi_target * starget;
- VirtTarget * vtarget;
struct sas_port * port;
int i;
u64 expander_sas_address;
@@ -1884,26 +2163,8 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
if (mptsas_sas_expander_pg0(ioc, &buffer,
(MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
- MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {
-
- /*
- * Issue target reset to all child end devices
- * then mark them deleted to prevent further
- * IO going to them.
- */
- phy_info = port_info->phy_info;
- for (i = 0; i < port_info->num_phys; i++, phy_info++) {
- starget = mptsas_get_starget(phy_info);
- if (!starget)
- continue;
- vtarget = starget->hostdata;
- if(vtarget->deleted)
- continue;
- vtarget->deleted = 1;
- mptsas_target_reset(ioc, vtarget);
- sas_port_delete(mptsas_get_port(phy_info));
- mptsas_port_delete(phy_info->port_details);
- }
+ MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
+ port_info->phy_info[0].handle)) {
/*
* Obtain the port_info instance to the parent port
@@ -1972,11 +2233,13 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
/*
Reporting RAID volumes.
*/
+ if (!ioc->ir_firmware)
+ goto out;
if (!ioc->raid_data.pIocPg2)
goto out;
if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
goto out;
- for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
+ for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
}
@@ -2030,12 +2293,37 @@ mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
mutex_lock(&ioc->sas_topology_mutex);
list_for_each_entry(port_info, &ioc->sas_topology, list) {
for (i = 0; i < port_info->num_phys; i++) {
+ if (!mptsas_is_end_device(
+ &port_info->phy_info[i].attached))
+ continue;
if (port_info->phy_info[i].attached.sas_address
!= sas_address)
continue;
+ phy_info = &port_info->phy_info[i];
+ break;
+ }
+ }
+ mutex_unlock(&ioc->sas_topology_mutex);
+ return phy_info;
+}
+
+static struct mptsas_phyinfo *
+mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id)
+{
+ struct mptsas_portinfo *port_info;
+ struct mptsas_phyinfo *phy_info = NULL;
+ int i;
+
+ mutex_lock(&ioc->sas_topology_mutex);
+ list_for_each_entry(port_info, &ioc->sas_topology, list) {
+ for (i = 0; i < port_info->num_phys; i++) {
if (!mptsas_is_end_device(
&port_info->phy_info[i].attached))
continue;
+ if (port_info->phy_info[i].attached.id != id)
+ continue;
+ if (port_info->phy_info[i].attached.channel != channel)
+ continue;
phy_info = &port_info->phy_info[i];
break;
}
@@ -2045,7 +2333,7 @@ mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
}
static struct mptsas_phyinfo *
-mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
+mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
{
struct mptsas_portinfo *port_info;
struct mptsas_phyinfo *phy_info = NULL;
@@ -2054,11 +2342,15 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
mutex_lock(&ioc->sas_topology_mutex);
list_for_each_entry(port_info, &ioc->sas_topology, list) {
for (i = 0; i < port_info->num_phys; i++) {
- if (port_info->phy_info[i].attached.id != id)
- continue;
if (!mptsas_is_end_device(
&port_info->phy_info[i].attached))
continue;
+ if (port_info->phy_info[i].attached.phys_disk_num == ~0)
+ continue;
+ if (port_info->phy_info[i].attached.phys_disk_num != id)
+ continue;
+ if (port_info->phy_info[i].attached.channel != channel)
+ continue;
phy_info = &port_info->phy_info[i];
break;
}
@@ -2094,6 +2386,76 @@ mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
mptsas_reprobe_lun);
}
+static void
+mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
+{
+ CONFIGPARMS cfg;
+ ConfigPageHeader_t hdr;
+ dma_addr_t dma_handle;
+ pRaidVolumePage0_t buffer = NULL;
+ RaidPhysDiskPage0_t phys_disk;
+ int i;
+ struct mptsas_hotplug_event *ev;
+
+ memset(&cfg, 0 , sizeof(CONFIGPARMS));
+ memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+ hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
+ cfg.pageAddr = (channel << 8) + id;
+ cfg.cfghdr.hdr = &hdr;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+
+ if (mpt_config(ioc, &cfg) != 0)
+ goto out;
+
+ if (!hdr.PageLength)
+ goto out;
+
+ buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
+ &dma_handle);
+
+ if (!buffer)
+ goto out;
+
+ cfg.physAddr = dma_handle;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+ if (mpt_config(ioc, &cfg) != 0)
+ goto out;
+
+ if (!(buffer->VolumeStatus.Flags &
+ MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
+ goto out;
+
+ if (!buffer->NumPhysDisks)
+ goto out;
+
+ for (i = 0; i < buffer->NumPhysDisks; i++) {
+
+ if (mpt_raid_phys_disk_pg0(ioc,
+ buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
+ continue;
+
+ ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
+ if (!ev) {
+ printk(KERN_WARNING "mptsas: lost hotplug event\n");
+ goto out;
+ }
+
+ INIT_WORK(&ev->work, mptsas_hotplug_work);
+ ev->ioc = ioc;
+ ev->id = phys_disk.PhysDiskID;
+ ev->channel = phys_disk.PhysDiskBus;
+ ev->phys_disk_num_valid = 1;
+ ev->phys_disk_num = phys_disk.PhysDiskNum;
+ ev->event_type = MPTSAS_ADD_DEVICE;
+ schedule_work(&ev->work);
+ }
+
+ out:
+ if (buffer)
+ pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
+ dma_handle);
+}
/*
* Work queue thread to handle SAS hotplug events
*/
@@ -2102,6 +2464,7 @@ mptsas_hotplug_work(struct work_struct *work)
{
struct mptsas_hotplug_event *ev =
container_of(work, struct mptsas_hotplug_event, work);
+
MPT_ADAPTER *ioc = ev->ioc;
struct mptsas_phyinfo *phy_info;
struct sas_rphy *rphy;
@@ -2114,17 +2477,43 @@ mptsas_hotplug_work(struct work_struct *work)
VirtTarget *vtarget;
VirtDevice *vdevice;
-
mutex_lock(&ioc->sas_discovery_mutex);
switch (ev->event_type) {
case MPTSAS_DEL_DEVICE:
- phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
+ phy_info = NULL;
+ if (ev->phys_disk_num_valid) {
+ if (ev->hidden_raid_component){
+ if (mptsas_sas_device_pg0(ioc, &sas_device,
+ (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
+ MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+ (ev->channel << 8) + ev->id)) {
+ dfailprintk((MYIOC_s_ERR_FMT
+ "%s: exit at line=%d\n", ioc->name,
+ __FUNCTION__, __LINE__));
+ break;
+ }
+ phy_info = mptsas_find_phyinfo_by_sas_address(
+ ioc, sas_device.sas_address);
+ }else
+ phy_info = mptsas_find_phyinfo_by_phys_disk_num(
+ ioc, ev->channel, ev->phys_disk_num);
+ }
+
+ if (!phy_info)
+ phy_info = mptsas_find_phyinfo_by_target(ioc,
+ ev->channel, ev->id);
/*
* Sanity checks, for non-existing phys and remote rphys.
*/
- if (!phy_info || !phy_info->port_details) {
+ if (!phy_info){
+ dfailprintk((MYIOC_s_ERR_FMT
+ "%s: exit at line=%d\n", ioc->name,
+ __FUNCTION__, __LINE__));
+ break;
+ }
+ if (!phy_info->port_details) {
dfailprintk((MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
@@ -2137,6 +2526,7 @@ mptsas_hotplug_work(struct work_struct *work)
__FUNCTION__, __LINE__));
break;
}
+
port = mptsas_get_port(phy_info);
if (!port) {
dfailprintk((MYIOC_s_ERR_FMT
@@ -2159,28 +2549,35 @@ mptsas_hotplug_work(struct work_struct *work)
/*
* Handling RAID components
*/
- if (ev->phys_disk_num_valid) {
- vtarget->target_id = ev->phys_disk_num;
- vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
+ if (ev->phys_disk_num_valid &&
+ ev->hidden_raid_component) {
+ printk(MYIOC_s_INFO_FMT
+ "RAID Hidding: channel=%d, id=%d, "
+ "physdsk %d \n", ioc->name, ev->channel,
+ ev->id, ev->phys_disk_num);
+ vtarget->id = ev->phys_disk_num;
+ vtarget->tflags |=
+ MPT_TARGET_FLAGS_RAID_COMPONENT;
mptsas_reprobe_target(starget, 1);
- break;
+ phy_info->attached.phys_disk_num =
+ ev->phys_disk_num;
+ break;
}
-
- vtarget->deleted = 1;
- mptsas_target_reset(ioc, vtarget);
}
- if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+ if (phy_info->attached.device_info &
+ MPI_SAS_DEVICE_INFO_SSP_TARGET)
ds = "ssp";
- if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
+ if (phy_info->attached.device_info &
+ MPI_SAS_DEVICE_INFO_STP_TARGET)
ds = "stp";
- if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+ if (phy_info->attached.device_info &
+ MPI_SAS_DEVICE_INFO_SATA_DEVICE)
ds = "sata";
printk(MYIOC_s_INFO_FMT
"removing %s device, channel %d, id %d, phy %d\n",
ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
-
#ifdef MPT_DEBUG_SAS_WIDE
dev_printk(KERN_DEBUG, &port->dev,
"delete port (%d)\n", port->port_identifier);
@@ -2198,14 +2595,14 @@ mptsas_hotplug_work(struct work_struct *work)
*/
if (mptsas_sas_device_pg0(ioc, &sas_device,
(MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
- MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) {
+ MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+ (ev->channel << 8) + ev->id)) {
dfailprintk((MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
break;
}
- ssleep(2);
__mptsas_discovery_work(ioc);
phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
@@ -2219,7 +2616,8 @@ mptsas_hotplug_work(struct work_struct *work)
}
starget = mptsas_get_starget(phy_info);
- if (starget) {
+ if (starget && (!ev->hidden_raid_component)){
+
vtarget = starget->hostdata;
if (!vtarget) {
@@ -2232,9 +2630,15 @@ mptsas_hotplug_work(struct work_struct *work)
* Handling RAID components
*/
if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
- vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
- vtarget->target_id = ev->id;
+ printk(MYIOC_s_INFO_FMT
+ "RAID Exposing: channel=%d, id=%d, "
+ "physdsk %d \n", ioc->name, ev->channel,
+ ev->id, ev->phys_disk_num);
+ vtarget->tflags &=
+ ~MPT_TARGET_FLAGS_RAID_COMPONENT;
+ vtarget->id = ev->id;
mptsas_reprobe_target(starget, 0);
+ phy_info->attached.phys_disk_num = ~0;
}
break;
}
@@ -2243,8 +2647,10 @@ mptsas_hotplug_work(struct work_struct *work)
dfailprintk((MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
+ if (ev->channel) printk("%d\n", __LINE__);
break;
}
+
port = mptsas_get_port(phy_info);
if (!port) {
dfailprintk((MYIOC_s_ERR_FMT
@@ -2252,15 +2658,17 @@ mptsas_hotplug_work(struct work_struct *work)
__FUNCTION__, __LINE__));
break;
}
-
memcpy(&phy_info->attached, &sas_device,
sizeof(struct mptsas_devinfo));
- if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+ if (phy_info->attached.device_info &
+ MPI_SAS_DEVICE_INFO_SSP_TARGET)
ds = "ssp";
- if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
+ if (phy_info->attached.device_info &
+ MPI_SAS_DEVICE_INFO_STP_TARGET)
ds = "stp";
- if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+ if (phy_info->attached.device_info &
+ MPI_SAS_DEVICE_INFO_SATA_DEVICE)
ds = "sata";
printk(MYIOC_s_INFO_FMT
@@ -2301,19 +2709,21 @@ mptsas_hotplug_work(struct work_struct *work)
break;
case MPTSAS_DEL_RAID:
sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
- ev->id, 0);
+ ev->id, 0);
if (!sdev)
break;
printk(MYIOC_s_INFO_FMT
"removing raid volume, channel %d, id %d\n",
ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
vdevice = sdev->hostdata;
- vdevice->vtarget->deleted = 1;
- mptsas_target_reset(ioc, vdevice->vtarget);
scsi_remove_device(sdev);
scsi_device_put(sdev);
mpt_findImVolumes(ioc);
break;
+ case MPTSAS_ADD_INACTIVE_VOLUME:
+ mptsas_adding_inactive_raid_components(ioc,
+ ev->channel, ev->id);
+ break;
case MPTSAS_IGNORE_EVENT:
default:
break;
@@ -2321,7 +2731,6 @@ mptsas_hotplug_work(struct work_struct *work)
mutex_unlock(&ioc->sas_discovery_mutex);
kfree(ev);
-
}
static void
@@ -2339,8 +2748,12 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc,
return;
switch (sas_event_data->ReasonCode) {
- case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
+
+ mptsas_target_reset_queue(ioc, sas_event_data);
+ break;
+
+ case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
if (!ev) {
printk(KERN_WARNING "mptsas: lost hotplug event\n");
@@ -2375,15 +2788,20 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc,
mptsas_persist_clear_table);
schedule_work(&ioc->sas_persist_task);
break;
+ /*
+ * TODO, handle other events
+ */
case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
- /* TODO */
+ case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
- /* TODO */
+ case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
+ case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
+ case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
+ case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
default:
break;
}
}
-
static void
mptsas_send_raid_event(MPT_ADAPTER *ioc,
EVENT_DATA_RAID *raid_event_data)
@@ -2404,31 +2822,36 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc,
INIT_WORK(&ev->work, mptsas_hotplug_work);
ev->ioc = ioc;
ev->id = raid_event_data->VolumeID;
+ ev->channel = raid_event_data->VolumeBus;
ev->event_type = MPTSAS_IGNORE_EVENT;
switch (raid_event_data->ReasonCode) {
case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
+ ev->phys_disk_num_valid = 1;
+ ev->phys_disk_num = raid_event_data->PhysDiskNum;
ev->event_type = MPTSAS_ADD_DEVICE;
break;
case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
- ioc->raid_data.isRaid = 1;
ev->phys_disk_num_valid = 1;
ev->phys_disk_num = raid_event_data->PhysDiskNum;
+ ev->hidden_raid_component = 1;
ev->event_type = MPTSAS_DEL_DEVICE;
break;
case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
switch (state) {
case MPI_PD_STATE_ONLINE:
- ioc->raid_data.isRaid = 1;
+ case MPI_PD_STATE_NOT_COMPATIBLE:
ev->phys_disk_num_valid = 1;
ev->phys_disk_num = raid_event_data->PhysDiskNum;
+ ev->hidden_raid_component = 1;
ev->event_type = MPTSAS_ADD_DEVICE;
break;
case MPI_PD_STATE_MISSING:
- case MPI_PD_STATE_NOT_COMPATIBLE:
case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
+ ev->phys_disk_num_valid = 1;
+ ev->phys_disk_num = raid_event_data->PhysDiskNum;
ev->event_type = MPTSAS_DEL_DEVICE;
break;
default:
@@ -2485,6 +2908,35 @@ mptsas_send_discovery_event(MPT_ADAPTER *ioc,
schedule_work(&ev->work);
};
+/*
+ * mptsas_send_ir2_event - handle exposing hidden disk when
+ * an inactive raid volume is added
+ *
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @ir2_data
+ *
+ */
+static void
+mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data)
+{
+ struct mptsas_hotplug_event *ev;
+
+ if (ir2_data->ReasonCode !=
+ MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED)
+ return;
+
+ ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
+ if (!ev)
+ return;
+
+ INIT_WORK(&ev->work, mptsas_hotplug_work);
+ ev->ioc = ioc;
+ ev->id = ir2_data->TargetID;
+ ev->channel = ir2_data->Bus;
+ ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME;
+
+ schedule_work(&ev->work);
+};
static int
mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
@@ -2524,6 +2976,10 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
mptsas_send_discovery_event(ioc,
(EVENT_DATA_SAS_DISCOVERY *)reply->Data);
break;
+ case MPI_EVENT_IR2:
+ mptsas_send_ir2_event(ioc,
+ (PTR_MPI_EVENT_DATA_IR2)reply->Data);
+ break;
default:
rc = mptscsih_event_process(ioc, reply);
break;
@@ -2611,12 +3067,11 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* set 16 byte cdb's */
sh->max_cmd_len = 16;
- sh->max_id = ioc->pfacts->MaxDevices + 1;
+ sh->max_id = ioc->pfacts[0].PortSCSIID;
+ sh->max_lun = max_lun;
sh->transportt = mptsas_transport_template;
- sh->max_lun = MPT_LAST_LUN + 1;
- sh->max_channel = 0;
sh->this_id = ioc->pfacts[0].PortSCSIID;
/* Required entry.
@@ -2659,8 +3114,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sh->sg_tablesize = numSGE;
}
- spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-
hd = (MPT_SCSI_HOST *) sh->hostdata;
hd->ioc = ioc;
@@ -2676,19 +3129,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
ioc->name, hd->ScsiLookup));
- /* Allocate memory for the device structures.
- * A non-Null pointer at an offset
- * indicates a device exists.
- * max_id = 1 + maximum id (hosts.h)
- */
- hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
- if (!hd->Targets) {
- error = -ENOMEM;
- goto out_mptsas_probe;
- }
-
- dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
-
/* Clear the TM flags
*/
hd->tmPending = 0;
@@ -2713,15 +3153,17 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->sas_data.ptClear = mpt_pt_clear;
+ init_waitqueue_head(&hd->scandv_waitq);
+ hd->scandv_wait_done = 0;
+ hd->last_queue_full = 0;
+ INIT_LIST_HEAD(&hd->target_reset_list);
+ spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+
if (ioc->sas_data.ptClear==1) {
mptbase_sas_persist_operation(
ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
}
- init_waitqueue_head(&hd->scandv_waitq);
- hd->scandv_wait_done = 0;
- hd->last_queue_full = 0;
-
error = scsi_add_host(sh, &ioc->pcidev->dev);
if (error) {
dprintk((KERN_ERR MYNAM
@@ -2745,7 +3187,7 @@ static void __devexit mptsas_remove(struct pci_dev *pdev)
struct mptsas_portinfo *p, *n;
int i;
- ioc->sas_discovery_ignore_events=1;
+ ioc->sas_discovery_ignore_events = 1;
sas_remove_host(ioc->sh);
mutex_lock(&ioc->sas_topology_mutex);
@@ -2800,7 +3242,7 @@ mptsas_init(void)
return -ENODEV;
mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
- mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
+ mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
mptsasInternalCtx =
mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
@@ -2810,7 +3252,7 @@ mptsas_init(void)
": Registered for IOC event notifications\n"));
}
- if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
+ if (mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset) == 0) {
dprintk((KERN_INFO MYNAM
": Registered for IOC reset notifications\n"));
}
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index f0cca3ea93b2..c417ae0b5fe6 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -4,7 +4,7 @@
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Copyright (c) 1999-2007 LSI Logic Corporation
- * (mailto:mpt_linux_developer@lsil.com)
+ * (mailto:mpt_linux_developer@lsi.com)
*
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -79,43 +79,6 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(my_VERSION);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-typedef struct _BIG_SENSE_BUF {
- u8 data[MPT_SENSE_BUFFER_ALLOC];
-} BIG_SENSE_BUF;
-
-#define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */
-#define MPT_SCANDV_DID_RESET (0x00000001)
-#define MPT_SCANDV_SENSE (0x00000002)
-#define MPT_SCANDV_SOME_ERROR (0x00000004)
-#define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008)
-#define MPT_SCANDV_ISSUE_SENSE (0x00000010)
-#define MPT_SCANDV_FALLBACK (0x00000020)
-
-#define MPT_SCANDV_MAX_RETRIES (10)
-
-#define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */
-#define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */
-#define MPT_ICFLAG_EBOS 0x04 /* ReadBuffer Echo buffer has EBOS */
-#define MPT_ICFLAG_PHYS_DISK 0x08 /* Any SCSI IO but do Phys Disk Format */
-#define MPT_ICFLAG_TAGGED_CMD 0x10 /* Do tagged IO */
-#define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */
-#define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */
-
-typedef struct _internal_cmd {
- char *data; /* data pointer */
- dma_addr_t data_dma; /* data dma address */
- int size; /* transfer size */
- u8 cmd; /* SCSI Op Code */
- u8 bus; /* bus number */
- u8 id; /* SCSI ID (virtual) */
- u8 lun;
- u8 flags; /* Bit Field - See above */
- u8 physDiskNum; /* Phys disk number, -1 else */
- u8 rsvd2;
- u8 rsvd;
-} INTERNAL_CMD;
-
/*
* Other private/forward protos...
*/
@@ -131,14 +94,11 @@ static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
-static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
+static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
-static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev);
-static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev);
-static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
@@ -517,16 +477,100 @@ mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
SEPMsg = (SEPRequest_t *)mf;
SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
- SEPMsg->Bus = vtarget->bus_id;
- SEPMsg->TargetID = vtarget->target_id;
+ SEPMsg->Bus = vtarget->channel;
+ SEPMsg->TargetID = vtarget->id;
SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
SEPMsg->SlotStatus = SlotStatus;
devtverboseprintk((MYIOC_s_WARN_FMT
- "Sending SEP cmd=%x id=%d bus=%d\n",
- ioc->name, SlotStatus, SEPMsg->TargetID, SEPMsg->Bus));
+ "Sending SEP cmd=%x channel=%d id=%d\n",
+ ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID));
mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
}
+#ifdef MPT_DEBUG_REPLY
+/**
+ * mptscsih_iocstatus_info_scsiio - IOCSTATUS information for SCSIIO
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @ioc_status: U32 IOCStatus word from IOC
+ * @scsi_status: U8 sam status from target
+ * @scsi_state: U8 scsi state
+ * @sc: original scsi cmnd pointer
+ * @mf: Pointer to MPT request frame
+ *
+ * Refer to lsi/mpi.h.
+ **/
+static void
+mptscsih_iocstatus_info_scsiio(MPT_ADAPTER *ioc, u32 ioc_status,
+ u8 scsi_status, u8 scsi_state, struct scsi_cmnd *sc)
+{
+ char extend_desc[EVENT_DESCR_STR_SZ];
+ char *desc = NULL;
+
+ switch (ioc_status) {
+
+ case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
+ desc = "SCSI Invalid Bus";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
+ desc = "SCSI Invalid TargetID";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
+ /*
+ * Inquiry is issued for device scanning
+ */
+ if (sc->cmnd[0] != 0x12)
+ desc = "SCSI Device Not There";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
+ desc = "SCSI Data Overrun";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
+ desc = "SCSI I/O Data Error";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
+ desc = "SCSI Protocol Error";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
+ desc = "SCSI Task Terminated";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
+ desc = "SCSI Residual Mismatch";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
+ desc = "SCSI Task Management Failed";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
+ desc = "SCSI IOC Terminated";
+ break;
+
+ case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
+ desc = "SCSI Ext Terminated";
+ break;
+ }
+
+ if (!desc)
+ return;
+
+ snprintf(extend_desc, EVENT_DESCR_STR_SZ,
+ "[%d:%d:%d:%d] cmd=%02Xh, sam_status=%02Xh state=%02Xh",
+ sc->device->host->host_no,
+ sc->device->channel, sc->device->id, sc->device->lun,
+ sc->cmnd[0], scsi_status, scsi_state);
+
+ printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n",
+ ioc->name, ioc_status, desc, extend_desc);
+}
+#endif
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mptscsih_io_done - Main SCSI IO callback routine registered to
@@ -613,12 +657,14 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
u32 xfer_cnt;
u16 status;
u8 scsi_state, scsi_status;
+ u32 log_info;
status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
scsi_state = pScsiReply->SCSIState;
scsi_status = pScsiReply->SCSIStatus;
xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
sc->resid = sc->request_bufflen - xfer_cnt;
+ log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
/*
* if we get a data underrun indication, yet no data was
@@ -633,13 +679,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
status = MPI_IOCSTATUS_SUCCESS;
}
- dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
- "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
- "resid=%d bufflen=%d xfer_cnt=%d\n",
- ioc->id, sc->device->id, sc->device->lun,
- status, scsi_state, scsi_status, sc->resid,
- sc->request_bufflen, xfer_cnt));
-
if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
@@ -648,9 +687,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
*/
if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
pScsiReply->ResponseInfo) {
- printk(KERN_NOTICE "ha=%d id=%d lun=%d: "
+ printk(KERN_NOTICE "[%d:%d:%d:%d] "
"FCP_ResponseInfo=%08xh\n",
- ioc->id, sc->device->id, sc->device->lun,
+ sc->device->host->host_no, sc->device->channel,
+ sc->device->id, sc->device->lun,
le32_to_cpu(pScsiReply->ResponseInfo));
}
@@ -695,9 +735,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
if ( ioc->bus_type == SAS ) {
u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
- u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
- log_info &=SAS_LOGINFO_MASK;
- if (log_info == SAS_LOGINFO_NEXUS_LOSS) {
+ if ((log_info & SAS_LOGINFO_MASK)
+ == SAS_LOGINFO_NEXUS_LOSS) {
sc->result = (DID_BUS_BUSY << 16);
break;
}
@@ -735,7 +774,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
else /* Sufficient data transfer occurred */
sc->result = (DID_OK << 16) | scsi_status;
dreplyprintk((KERN_NOTICE
- "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
+ "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n",
+ sc->result, sc->device->channel, sc->device->id));
break;
case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
@@ -848,7 +888,28 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
} /* switch(status) */
- dreplyprintk((KERN_NOTICE " sc->result is %08xh\n", sc->result));
+#ifdef MPT_DEBUG_REPLY
+ if (sc->result) {
+
+ mptscsih_iocstatus_info_scsiio(ioc, status,
+ scsi_status, scsi_state, sc);
+
+ dreplyprintk(("%s: [%d:%d:%d:%d] cmd=0x%02x "
+ "result=0x%08x\n\tiocstatus=0x%04X "
+ "scsi_state=0x%02X scsi_status=0x%02X "
+ "loginfo=0x%08X\n", __FUNCTION__,
+ sc->device->host->host_no, sc->device->channel, sc->device->id,
+ sc->device->lun, sc->cmnd[0], sc->result, status,
+ scsi_state, scsi_status, log_info));
+
+ dreplyprintk(("%s: [%d:%d:%d:%d] resid=%d "
+ "bufflen=%d xfer_cnt=%d\n", __FUNCTION__,
+ sc->device->host->host_no, sc->device->channel, sc->device->id,
+ sc->device->lun, sc->resid, sc->request_bufflen,
+ xfer_cnt));
+ }
+#endif
+
} /* end of address reply case */
/* Unmap the DMA buffers, if any. */
@@ -955,9 +1016,10 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
int ii;
int max = hd->ioc->req_depth;
struct scsi_cmnd *sc;
+ struct scsi_lun lun;
- dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
- vdevice->vtarget->target_id, vdevice->lun, max));
+ dsprintk((KERN_INFO MYNAM ": search_running channel %d id %d lun %d max %d\n",
+ vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, max));
for (ii=0; ii < max; ii++) {
if ((sc = hd->ScsiLookup[ii]) != NULL) {
@@ -965,10 +1027,14 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
if (mf == NULL)
continue;
- dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
- hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
- if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
+ int_to_scsilun(vdevice->lun, &lun);
+ if ((mf->Bus != vdevice->vtarget->channel) ||
+ (mf->TargetID != vdevice->vtarget->id) ||
+ memcmp(lun.scsi_lun, mf->LUN, 8))
continue;
+ dsprintk(( "search_running: found (sc=%p, mf = %p) "
+ "channel %d id %d, lun %d \n", hd->ScsiLookup[ii],
+ mf, mf->Bus, mf->TargetID, vdevice->lun));
/* Cleanup
*/
@@ -1065,12 +1131,6 @@ mptscsih_remove(struct pci_dev *pdev)
hd->ScsiLookup = NULL;
}
- /*
- * Free pointer array.
- */
- kfree(hd->Targets);
- hd->Targets = NULL;
-
dprintk((MYIOC_s_INFO_FMT
"Free'd ScsiLookup (%d) memory\n",
hd->ioc->name, sz1));
@@ -1317,14 +1377,6 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
return SCSI_MLQUEUE_HOST_BUSY;
}
- if ((hd->ioc->bus_type == SPI) &&
- vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT &&
- mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) {
- SCpnt->result = DID_NO_CONNECT << 16;
- done(SCpnt);
- return 0;
- }
-
/*
* Put together a MPT SCSI request...
*/
@@ -1368,8 +1420,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
/* Use the above information to set up the message frame
*/
- pScsiReq->TargetID = (u8) vdev->vtarget->target_id;
- pScsiReq->Bus = vdev->vtarget->bus_id;
+ pScsiReq->TargetID = (u8) vdev->vtarget->id;
+ pScsiReq->Bus = vdev->vtarget->channel;
pScsiReq->ChainOffset = 0;
if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
@@ -1379,14 +1431,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
pScsiReq->Reserved = 0;
pScsiReq->MsgFlags = mpt_msg_flags();
- pScsiReq->LUN[0] = 0;
- pScsiReq->LUN[1] = lun;
- pScsiReq->LUN[2] = 0;
- pScsiReq->LUN[3] = 0;
- pScsiReq->LUN[4] = 0;
- pScsiReq->LUN[5] = 0;
- pScsiReq->LUN[6] = 0;
- pScsiReq->LUN[7] = 0;
+ int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
pScsiReq->Control = cpu_to_le32(scsictl);
/*
@@ -1491,14 +1536,14 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
* mptscsih_TMHandler - Generic handler for SCSI Task Management.
* Fall through to mpt_HardResetHandler if: not operational, too many
* failed TM requests or handshake failure.
*
* @ioc: Pointer to MPT_ADAPTER structure
* @type: Task Management type
- * @target: Logical Target ID for reset (if appropriate)
+ * @id: Logical Target ID for reset (if appropriate)
* @lun: Logical Unit for reset (if appropriate)
* @ctx2abort: Context for the task to be aborted (if appropriate)
*
@@ -1507,28 +1552,17 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
* Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
* will be active.
*
- * Returns 0 for SUCCESS or -1 if FAILED.
- */
+ * Returns 0 for SUCCESS, or FAILED.
+ **/
int
-mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
+mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
{
MPT_ADAPTER *ioc;
int rc = -1;
- int doTask = 1;
u32 ioc_raw_state;
unsigned long flags;
- /* If FW is being reloaded currently, return success to
- * the calling function.
- */
- if (hd == NULL)
- return 0;
-
ioc = hd->ioc;
- if (ioc == NULL) {
- printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
- return FAILED;
- }
dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
// SJR - CHECKME - Can we avoid this here?
@@ -1541,8 +1575,10 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
spin_unlock_irqrestore(&ioc->diagLock, flags);
/* Wait a fixed amount of time for the TM pending flag to be cleared.
- * If we time out and not bus reset, then we return a FAILED status to the caller.
- * The call to mptscsih_tm_pending_wait() will set the pending flag if we are
+ * If we time out and not bus reset, then we return a FAILED status
+ * to the caller.
+ * The call to mptscsih_tm_pending_wait() will set the pending flag
+ * if we are
* successful. Otherwise, reload the FW.
*/
if (mptscsih_tm_pending_wait(hd) == FAILED) {
@@ -1552,18 +1588,16 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
hd->ioc->name, hd->tmPending));
return FAILED;
} else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
- dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "
- "Timed out waiting for last TM (%d) to complete! \n",
- hd->ioc->name, hd->tmPending));
+ dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target "
+ "reset: Timed out waiting for last TM (%d) "
+ "to complete! \n", hd->ioc->name,
+ hd->tmPending));
return FAILED;
} else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
"Timed out waiting for last TM (%d) to complete! \n",
hd->ioc->name, hd->tmPending));
- if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
- return FAILED;
-
- doTask = 0;
+ return FAILED;
}
} else {
spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
@@ -1571,47 +1605,40 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
}
- /* Is operational?
- */
ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
-#ifdef MPT_DEBUG_RESET
if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
printk(MYIOC_s_WARN_FMT
- "TM Handler: IOC Not operational(0x%x)!\n",
- hd->ioc->name, ioc_raw_state);
- }
-#endif
-
- if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
- && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
-
- /* Isse the Task Mgmt request.
- */
- if (hd->hard_resets < -1)
- hd->hard_resets++;
- rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout);
- if (rc) {
- printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
- } else {
- dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
- }
+ "TM Handler for type=%x: IOC Not operational (0x%x)!\n",
+ ioc->name, type, ioc_raw_state);
+ printk(KERN_WARNING " Issuing HardReset!!\n");
+ if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
+ printk((KERN_WARNING "TMHandler: HardReset "
+ "FAILED!!\n"));
+ return FAILED;
}
- /* Only fall through to the HRH if this is a bus reset
- */
- if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
- ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
- dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
- hd->ioc->name));
- rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
+ if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
+ printk(MYIOC_s_WARN_FMT
+ "TM Handler for type=%x: ioc_state: "
+ "DOORBELL_ACTIVE (0x%x)!\n",
+ ioc->name, type, ioc_raw_state);
+ return FAILED;
}
- /*
- * Check IOCStatus from TM reply message
+ /* Isse the Task Mgmt request.
*/
- if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS)
- rc = FAILED;
+ if (hd->hard_resets < -1)
+ hd->hard_resets++;
+
+ rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun,
+ ctx2abort, timeout);
+ if (rc)
+ printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n",
+ hd->ioc->name);
+ else
+ dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n",
+ hd->ioc->name));
dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
@@ -1620,11 +1647,11 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
+/**
* mptscsih_IssueTaskMgmt - Generic send Task Management function.
* @hd: Pointer to MPT_SCSI_HOST structure
* @type: Task Management type
- * @target: Logical Target ID for reset (if appropriate)
+ * @id: Logical Target ID for reset (if appropriate)
* @lun: Logical Unit for reset (if appropriate)
* @ctx2abort: Context for the task to be aborted (if appropriate)
*
@@ -1633,11 +1660,11 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
*
* Not all fields are meaningfull for all task types.
*
- * Returns 0 for SUCCESS, -999 for "no msg frames",
- * else other non-zero value returned.
- */
+ * Returns 0 for SUCCESS, or FAILED.
+ *
+ **/
static int
-mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
+mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
{
MPT_FRAME_HDR *mf;
SCSITaskMgmt_t *pScsiTm;
@@ -1657,7 +1684,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
/* Format the Request
*/
pScsiTm = (SCSITaskMgmt_t *) mf;
- pScsiTm->TargetID = target;
+ pScsiTm->TargetID = id;
pScsiTm->Bus = channel;
pScsiTm->ChainOffset = 0;
pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
@@ -1668,42 +1695,59 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
- for (ii= 0; ii < 8; ii++) {
- pScsiTm->LUN[ii] = 0;
- }
- pScsiTm->LUN[1] = lun;
+ int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
for (ii=0; ii < 7; ii++)
pScsiTm->Reserved2[ii] = 0;
pScsiTm->TaskMsgContext = ctx2abort;
- dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
- hd->ioc->name, ctx2abort, type));
+ dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) "
+ "type=%d\n", hd->ioc->name, ctx2abort, type));
DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
- sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
- CAN_SLEEP)) != 0) {
- dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
- " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
- hd->ioc, mf));
- mpt_free_msg_frame(hd->ioc, mf);
- return retval;
+ sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) {
+ dfailprintk((MYIOC_s_ERR_FMT "send_handshake FAILED!"
+ " (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd,
+ hd->ioc, mf, retval));
+ goto fail_out;
}
if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
- dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
+ dfailprintk((MYIOC_s_ERR_FMT "task management request TIMED OUT!"
" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
hd->ioc, mf));
- mpt_free_msg_frame(hd->ioc, mf);
dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
hd->ioc->name));
retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
+ dtmprintk((MYIOC_s_INFO_FMT "rc=%d \n",
+ hd->ioc->name, retval));
+ goto fail_out;
}
+ /*
+ * Handle success case, see if theres a non-zero ioc_status.
+ */
+ if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS ||
+ hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
+ hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
+ retval = 0;
+ else
+ retval = FAILED;
+
return retval;
+
+ fail_out:
+
+ /*
+ * Free task managment mf, and corresponding tm flags
+ */
+ mpt_free_msg_frame(hd->ioc, mf);
+ hd->tmPending = 0;
+ hd->tmState = TM_STATE_NONE;
+ return FAILED;
}
static int
@@ -1728,7 +1772,7 @@ mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
* (linux scsi_host_template.eh_abort_handler routine)
*
* Returns SUCCESS or FAILED.
- */
+ **/
int
mptscsih_abort(struct scsi_cmnd * SCpnt)
{
@@ -1764,9 +1808,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
return SUCCESS;
}
- if (hd->resetPending) {
+ if (hd->resetPending)
return FAILED;
- }
if (hd->timeouts < -1)
hd->timeouts++;
@@ -1789,13 +1832,12 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
vdev = SCpnt->device->hostdata;
retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
- vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
+ vdev->vtarget->channel, vdev->vtarget->id, vdev->lun,
ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
- SCpnt->serial_number == sn) {
+ SCpnt->serial_number == sn)
retval = FAILED;
- }
printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
hd->ioc->name,
@@ -1803,12 +1845,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
if (retval == 0)
return SUCCESS;
-
- if(retval != FAILED ) {
- hd->tmPending = 0;
- hd->tmState = TM_STATE_NONE;
- }
- return FAILED;
+ else
+ return FAILED;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1819,7 +1857,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
* (linux scsi_host_template.eh_dev_reset_handler routine)
*
* Returns SUCCESS or FAILED.
- */
+ **/
int
mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
{
@@ -1845,7 +1883,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
vdev = SCpnt->device->hostdata;
retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
- vdev->vtarget->bus_id, vdev->vtarget->target_id,
+ vdev->vtarget->channel, vdev->vtarget->id,
0, 0, mptscsih_get_tm_timeout(hd->ioc));
printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
@@ -1854,14 +1892,11 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
if (retval == 0)
return SUCCESS;
-
- if(retval != FAILED ) {
- hd->tmPending = 0;
- hd->tmState = TM_STATE_NONE;
- }
- return FAILED;
+ else
+ return FAILED;
}
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
@@ -1870,7 +1905,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
* (linux scsi_host_template.eh_bus_reset_handler routine)
*
* Returns SUCCESS or FAILED.
- */
+ **/
int
mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
{
@@ -1896,7 +1931,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
vdev = SCpnt->device->hostdata;
retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
- vdev->vtarget->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
+ vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
hd->ioc->name,
@@ -1904,12 +1939,8 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
if (retval == 0)
return SUCCESS;
-
- if(retval != FAILED ) {
- hd->tmPending = 0;
- hd->tmState = TM_STATE_NONE;
- }
- return FAILED;
+ else
+ return FAILED;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1992,7 +2023,6 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
/**
* mptscsih_tm_wait_for_completion - wait for completion of TM task
* @hd: Pointer to MPT host structure.
- * @timeout: timeout in seconds
*
* Returns {SUCCESS,FAILED}.
*/
@@ -2066,7 +2096,7 @@ mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
* load/init time via the mpt_register() API call.
*
* Returns 1 indicating alloc'd request frame ptr should be freed.
- */
+ **/
int
mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
{
@@ -2076,78 +2106,85 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
unsigned long flags;
u16 iocstatus;
u8 tmType;
+ u32 termination_count;
dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
- ioc->name, mf, mr));
- if (ioc->sh) {
- /* Depending on the thread, a timer is activated for
- * the TM request. Delete this timer on completion of TM.
- * Decrement count of outstanding TM requests.
- */
- hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
- } else {
- dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
- ioc->name));
+ ioc->name, mf, mr));
+ if (!ioc->sh) {
+ dtmprintk((MYIOC_s_WARN_FMT
+ "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name));
return 1;
}
if (mr == NULL) {
- dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
- ioc->name, mf));
+ dtmprintk((MYIOC_s_WARN_FMT
+ "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf));
return 1;
- } else {
- pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
- pScsiTmReq = (SCSITaskMgmt_t*)mf;
-
- /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
- tmType = pScsiTmReq->TaskType;
+ }
- if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
- pScsiTmReply->ResponseCode)
- mptscsih_taskmgmt_response_code(ioc,
- pScsiTmReply->ResponseCode);
+ hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
+ pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
+ pScsiTmReq = (SCSITaskMgmt_t*)mf;
+ tmType = pScsiTmReq->TaskType;
+ iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+ termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
+
+ if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
+ pScsiTmReply->ResponseCode)
+ mptscsih_taskmgmt_response_code(ioc,
+ pScsiTmReply->ResponseCode);
+ DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
+
+#if defined(MPT_DEBUG_REPLY) || defined(MPT_DEBUG_TM)
+ printk("%s: ha=%d [%d:%d:0] task_type=0x%02X "
+ "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X "
+ "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus,
+ pScsiTmReply->TargetID, pScsiTmReq->TaskType,
+ le16_to_cpu(pScsiTmReply->IOCStatus),
+ le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode,
+ le32_to_cpu(pScsiTmReply->TerminationCount));
+#endif
+ if (!iocstatus) {
+ dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
+ hd->abortSCpnt = NULL;
+ goto out;
+ }
- dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n",
- ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
- DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
+ /* Error? (anything non-zero?) */
- iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
- hd->tm_iocstatus = iocstatus;
- dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
- ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
- /* Error? (anything non-zero?) */
- if (iocstatus) {
+ /* clear flags and continue.
+ */
+ switch (tmType) {
- /* clear flags and continue.
- */
- if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
- hd->abortSCpnt = NULL;
+ case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
+ if (termination_count == 1)
+ iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED;
+ hd->abortSCpnt = NULL;
+ break;
- /* If an internal command is present
- * or the TM failed - reload the FW.
- * FC FW may respond FAILED to an ABORT
- */
- if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
- if ((hd->cmdPtr) ||
- (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
- if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
- printk((KERN_WARNING
- " Firmware Reload FAILED!!\n"));
- }
- }
- }
- } else {
- dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
+ case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:
- hd->abortSCpnt = NULL;
+ /* If an internal command is present
+ * or the TM failed - reload the FW.
+ * FC FW may respond FAILED to an ABORT
+ */
+ if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED ||
+ hd->cmdPtr)
+ if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
+ printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
+ break;
- }
+ case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
+ default:
+ break;
}
+ out:
spin_lock_irqsave(&ioc->FreeQlock, flags);
hd->tmPending = 0;
- spin_unlock_irqrestore(&ioc->FreeQlock, flags);
hd->tmState = TM_STATE_NONE;
+ hd->tm_iocstatus = iocstatus;
+ spin_unlock_irqrestore(&ioc->FreeQlock, flags);
return 1;
}
@@ -2191,7 +2228,7 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
dprintk((KERN_NOTICE
": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
- sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors));
+ sdev->id, sdev->lun, sdev->channel, (int)cylinders, heads, sectors));
return 0;
}
@@ -2200,115 +2237,78 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
*
*/
int
-mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
+mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
{
+ struct inactive_raid_component_info *component_info;
int i;
+ int rc = 0;
- if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
- return 0;
+ if (!ioc->raid_data.pIocPg3)
+ goto out;
for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
- if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
- return 1;
- }
- return 0;
-}
-EXPORT_SYMBOL(mptscsih_is_phys_disk);
-
-int
-mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid)
-{
- int i;
-
- if (!hd->ioc->raid_data.isRaid || !hd->ioc->raid_data.pIocPg3)
- return -ENXIO;
-
- for (i = 0; i < hd->ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
- if (physdiskid ==
- hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
- return hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
+ if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
+ (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
+ rc = 1;
+ goto out;
+ }
}
- return -ENXIO;
-}
-EXPORT_SYMBOL(mptscsih_raid_id_to_num);
+ /*
+ * Check inactive list for matching phys disks
+ */
+ if (list_empty(&ioc->raid_data.inactive_list))
+ goto out;
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * OS entry point to allow host driver to alloc memory
- * for each scsi target. Called once per device the bus scan.
- * Return non-zero if allocation fails.
- */
-int
-mptscsih_target_alloc(struct scsi_target *starget)
-{
- VirtTarget *vtarget;
+ down(&ioc->raid_data.inactive_list_mutex);
+ list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
+ list) {
+ if ((component_info->d.PhysDiskID == id) &&
+ (component_info->d.PhysDiskBus == channel))
+ rc = 1;
+ }
+ up(&ioc->raid_data.inactive_list_mutex);
- vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
- if (!vtarget)
- return -ENOMEM;
- starget->hostdata = vtarget;
- vtarget->starget = starget;
- return 0;
+ out:
+ return rc;
}
+EXPORT_SYMBOL(mptscsih_is_phys_disk);
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * OS entry point to allow host driver to alloc memory
- * for each scsi device. Called once per device the bus scan.
- * Return non-zero if allocation fails.
- */
-int
-mptscsih_slave_alloc(struct scsi_device *sdev)
+u8
+mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
{
- struct Scsi_Host *host = sdev->host;
- MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
- VirtTarget *vtarget;
- VirtDevice *vdev;
- struct scsi_target *starget;
+ struct inactive_raid_component_info *component_info;
+ int i;
+ int rc = -ENXIO;
- vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
- if (!vdev) {
- printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
- hd->ioc->name, sizeof(VirtDevice));
- return -ENOMEM;
+ if (!ioc->raid_data.pIocPg3)
+ goto out;
+ for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+ if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
+ (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
+ rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
+ goto out;
+ }
}
- vdev->lun = sdev->lun;
- sdev->hostdata = vdev;
-
- starget = scsi_target(sdev);
- vtarget = starget->hostdata;
+ /*
+ * Check inactive list for matching phys disks
+ */
+ if (list_empty(&ioc->raid_data.inactive_list))
+ goto out;
- vdev->vtarget = vtarget;
-
- if (vtarget->num_luns == 0) {
- hd->Targets[sdev->id] = vtarget;
- vtarget->ioc_id = hd->ioc->id;
- vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
- vtarget->target_id = sdev->id;
- vtarget->bus_id = sdev->channel;
- if (hd->ioc->bus_type == SPI && sdev->channel == 0 &&
- hd->ioc->raid_data.isRaid & (1 << sdev->id)) {
- vtarget->raidVolume = 1;
- ddvtprintk((KERN_INFO
- "RAID Volume @ id %d\n", sdev->id));
- }
+ down(&ioc->raid_data.inactive_list_mutex);
+ list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
+ list) {
+ if ((component_info->d.PhysDiskID == id) &&
+ (component_info->d.PhysDiskBus == channel))
+ rc = component_info->d.PhysDiskNum;
}
- vtarget->num_luns++;
- return 0;
-}
+ up(&ioc->raid_data.inactive_list_mutex);
-/*
- * OS entry point to allow for host driver to free allocated memory
- * Called if no device present or device being unloaded
- */
-void
-mptscsih_target_destroy(struct scsi_target *starget)
-{
- if (starget->hostdata)
- kfree(starget->hostdata);
- starget->hostdata = NULL;
+ out:
+ return rc;
}
+EXPORT_SYMBOL(mptscsih_raid_id_to_num);
/*
* OS entry point to allow for host driver to free allocated memory
@@ -2328,11 +2328,7 @@ mptscsih_slave_destroy(struct scsi_device *sdev)
vdevice = sdev->hostdata;
mptscsih_search_running_cmds(hd, vdevice);
- vtarget->luns[0] &= ~(1 << vdevice->lun);
vtarget->num_luns--;
- if (vtarget->num_luns == 0) {
- hd->Targets[sdev->id] = NULL;
- }
mptscsih_synchronize_cache(hd, vdevice);
kfree(vdevice);
sdev->hostdata = NULL;
@@ -2394,15 +2390,14 @@ mptscsih_slave_configure(struct scsi_device *sdev)
VirtDevice *vdevice;
struct scsi_target *starget;
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
- int indexed_lun, lun_index;
starget = scsi_target(sdev);
vtarget = starget->hostdata;
vdevice = sdev->hostdata;
dsprintk((MYIOC_s_INFO_FMT
- "device @ %p, id=%d, LUN=%d, channel=%d\n",
- hd->ioc->name, sdev, sdev->id, sdev->lun, sdev->channel));
+ "device @ %p, channel=%d, id=%d, lun=%d\n",
+ hd->ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
if (hd->ioc->bus_type == SPI)
dsprintk((MYIOC_s_INFO_FMT
"sdtr %d wdtr %d ppr %d inq length=%d\n",
@@ -2415,11 +2410,7 @@ mptscsih_slave_configure(struct scsi_device *sdev)
goto slave_configure_exit;
}
- vdevice->configured_lun=1;
- lun_index = (vdevice->lun >> 5); /* 32 luns per lun_index */
- indexed_lun = (vdevice->lun % 32);
- vtarget->luns[lun_index] |= (1 << indexed_lun);
- mptscsih_initTarget(hd, vtarget, sdev);
+ vdevice->configured_lun = 1;
mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
dsprintk((MYIOC_s_INFO_FMT
@@ -2683,285 +2674,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * mptscsih_initTarget - Target, LUN alloc/free functionality.
- * @hd: Pointer to MPT_SCSI_HOST structure
- * @vtarget: per target private data
- * @sdev: SCSI device
- *
- * NOTE: It's only SAFE to call this routine if data points to
- * sane & valid STANDARD INQUIRY data!
- *
- * Allocate and initialize memory for this target.
- * Save inquiry data.
- *
- */
-static void
-mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget,
- struct scsi_device *sdev)
-{
- dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
- hd->ioc->name, vtarget->bus_id, vtarget->target_id,
- sdev->lun, hd));
-
- /* Is LUN supported? If so, upper 2 bits will be 0
- * in first byte of inquiry data.
- */
- if (sdev->inq_periph_qual != 0)
- return;
-
- if (vtarget == NULL)
- return;
-
- vtarget->type = sdev->type;
-
- if (hd->ioc->bus_type != SPI)
- return;
-
- if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
- /* Treat all Processors as SAF-TE if
- * command line option is set */
- vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
- mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
- }else if ((sdev->type == TYPE_PROCESSOR) &&
- !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
- if (sdev->inquiry_len > 49 ) {
- if (sdev->inquiry[44] == 'S' &&
- sdev->inquiry[45] == 'A' &&
- sdev->inquiry[46] == 'F' &&
- sdev->inquiry[47] == '-' &&
- sdev->inquiry[48] == 'T' &&
- sdev->inquiry[49] == 'E' ) {
- vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
- mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
- }
- }
- }
- mptscsih_setTargetNegoParms(hd, vtarget, sdev);
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * Update the target negotiation parameters based on the
- * the Inquiry data, adapter capabilities, and NVRAM settings.
- *
- */
-static void
-mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
- struct scsi_device *sdev)
-{
- SpiCfgData *pspi_data = &hd->ioc->spi_data;
- int id = (int) target->target_id;
- int nvram;
- u8 width = MPT_NARROW;
- u8 factor = MPT_ASYNC;
- u8 offset = 0;
- u8 nfactor;
- u8 noQas = 1;
-
- target->negoFlags = pspi_data->noQas;
-
- /* noQas == 0 => device supports QAS. */
-
- if (sdev->scsi_level < SCSI_2) {
- width = 0;
- factor = MPT_ULTRA2;
- offset = pspi_data->maxSyncOffset;
- target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
- } else {
- if (scsi_device_wide(sdev)) {
- width = 1;
- }
-
- if (scsi_device_sync(sdev)) {
- factor = pspi_data->minSyncFactor;
- if (!scsi_device_dt(sdev))
- factor = MPT_ULTRA2;
- else {
- if (!scsi_device_ius(sdev) &&
- !scsi_device_qas(sdev))
- factor = MPT_ULTRA160;
- else {
- factor = MPT_ULTRA320;
- if (scsi_device_qas(sdev)) {
- ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id));
- noQas = 0;
- }
- if (sdev->type == TYPE_TAPE &&
- scsi_device_ius(sdev))
- target->negoFlags |= MPT_TAPE_NEGO_IDP;
- }
- }
- offset = pspi_data->maxSyncOffset;
-
- /* If RAID, never disable QAS
- * else if non RAID, do not disable
- * QAS if bit 1 is set
- * bit 1 QAS support, non-raid only
- * bit 0 IU support
- */
- if (target->raidVolume == 1) {
- noQas = 0;
- }
- } else {
- factor = MPT_ASYNC;
- offset = 0;
- }
- }
-
- if (!sdev->tagged_supported) {
- target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
- }
-
- /* Update tflags based on NVRAM settings. (SCSI only)
- */
- if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
- nvram = pspi_data->nvram[id];
- nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
-
- if (width)
- width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
-
- if (offset > 0) {
- /* Ensure factor is set to the
- * maximum of: adapter, nvram, inquiry
- */
- if (nfactor) {
- if (nfactor < pspi_data->minSyncFactor )
- nfactor = pspi_data->minSyncFactor;
-
- factor = max(factor, nfactor);
- if (factor == MPT_ASYNC)
- offset = 0;
- } else {
- offset = 0;
- factor = MPT_ASYNC;
- }
- } else {
- factor = MPT_ASYNC;
- }
- }
-
- /* Make sure data is consistent
- */
- if ((!width) && (factor < MPT_ULTRA2)) {
- factor = MPT_ULTRA2;
- }
-
- /* Save the data to the target structure.
- */
- target->minSyncFactor = factor;
- target->maxOffset = offset;
- target->maxWidth = width;
-
- target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
-
- /* Disable unused features.
- */
- if (!width)
- target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
-
- if (!offset)
- target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
-
- if ( factor > MPT_ULTRA320 )
- noQas = 0;
-
- if (noQas && (pspi_data->noQas == 0)) {
- pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
- target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
-
- /* Disable QAS in a mixed configuration case
- */
-
- ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
- }
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * SCSI Config Page functionality ...
- */
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* mptscsih_writeIOCPage4 - write IOC Page 4
- * @hd: Pointer to a SCSI Host Structure
- * @target_id: write IOC Page4 for this ID & Bus
- *
- * Return: -EAGAIN if unable to obtain a Message Frame
- * or 0 if success.
- *
- * Remark: We do not wait for a return, write pages sequentially.
- */
-static int
-mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
-{
- MPT_ADAPTER *ioc = hd->ioc;
- Config_t *pReq;
- IOCPage4_t *IOCPage4Ptr;
- MPT_FRAME_HDR *mf;
- dma_addr_t dataDma;
- u16 req_idx;
- u32 frameOffset;
- u32 flagsLength;
- int ii;
-
- /* Get a MF for this command.
- */
- if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
- dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
- ioc->name));
- return -EAGAIN;
- }
-
- /* Set the request and the data pointers.
- * Place data at end of MF.
- */
- pReq = (Config_t *)mf;
-
- req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
- frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
-
- /* Complete the request frame (same for all requests).
- */
- pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
- pReq->Reserved = 0;
- pReq->ChainOffset = 0;
- pReq->Function = MPI_FUNCTION_CONFIG;
- pReq->ExtPageLength = 0;
- pReq->ExtPageType = 0;
- pReq->MsgFlags = 0;
- for (ii=0; ii < 8; ii++) {
- pReq->Reserved2[ii] = 0;
- }
-
- IOCPage4Ptr = ioc->spi_data.pIocPg4;
- dataDma = ioc->spi_data.IocPg4_dma;
- ii = IOCPage4Ptr->ActiveSEP++;
- IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
- IOCPage4Ptr->SEP[ii].SEPBus = bus;
- pReq->Header = IOCPage4Ptr->Header;
- pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
-
- /* Add a SGE to the config request.
- */
- flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
- (IOCPage4Ptr->Header.PageLength + ii) * 4;
-
- mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
-
- dinitprintk((MYIOC_s_INFO_FMT
- "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
- ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
-
- mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
-
- return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
* Bus Scan and Domain Validation functionality ...
*/
@@ -3343,7 +3055,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
} else {
pScsiReq->TargetID = io->id;
- pScsiReq->Bus = io->bus;
+ pScsiReq->Bus = io->channel;
pScsiReq->ChainOffset = 0;
pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
}
@@ -3356,9 +3068,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
pScsiReq->MsgFlags = mpt_msg_flags();
/* MsgContext set in mpt_get_msg_fram call */
- for (ii=0; ii < 8; ii++)
- pScsiReq->LUN[ii] = 0;
- pScsiReq->LUN[1] = io->lun;
+ int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
if (io->flags & MPT_ICFLAG_TAGGED_CMD)
pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
@@ -3379,7 +3089,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
+ (my_idx * MPT_SENSE_BUFFER_ALLOC));
ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
- hd->ioc->name, cmd, io->bus, io->id, io->lun));
+ hd->ioc->name, cmd, io->channel, io->id, io->lun));
if (dir == MPI_SCSIIO_CONTROL_READ) {
mpt_add_sge((char *) &pScsiReq->SGL,
@@ -3462,9 +3172,9 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
iocmd.data_dma = -1;
iocmd.size = 0;
iocmd.rsvd = iocmd.rsvd2 = 0;
- iocmd.bus = vdevice->vtarget->bus_id;
- iocmd.id = vdevice->vtarget->target_id;
- iocmd.lun = (u8)vdevice->lun;
+ iocmd.channel = vdevice->vtarget->channel;
+ iocmd.id = vdevice->vtarget->id;
+ iocmd.lun = vdevice->lun;
if ((vdevice->vtarget->type == TYPE_DISK) &&
(vdevice->configured_lun))
@@ -3480,9 +3190,6 @@ EXPORT_SYMBOL(mptscsih_resume);
EXPORT_SYMBOL(mptscsih_proc_info);
EXPORT_SYMBOL(mptscsih_info);
EXPORT_SYMBOL(mptscsih_qcmd);
-EXPORT_SYMBOL(mptscsih_target_alloc);
-EXPORT_SYMBOL(mptscsih_slave_alloc);
-EXPORT_SYMBOL(mptscsih_target_destroy);
EXPORT_SYMBOL(mptscsih_slave_destroy);
EXPORT_SYMBOL(mptscsih_slave_configure);
EXPORT_SYMBOL(mptscsih_abort);
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 187c8af0890b..843c01a6aa0e 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -6,7 +6,7 @@
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Copyright (c) 1999-2007 LSI Logic Corporation
- * (mailto:mpt_linux_developer@lsil.com)
+ * (mailto:mpt_linux_developer@lsi.com)
*
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -53,6 +53,24 @@
* SCSI Public stuff...
*/
+#define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */
+#define MPT_SCANDV_DID_RESET (0x00000001)
+#define MPT_SCANDV_SENSE (0x00000002)
+#define MPT_SCANDV_SOME_ERROR (0x00000004)
+#define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008)
+#define MPT_SCANDV_ISSUE_SENSE (0x00000010)
+#define MPT_SCANDV_FALLBACK (0x00000020)
+
+#define MPT_SCANDV_MAX_RETRIES (10)
+
+#define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */
+#define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */
+#define MPT_ICFLAG_EBOS 0x04 /* ReadBuffer Echo buffer has EBOS */
+#define MPT_ICFLAG_PHYS_DISK 0x08 /* Any SCSI IO but do Phys Disk Format */
+#define MPT_ICFLAG_TAGGED_CMD 0x10 /* Do tagged IO */
+#define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */
+#define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */
+
#define MPT_SCSI_CMD_PER_DEV_HIGH 64
#define MPT_SCSI_CMD_PER_DEV_LOW 32
@@ -69,9 +87,22 @@
#define MPTSCSIH_SAF_TE 0
#define MPTSCSIH_PT_CLEAR 0
-
#endif
+typedef struct _internal_cmd {
+ char *data; /* data pointer */
+ dma_addr_t data_dma; /* data dma address */
+ int size; /* transfer size */
+ u8 cmd; /* SCSI Op Code */
+ u8 channel; /* bus number */
+ u8 id; /* SCSI ID (virtual) */
+ int lun;
+ u8 flags; /* Bit Field - See above */
+ u8 physDiskNum; /* Phys disk number, -1 else */
+ u8 rsvd2;
+ u8 rsvd;
+} INTERNAL_CMD;
+
extern void mptscsih_remove(struct pci_dev *);
extern void mptscsih_shutdown(struct pci_dev *);
#ifdef CONFIG_PM
@@ -81,9 +112,6 @@ extern int mptscsih_resume(struct pci_dev *pdev);
extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func);
extern const char * mptscsih_info(struct Scsi_Host *SChost);
extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *));
-extern int mptscsih_target_alloc(struct scsi_target *starget);
-extern int mptscsih_slave_alloc(struct scsi_device *device);
-extern void mptscsih_target_destroy(struct scsi_target *starget);
extern void mptscsih_slave_destroy(struct scsi_device *device);
extern int mptscsih_slave_configure(struct scsi_device *device);
extern int mptscsih_abort(struct scsi_cmnd * SCpnt);
@@ -98,6 +126,6 @@ extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pE
extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
extern void mptscsih_timer_expired(unsigned long data);
-extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
-extern int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid);
-extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
+extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
+extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id);
+extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 203c661d2c79..c31a9e3c8a26 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -4,7 +4,7 @@
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Copyright (c) 1999-2007 LSI Logic Corporation
- * (mailto:mpt_linux_developer@lsil.com)
+ * (mailto:mpt_linux_developer@lsi.com)
*
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -65,6 +65,7 @@
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>
+#include <scsi/scsi_dbg.h>
#include "mptbase.h"
#include "mptscsih.h"
@@ -95,25 +96,339 @@ static int mptspiDoneCtx = -1;
static int mptspiTaskCtx = -1;
static int mptspiInternalCtx = -1; /* Used only for internal commands */
+/**
+ * mptspi_setTargetNegoParms - Update the target negotiation
+ * parameters based on the the Inquiry data, adapter capabilities,
+ * and NVRAM settings
+ *
+ * @hd: Pointer to a SCSI Host Structure
+ * @vtarget: per target private data
+ * @sdev: SCSI device
+ *
+ **/
+static void
+mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
+ struct scsi_device *sdev)
+{
+ SpiCfgData *pspi_data = &hd->ioc->spi_data;
+ int id = (int) target->id;
+ int nvram;
+ u8 width = MPT_NARROW;
+ u8 factor = MPT_ASYNC;
+ u8 offset = 0;
+ u8 nfactor;
+ u8 noQas = 1;
+
+ target->negoFlags = pspi_data->noQas;
+
+ if (sdev->scsi_level < SCSI_2) {
+ width = 0;
+ factor = MPT_ULTRA2;
+ offset = pspi_data->maxSyncOffset;
+ target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
+ } else {
+ if (scsi_device_wide(sdev))
+ width = 1;
+
+ if (scsi_device_sync(sdev)) {
+ factor = pspi_data->minSyncFactor;
+ if (!scsi_device_dt(sdev))
+ factor = MPT_ULTRA2;
+ else {
+ if (!scsi_device_ius(sdev) &&
+ !scsi_device_qas(sdev))
+ factor = MPT_ULTRA160;
+ else {
+ factor = MPT_ULTRA320;
+ if (scsi_device_qas(sdev)) {
+ ddvprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id));
+ noQas = 0;
+ }
+ if (sdev->type == TYPE_TAPE &&
+ scsi_device_ius(sdev))
+ target->negoFlags |= MPT_TAPE_NEGO_IDP;
+ }
+ }
+ offset = pspi_data->maxSyncOffset;
+
+ /* If RAID, never disable QAS
+ * else if non RAID, do not disable
+ * QAS if bit 1 is set
+ * bit 1 QAS support, non-raid only
+ * bit 0 IU support
+ */
+ if (target->raidVolume == 1)
+ noQas = 0;
+ } else {
+ factor = MPT_ASYNC;
+ offset = 0;
+ }
+ }
+
+ if (!sdev->tagged_supported)
+ target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
+
+ /* Update tflags based on NVRAM settings. (SCSI only)
+ */
+ if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
+ nvram = pspi_data->nvram[id];
+ nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
+
+ if (width)
+ width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
+
+ if (offset > 0) {
+ /* Ensure factor is set to the
+ * maximum of: adapter, nvram, inquiry
+ */
+ if (nfactor) {
+ if (nfactor < pspi_data->minSyncFactor )
+ nfactor = pspi_data->minSyncFactor;
+
+ factor = max(factor, nfactor);
+ if (factor == MPT_ASYNC)
+ offset = 0;
+ } else {
+ offset = 0;
+ factor = MPT_ASYNC;
+ }
+ } else {
+ factor = MPT_ASYNC;
+ }
+ }
+
+ /* Make sure data is consistent
+ */
+ if ((!width) && (factor < MPT_ULTRA2))
+ factor = MPT_ULTRA2;
+
+ /* Save the data to the target structure.
+ */
+ target->minSyncFactor = factor;
+ target->maxOffset = offset;
+ target->maxWidth = width;
+
+ target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
+
+ /* Disable unused features.
+ */
+ if (!width)
+ target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
+
+ if (!offset)
+ target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
+
+ if ( factor > MPT_ULTRA320 )
+ noQas = 0;
+
+ if (noQas && (pspi_data->noQas == 0)) {
+ pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
+ target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+
+ /* Disable QAS in a mixed configuration case
+ */
+
+ ddvprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
+ }
+}
+
+/**
+ * mptspi_writeIOCPage4 - write IOC Page 4
+ * @hd: Pointer to a SCSI Host Structure
+ * @channel:
+ * @id: write IOC Page4 for this ID & Bus
+ *
+ * Return: -EAGAIN if unable to obtain a Message Frame
+ * or 0 if success.
+ *
+ * Remark: We do not wait for a return, write pages sequentially.
+ **/
+static int
+mptspi_writeIOCPage4(MPT_SCSI_HOST *hd, u8 channel , u8 id)
+{
+ MPT_ADAPTER *ioc = hd->ioc;
+ Config_t *pReq;
+ IOCPage4_t *IOCPage4Ptr;
+ MPT_FRAME_HDR *mf;
+ dma_addr_t dataDma;
+ u16 req_idx;
+ u32 frameOffset;
+ u32 flagsLength;
+ int ii;
+
+ /* Get a MF for this command.
+ */
+ if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
+ dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
+ ioc->name));
+ return -EAGAIN;
+ }
+
+ /* Set the request and the data pointers.
+ * Place data at end of MF.
+ */
+ pReq = (Config_t *)mf;
+
+ req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+ frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
+
+ /* Complete the request frame (same for all requests).
+ */
+ pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+ pReq->Reserved = 0;
+ pReq->ChainOffset = 0;
+ pReq->Function = MPI_FUNCTION_CONFIG;
+ pReq->ExtPageLength = 0;
+ pReq->ExtPageType = 0;
+ pReq->MsgFlags = 0;
+ for (ii=0; ii < 8; ii++) {
+ pReq->Reserved2[ii] = 0;
+ }
+
+ IOCPage4Ptr = ioc->spi_data.pIocPg4;
+ dataDma = ioc->spi_data.IocPg4_dma;
+ ii = IOCPage4Ptr->ActiveSEP++;
+ IOCPage4Ptr->SEP[ii].SEPTargetID = id;
+ IOCPage4Ptr->SEP[ii].SEPBus = channel;
+ pReq->Header = IOCPage4Ptr->Header;
+ pReq->PageAddress = cpu_to_le32(id | (channel << 8 ));
+
+ /* Add a SGE to the config request.
+ */
+ flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
+ (IOCPage4Ptr->Header.PageLength + ii) * 4;
+
+ mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
+
+ ddvprintk((MYIOC_s_INFO_FMT
+ "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
+ ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, channel));
+
+ mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
+
+ return 0;
+}
+
+/**
+ * mptspi_initTarget - Target, LUN alloc/free functionality.
+ * @hd: Pointer to MPT_SCSI_HOST structure
+ * @vtarget: per target private data
+ * @sdev: SCSI device
+ *
+ * NOTE: It's only SAFE to call this routine if data points to
+ * sane & valid STANDARD INQUIRY data!
+ *
+ * Allocate and initialize memory for this target.
+ * Save inquiry data.
+ *
+ **/
+static void
+mptspi_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget,
+ struct scsi_device *sdev)
+{
+
+ /* Is LUN supported? If so, upper 2 bits will be 0
+ * in first byte of inquiry data.
+ */
+ if (sdev->inq_periph_qual != 0)
+ return;
+
+ if (vtarget == NULL)
+ return;
+
+ vtarget->type = sdev->type;
+
+ if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
+ /* Treat all Processors as SAF-TE if
+ * command line option is set */
+ vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+ mptspi_writeIOCPage4(hd, vtarget->channel, vtarget->id);
+ }else if ((sdev->type == TYPE_PROCESSOR) &&
+ !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
+ if (sdev->inquiry_len > 49 ) {
+ if (sdev->inquiry[44] == 'S' &&
+ sdev->inquiry[45] == 'A' &&
+ sdev->inquiry[46] == 'F' &&
+ sdev->inquiry[47] == '-' &&
+ sdev->inquiry[48] == 'T' &&
+ sdev->inquiry[49] == 'E' ) {
+ vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+ mptspi_writeIOCPage4(hd, vtarget->channel, vtarget->id);
+ }
+ }
+ }
+ mptspi_setTargetNegoParms(hd, vtarget, sdev);
+}
+
+/**
+ * mptspi_is_raid - Determines whether target is belonging to volume
+ * @hd: Pointer to a SCSI HOST structure
+ * @id: target device id
+ *
+ * Return:
+ * non-zero = true
+ * zero = false
+ *
+ */
+static int
+mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id)
+{
+ int i, rc = 0;
+
+ if (!hd->ioc->raid_data.pIocPg2)
+ goto out;
+
+ if (!hd->ioc->raid_data.pIocPg2->NumActiveVolumes)
+ goto out;
+ for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
+ if (hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) {
+ rc = 1;
+ goto out;
+ }
+ }
+
+ out:
+ return rc;
+}
+
static int mptspi_target_alloc(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(&starget->dev);
struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
- int ret;
+ VirtTarget *vtarget;
if (hd == NULL)
return -ENODEV;
- ret = mptscsih_target_alloc(starget);
- if (ret)
- return ret;
+ vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
+ if (!vtarget)
+ return -ENOMEM;
+
+ vtarget->ioc_id = hd->ioc->id;
+ vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
+ vtarget->id = (u8)starget->id;
+ vtarget->channel = (u8)starget->channel;
+ vtarget->starget = starget;
+ starget->hostdata = vtarget;
+
+ if (starget->channel == 1) {
+ if (mptscsih_is_phys_disk(hd->ioc, 0, starget->id) == 0)
+ return 0;
+ vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
+ /* The real channel for this device is zero */
+ vtarget->channel = 0;
+ /* The actual physdisknum (for RAID passthrough) */
+ vtarget->id = mptscsih_raid_id_to_num(hd->ioc, 0,
+ starget->id);
+ }
- /* if we're a device on virtual channel 1 and we're not part
- * of an array, just return here (otherwise the setup below
- * may actually affect a real physical device on channel 0 */
- if (starget->channel == 1 &&
- mptscsih_raid_id_to_num(hd, starget->id) < 0)
- return 0;
+ if (starget->channel == 0 &&
+ mptspi_is_raid(hd, starget->id)) {
+ vtarget->raidVolume = 1;
+ ddvprintk((KERN_INFO
+ "RAID Volume @ channel=%d id=%d\n", starget->channel,
+ starget->id));
+ }
if (hd->ioc->spi_data.nvram &&
hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) {
@@ -132,6 +447,64 @@ static int mptspi_target_alloc(struct scsi_target *starget)
return 0;
}
+void
+mptspi_target_destroy(struct scsi_target *starget)
+{
+ if (starget->hostdata)
+ kfree(starget->hostdata);
+ starget->hostdata = NULL;
+}
+
+/**
+ * mptspi_print_write_nego - negotiation parameters debug info that is being sent
+ * @hd: Pointer to a SCSI HOST structure
+ * @starget: SCSI target
+ * @ii: negotiation parameters
+ *
+ */
+static void
+mptspi_print_write_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii)
+{
+ ddvprintk((MYIOC_s_INFO_FMT "id=%d Requested = 0x%08x"
+ " ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n",
+ hd->ioc->name, starget->id, ii,
+ ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "",
+ ((ii >> 8) & 0xFF), ((ii >> 16) & 0xFF),
+ ii & MPI_SCSIDEVPAGE0_NP_IU ? "IU ": "",
+ ii & MPI_SCSIDEVPAGE0_NP_DT ? "DT ": "",
+ ii & MPI_SCSIDEVPAGE0_NP_QAS ? "QAS ": "",
+ ii & MPI_SCSIDEVPAGE0_NP_HOLD_MCS ? "HOLDMCS ": "",
+ ii & MPI_SCSIDEVPAGE0_NP_WR_FLOW ? "WRFLOW ": "",
+ ii & MPI_SCSIDEVPAGE0_NP_RD_STRM ? "RDSTRM ": "",
+ ii & MPI_SCSIDEVPAGE0_NP_RTI ? "RTI ": "",
+ ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": ""));
+}
+
+/**
+ * mptspi_print_read_nego - negotiation parameters debug info that is being read
+ * @hd: Pointer to a SCSI HOST structure
+ * @starget: SCSI target
+ * @ii: negotiation parameters
+ *
+ */
+static void
+mptspi_print_read_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii)
+{
+ ddvprintk((MYIOC_s_INFO_FMT "id=%d Read = 0x%08x"
+ " ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n",
+ hd->ioc->name, starget->id, ii,
+ ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "",
+ ((ii >> 8) & 0xFF), ((ii >> 16) & 0xFF),
+ ii & MPI_SCSIDEVPAGE0_NP_IU ? "IU ": "",
+ ii & MPI_SCSIDEVPAGE0_NP_DT ? "DT ": "",
+ ii & MPI_SCSIDEVPAGE0_NP_QAS ? "QAS ": "",
+ ii & MPI_SCSIDEVPAGE0_NP_HOLD_MCS ? "HOLDMCS ": "",
+ ii & MPI_SCSIDEVPAGE0_NP_WR_FLOW ? "WRFLOW ": "",
+ ii & MPI_SCSIDEVPAGE0_NP_RD_STRM ? "RDSTRM ": "",
+ ii & MPI_SCSIDEVPAGE0_NP_RTI ? "RTI ": "",
+ ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": ""));
+}
+
static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0)
{
@@ -147,7 +520,7 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
/* No SPI parameters for RAID devices */
if (starget->channel == 0 &&
- (hd->ioc->raid_data.isRaid & (1 << starget->id)))
+ mptspi_is_raid(hd, starget->id))
return -1;
size = ioc->spi_data.sdp0length * 4;
@@ -185,6 +558,8 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
err = 0;
memcpy(pass_pg0, pg0, size);
+ mptspi_print_read_nego(hd, starget, le32_to_cpu(pg0->NegotiatedParameters));
+
out_free:
dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma);
return err;
@@ -233,7 +608,7 @@ static void mptspi_read_parameters(struct scsi_target *starget)
}
static int
-mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk)
+mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
{
MpiRaidActionRequest_t *pReq;
MPT_FRAME_HDR *mf;
@@ -253,8 +628,8 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk)
pReq->Reserved1 = 0;
pReq->ChainOffset = 0;
pReq->Function = MPI_FUNCTION_RAID_ACTION;
- pReq->VolumeID = disk;
- pReq->VolumeBus = 0;
+ pReq->VolumeID = id;
+ pReq->VolumeBus = channel;
pReq->PhysDiskNum = 0;
pReq->MsgFlags = 0;
pReq->Reserved2 = 0;
@@ -263,8 +638,8 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk)
mpt_add_sge((char *)&pReq->ActionDataSGE,
MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
- ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
- hd->ioc->name, action, io->id));
+ ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action=%x channel=%d id=%d\n",
+ hd->ioc->name, pReq->Action, channel, id));
hd->pLocal = NULL;
hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
@@ -292,12 +667,12 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
/* no DV on RAID devices */
if (sdev->channel == 0 &&
- (hd->ioc->raid_data.isRaid & (1 << sdev->id)))
+ mptspi_is_raid(hd, sdev->id))
return;
/* If this is a piece of a RAID, then quiesce first */
if (sdev->channel == 1 &&
- mptscsih_quiesce_raid(hd, 1, vtarget->target_id) < 0) {
+ mptscsih_quiesce_raid(hd, 1, vtarget->channel, vtarget->id) < 0) {
starget_printk(KERN_ERR, scsi_target(sdev),
"Integrated RAID quiesce failed\n");
return;
@@ -306,7 +681,7 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
spi_dv_device(sdev);
if (sdev->channel == 1 &&
- mptscsih_quiesce_raid(hd, 0, vtarget->target_id) < 0)
+ mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0)
starget_printk(KERN_ERR, scsi_target(sdev),
"Integrated RAID resume failed\n");
@@ -317,54 +692,89 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
static int mptspi_slave_alloc(struct scsi_device *sdev)
{
- int ret;
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
- /* gcc doesn't see that all uses of this variable occur within
- * the if() statements, so stop it from whining */
- int physdisknum = 0;
-
- if (sdev->channel == 1) {
- physdisknum = mptscsih_raid_id_to_num(hd, sdev->id);
+ VirtTarget *vtarget;
+ VirtDevice *vdev;
+ struct scsi_target *starget;
- if (physdisknum < 0)
- return physdisknum;
+ if (sdev->channel == 1 &&
+ mptscsih_is_phys_disk(hd->ioc, 0, sdev->id) == 0)
+ return -ENXIO;
+
+ vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
+ if (!vdev) {
+ printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
+ hd->ioc->name, sizeof(VirtDevice));
+ return -ENOMEM;
}
- ret = mptscsih_slave_alloc(sdev);
+ vdev->lun = sdev->lun;
+ sdev->hostdata = vdev;
- if (ret)
- return ret;
+ starget = scsi_target(sdev);
+ vtarget = starget->hostdata;
+ vdev->vtarget = vtarget;
+ vtarget->num_luns++;
- if (sdev->channel == 1) {
- VirtDevice *vdev = sdev->hostdata;
+ if (sdev->channel == 1)
sdev->no_uld_attach = 1;
- vdev->vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
- /* The real channel for this device is zero */
- vdev->vtarget->bus_id = 0;
- /* The actual physdisknum (for RAID passthrough) */
- vdev->vtarget->target_id = physdisknum;
- }
return 0;
}
static int mptspi_slave_configure(struct scsi_device *sdev)
{
- int ret = mptscsih_slave_configure(sdev);
struct _MPT_SCSI_HOST *hd =
(struct _MPT_SCSI_HOST *)sdev->host->hostdata;
+ VirtTarget *vtarget = scsi_target(sdev)->hostdata;
+ int ret = mptscsih_slave_configure(sdev);
if (ret)
return ret;
+ mptspi_initTarget(hd, vtarget, sdev);
+
+ ddvprintk((MYIOC_s_INFO_FMT "id=%d min_period=0x%02x"
+ " max_offset=0x%02x max_width=%d\n", hd->ioc->name,
+ sdev->id, spi_min_period(scsi_target(sdev)),
+ spi_max_offset(scsi_target(sdev)),
+ spi_max_width(scsi_target(sdev))));
+
if ((sdev->channel == 1 ||
- !(hd->ioc->raid_data.isRaid & (1 << sdev->id))) &&
+ !(mptspi_is_raid(hd, sdev->id))) &&
!spi_initial_dv(sdev->sdev_target))
mptspi_dv_device(hd, sdev);
return 0;
}
+static int
+mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
+{
+ struct _MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
+ VirtDevice *vdev = SCpnt->device->hostdata;
+
+ if (!vdev || !vdev->vtarget) {
+ SCpnt->result = DID_NO_CONNECT << 16;
+ done(SCpnt);
+ return 0;
+ }
+
+ if (SCpnt->device->channel == 1 &&
+ mptscsih_is_phys_disk(hd->ioc, 0, SCpnt->device->id) == 0) {
+ SCpnt->result = DID_NO_CONNECT << 16;
+ done(SCpnt);
+ return 0;
+ }
+
+#ifdef MPT_DEBUG_DV
+ if (spi_dv_pending(scsi_target(SCpnt->device)))
+ scsi_print_command(SCpnt);
+#endif
+
+ return mptscsih_qcmd(SCpnt,done);
+}
+
static void mptspi_slave_destroy(struct scsi_device *sdev)
{
struct scsi_target *starget = scsi_target(sdev);
@@ -392,11 +802,11 @@ static struct scsi_host_template mptspi_driver_template = {
.proc_info = mptscsih_proc_info,
.name = "MPT SPI Host",
.info = mptscsih_info,
- .queuecommand = mptscsih_qcmd,
+ .queuecommand = mptspi_qcmd,
.target_alloc = mptspi_target_alloc,
.slave_alloc = mptspi_slave_alloc,
.slave_configure = mptspi_slave_configure,
- .target_destroy = mptscsih_target_destroy,
+ .target_destroy = mptspi_target_destroy,
.slave_destroy = mptspi_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth,
.eh_abort_handler = mptscsih_abort,
@@ -427,7 +837,7 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
/* don't allow updating nego parameters on RAID devices */
if (starget->channel == 0 &&
- (hd->ioc->raid_data.isRaid & (1 << starget->id)))
+ mptspi_is_raid(hd, starget->id))
return -1;
size = ioc->spi_data.sdp1length * 4;
@@ -460,6 +870,8 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
pg1->Header.PageNumber = hdr.PageNumber;
pg1->Header.PageType = hdr.PageType;
+ mptspi_print_write_nego(hd, starget, le32_to_cpu(pg1->RequestedParameters));
+
if (mpt_config(ioc, &cfg)) {
starget_printk(KERN_ERR, starget, "mpt_config failed\n");
goto out_free;
@@ -672,9 +1084,9 @@ static void mpt_work_wrapper(struct work_struct *work)
if (sdev->channel != 1)
continue;
- /* The target_id is the raid PhysDiskNum, even if
+ /* The id is the raid PhysDiskNum, even if
* starget->id is the actual target address */
- if(vtarget->target_id != disk)
+ if(vtarget->id != disk)
continue;
starget_printk(KERN_INFO, vtarget->starget,
@@ -727,7 +1139,7 @@ mptspi_deny_binding(struct scsi_target *starget)
{
struct _MPT_SCSI_HOST *hd =
(struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata;
- return ((hd->ioc->raid_data.isRaid & (1 << starget->id)) &&
+ return ((mptspi_is_raid(hd, starget->id)) &&
starget->channel == 0) ? 1 : 0;
}
@@ -945,14 +1357,13 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
* max_lun = 1 + actual last lun,
* see hosts.h :o(
*/
- sh->max_id = MPT_MAX_SCSI_DEVICES;
+ sh->max_id = ioc->devices_per_bus;
sh->max_lun = MPT_LAST_LUN + 1;
/*
* If RAID Firmware Detected, setup virtual channel
*/
- if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
- > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
+ if (ioc->ir_firmware)
sh->max_channel = 1;
else
sh->max_channel = 0;
@@ -1009,20 +1420,6 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
ioc->name, hd->ScsiLookup));
- /* Allocate memory for the device structures.
- * A non-Null pointer at an offset
- * indicates a device exists.
- * max_id = 1 + maximum id (hosts.h)
- */
- hd->Targets = kcalloc(sh->max_id * (sh->max_channel + 1),
- sizeof(void *), GFP_ATOMIC);
- if (!hd->Targets) {
- error = -ENOMEM;
- goto out_mptspi_probe;
- }
-
- dprintk((KERN_INFO " vdev @ %p\n", hd->Targets));
-
/* Clear the TM flags
*/
hd->tmPending = 0;