aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/message/fusion')
-rw-r--r--drivers/message/fusion/Kconfig1
-rw-r--r--drivers/message/fusion/lsi/mpi.h10
-rw-r--r--drivers/message/fusion/lsi/mpi_cnfg.h158
-rw-r--r--drivers/message/fusion/lsi/mpi_history.txt77
-rw-r--r--drivers/message/fusion/lsi/mpi_init.h8
-rw-r--r--drivers/message/fusion/lsi/mpi_ioc.h122
-rw-r--r--drivers/message/fusion/lsi/mpi_log_fc.h89
-rw-r--r--drivers/message/fusion/lsi/mpi_log_sas.h162
-rw-r--r--drivers/message/fusion/lsi/mpi_sas.h30
-rw-r--r--drivers/message/fusion/mptbase.c48
-rw-r--r--drivers/message/fusion/mptbase.h34
-rw-r--r--drivers/message/fusion/mptctl.c12
-rw-r--r--drivers/message/fusion/mptfc.c579
-rw-r--r--drivers/message/fusion/mptlan.c14
-rw-r--r--drivers/message/fusion/mptsas.c404
-rw-r--r--drivers/message/fusion/mptscsih.c34
-rw-r--r--drivers/message/fusion/mptspi.c26
17 files changed, 1558 insertions, 250 deletions
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig
index 1883d22..e67cf15 100644
--- a/drivers/message/fusion/Kconfig
+++ b/drivers/message/fusion/Kconfig
@@ -23,6 +23,7 @@ config FUSION_FC
tristate "Fusion MPT ScsiHost drivers for FC"
depends on PCI && SCSI
select FUSION
+ select SCSI_FC_ATTRS
---help---
SCSI HOST support for a Fiber Channel host adapters.
diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h
index b61e3d1..02cdc84 100644
--- a/drivers/message/fusion/lsi/mpi.h
+++ b/drivers/message/fusion/lsi/mpi.h
@@ -6,7 +6,7 @@
* Title: MPI Message independent structures and definitions
* Creation Date: July 27, 2000
*
- * mpi.h Version: 01.05.08
+ * mpi.h Version: 01.05.10
*
* Version History
* ---------------
@@ -74,6 +74,8 @@
* 06-24-05 01.05.08 Added function codes for SCSI IO 32 and
* TargetAssistExtended requests.
* Added EEDP IOCStatus codes.
+ * 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT.
+ * 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target.
* --------------------------------------------------------------------------
*/
@@ -104,7 +106,7 @@
/* Note: The major versions of 0xe0 through 0xff are reserved */
/* versioning for this MPI header set */
-#define MPI_HEADER_VERSION_UNIT (0x0A)
+#define MPI_HEADER_VERSION_UNIT (0x0C)
#define MPI_HEADER_VERSION_DEV (0x00)
#define MPI_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI_HEADER_VERSION_UNIT_SHIFT (8)
@@ -711,6 +713,8 @@ typedef struct _MSG_DEFAULT_REPLY
#define MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D)
#define MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E)
#define MPI_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F)
+#define MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070)
+#define MPI_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071)
/****************************************************************************/
/* Additional FCP target values (obsolete) */
@@ -745,7 +749,7 @@ typedef struct _MSG_DEFAULT_REPLY
#define MPI_IOCSTATUS_LAN_CANCELED (0x0087)
/****************************************************************************/
-/* Serial Attached SCSI values */
+/* Serial Attached SCSI values */
/****************************************************************************/
#define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090)
diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h
index d833989..b1becec 100644
--- a/drivers/message/fusion/lsi/mpi_cnfg.h
+++ b/drivers/message/fusion/lsi/mpi_cnfg.h
@@ -6,7 +6,7 @@
* Title: MPI Config message, structures, and Pages
* Creation Date: July 27, 2000
*
- * mpi_cnfg.h Version: 01.05.09
+ * mpi_cnfg.h Version: 01.05.11
*
* Version History
* ---------------
@@ -249,6 +249,23 @@
* Added OwnerDevHandle and Flags field to SAS PHY Page 0.
* Added IOC GPIO Flags define to SAS Enclosure Page 0.
* Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT.
+ * 08-03-05 01.05.10 Removed ISDataScrubRate and ISResyncRate from
+ * Manufacturing Page 4.
+ * Added MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE bit.
+ * Added NumDevsPerEnclosure field to SAS IO Unit page 2.
+ * Added MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP
+ * define.
+ * Added EnclosureHandle field to SAS Expander page 0.
+ * Removed redundant NumTableEntriesProg field from SAS
+ * Expander Page 1.
+ * 08-30-05 01.05.11 Added DeviceID for FC949E and changed the DeviceID for
+ * SAS1078.
+ * Added more defines for Manufacturing Page 4 Flags field.
+ * Added more defines for IOCSettings and added
+ * ExpanderSpinup field to Bios Page 1.
+ * Added postpone SATA Init bit to SAS IO Unit Page 1
+ * ControlFlags.
+ * Changed LogEntry format for Log Page 0.
* --------------------------------------------------------------------------
*/
@@ -494,7 +511,7 @@ typedef struct _MSG_CONFIG_REPLY
#define MPI_MANUFACTPAGE_DEVICEID_FC929X (0x0626)
#define MPI_MANUFACTPAGE_DEVICEID_FC939X (0x0642)
#define MPI_MANUFACTPAGE_DEVICEID_FC949X (0x0640)
-#define MPI_MANUFACTPAGE_DEVICEID_FC949ES (0x0646)
+#define MPI_MANUFACTPAGE_DEVICEID_FC949E (0x0646)
/* SCSI */
#define MPI_MANUFACTPAGE_DEVID_53C1030 (0x0030)
#define MPI_MANUFACTPAGE_DEVID_53C1030ZC (0x0031)
@@ -510,7 +527,7 @@ typedef struct _MSG_CONFIG_REPLY
#define MPI_MANUFACTPAGE_DEVID_SAS1066E (0x005A)
#define MPI_MANUFACTPAGE_DEVID_SAS1068 (0x0054)
#define MPI_MANUFACTPAGE_DEVID_SAS1068E (0x0058)
-#define MPI_MANUFACTPAGE_DEVID_SAS1078 (0x0060)
+#define MPI_MANUFACTPAGE_DEVID_SAS1078 (0x0062)
typedef struct _CONFIG_PAGE_MANUFACTURING_0
@@ -602,9 +619,7 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4
U32 IMVolumeSettings; /* 50h */
U32 Reserved3; /* 54h */
U32 Reserved4; /* 58h */
- U8 ISDataScrubRate; /* 5Ch */
- U8 ISResyncRate; /* 5Dh */
- U16 Reserved5; /* 5Eh */
+ U32 Reserved5; /* 5Ch */
U8 IMEDataScrubRate; /* 60h */
U8 IMEResyncRate; /* 61h */
U16 Reserved6; /* 62h */
@@ -616,9 +631,14 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4
} CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4,
ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t;
-#define MPI_MANUFACTURING4_PAGEVERSION (0x02)
+#define MPI_MANUFACTURING4_PAGEVERSION (0x03)
/* defines for the Flags field */
+#define MPI_MANPAGE4_IME_DISABLE (0x20)
+#define MPI_MANPAGE4_IM_DISABLE (0x10)
+#define MPI_MANPAGE4_IS_DISABLE (0x08)
+#define MPI_MANPAGE4_IR_MODEPAGE8_DISABLE (0x04)
+#define MPI_MANPAGE4_IM_RESYNC_CACHE_ENABLE (0x02)
#define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA (0x01)
@@ -669,7 +689,7 @@ typedef struct _CONFIG_PAGE_IO_UNIT_1
} CONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1,
IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t;
-#define MPI_IOUNITPAGE1_PAGEVERSION (0x01)
+#define MPI_IOUNITPAGE1_PAGEVERSION (0x02)
/* IO Unit Page 1 Flags defines */
#define MPI_IOUNITPAGE1_MULTI_FUNCTION (0x00000000)
@@ -681,7 +701,7 @@ typedef struct _CONFIG_PAGE_IO_UNIT_1
#define MPI_IOUNITPAGE1_DISABLE_IR (0x00000040)
#define MPI_IOUNITPAGE1_FORCE_32 (0x00000080)
#define MPI_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100)
-
+#define MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE (0x00000200)
typedef struct _MPI_ADAPTER_INFO
{
@@ -968,7 +988,8 @@ typedef struct _CONFIG_PAGE_BIOS_1
U32 Reserved1; /* 0Ch */
U32 DeviceSettings; /* 10h */
U16 NumberOfDevices; /* 14h */
- U16 Reserved2; /* 16h */
+ U8 ExpanderSpinup; /* 16h */
+ U8 Reserved2; /* 17h */
U16 IOTimeoutBlockDevicesNonRM; /* 18h */
U16 IOTimeoutSequential; /* 1Ah */
U16 IOTimeoutOther; /* 1Ch */
@@ -976,7 +997,7 @@ typedef struct _CONFIG_PAGE_BIOS_1
} CONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1,
BIOSPage1_t, MPI_POINTER pBIOSPage1_t;
-#define MPI_BIOSPAGE1_PAGEVERSION (0x02)
+#define MPI_BIOSPAGE1_PAGEVERSION (0x03)
/* values for the BiosOptions field */
#define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE (0x00000400)
@@ -985,8 +1006,15 @@ typedef struct _CONFIG_PAGE_BIOS_1
#define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001)
/* values for the IOCSettings field */
+#define MPI_BIOSPAGE1_IOCSET_MASK_INITIAL_SPINUP_DELAY (0x0F000000)
+#define MPI_BIOSPAGE1_IOCSET_SHIFT_INITIAL_SPINUP_DELAY (24)
+
#define MPI_BIOSPAGE1_IOCSET_MASK_PORT_ENABLE_DELAY (0x00F00000)
#define MPI_BIOSPAGE1_IOCSET_SHIFT_PORT_ENABLE_DELAY (20)
+
+#define MPI_BIOSPAGE1_IOCSET_AUTO_PORT_ENABLE (0x00080000)
+#define MPI_BIOSPAGE1_IOCSET_DIRECT_ATTACH_SPINUP_MODE (0x00040000)
+
#define MPI_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000)
#define MPI_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000)
#define MPI_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000)
@@ -1016,6 +1044,11 @@ typedef struct _CONFIG_PAGE_BIOS_1
#define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002)
#define MPI_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001)
+/* defines for the ExpanderSpinup field */
+#define MPI_BIOSPAGE1_EXPSPINUP_MASK_MAX_TARGET (0xF0)
+#define MPI_BIOSPAGE1_EXPSPINUP_SHIFT_MAX_TARGET (4)
+#define MPI_BIOSPAGE1_EXPSPINUP_MASK_DELAY (0x0F)
+
typedef struct _MPI_BOOT_DEVICE_ADAPTER_ORDER
{
U32 Reserved1; /* 00h */
@@ -1233,13 +1266,13 @@ typedef struct _CONFIG_PAGE_SCSI_PORT_0
#define MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD (8)
#define MPI_SCSIPORTPAGE0_CAP_GET_MIN_SYNC_PERIOD(Cap) \
- ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MIN_SYNC_PERIOD) \
+ ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK) \
>> MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD \
)
#define MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK (0x00FF0000)
#define MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET (16)
#define MPI_SCSIPORTPAGE0_CAP_GET_MAX_SYNC_OFFSET(Cap) \
- ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MAX_SYNC_OFFSET) \
+ ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK) \
>> MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET \
)
#define MPI_SCSIPORTPAGE0_CAP_IDP (0x08000000)
@@ -2370,47 +2403,48 @@ 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 (0x04)
+#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x05)
/* values for SAS IO Unit Page 1 ControlFlags */
-#define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX (0x4000)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX (0x2000)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000)
-#define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH (0x0800)
-
-#define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600)
-#define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9)
-#define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x00)
-#define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x01)
-#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x02)
-
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010)
-#define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH (0x0008)
-#define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004)
-#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002)
-#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001)
+#define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX (0x4000)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX (0x2000)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000)
+#define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH (0x0800)
+
+#define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600)
+#define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9)
+#define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x00)
+#define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x01)
+#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x02)
+
+#define MPI_SAS_IOUNIT1_CONTROL_POSTPONE_SATA_INIT (0x0100)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010)
+#define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH (0x0008)
+#define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004)
+#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002)
+#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001)
/* values for SAS IO Unit Page 1 PortFlags */
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM (0x00)
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM (0x04)
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM (0x00)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM (0x04)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01)
/* values for SAS IO Unit Page 0 PhyFlags */
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE (0x04)
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT (0x02)
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT (0x01)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE (0x04)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT (0x02)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT (0x01)
/* values for SAS IO Unit Page 0 MaxMinLinkRate */
-#define MPI_SAS_IOUNIT1_MAX_RATE_MASK (0xF0)
-#define MPI_SAS_IOUNIT1_MAX_RATE_1_5 (0x80)
-#define MPI_SAS_IOUNIT1_MAX_RATE_3_0 (0x90)
-#define MPI_SAS_IOUNIT1_MIN_RATE_MASK (0x0F)
-#define MPI_SAS_IOUNIT1_MIN_RATE_1_5 (0x08)
-#define MPI_SAS_IOUNIT1_MIN_RATE_3_0 (0x09)
+#define MPI_SAS_IOUNIT1_MAX_RATE_MASK (0xF0)
+#define MPI_SAS_IOUNIT1_MAX_RATE_1_5 (0x80)
+#define MPI_SAS_IOUNIT1_MAX_RATE_3_0 (0x90)
+#define MPI_SAS_IOUNIT1_MIN_RATE_MASK (0x0F)
+#define MPI_SAS_IOUNIT1_MIN_RATE_1_5 (0x08)
+#define MPI_SAS_IOUNIT1_MIN_RATE_3_0 (0x09)
/* see mpi_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
@@ -2418,16 +2452,18 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
{
CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
- U32 Reserved1; /* 08h */
+ U8 NumDevsPerEnclosure; /* 08h */
+ U8 Reserved1; /* 09h */
+ U16 Reserved2; /* 0Ah */
U16 MaxPersistentIDs; /* 0Ch */
U16 NumPersistentIDsUsed; /* 0Eh */
U8 Status; /* 10h */
U8 Flags; /* 11h */
- U16 MaxNumPhysicalMappedIDs;/* 12h */ /* 12h */
+ U16 MaxNumPhysicalMappedIDs;/* 12h */
} 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 (0x04)
+#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x05)
/* values for SAS IO Unit Page 2 Status field */
#define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02)
@@ -2441,6 +2477,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
#define MPI_SAS_IOUNIT2_FLAGS_NO_PHYS_MAP (0x00)
#define MPI_SAS_IOUNIT2_FLAGS_DIRECT_ATTACH_PHYS_MAP (0x01)
#define MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP (0x02)
+#define MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP (0x07)
#define MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT (0x10)
#define MPI_SAS_IOUNIT2_FLAGS_DA_STARTING_SLOT (0x20)
@@ -2473,7 +2510,7 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_0
CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
U8 PhysicalPort; /* 08h */
U8 Reserved1; /* 09h */
- U16 Reserved2; /* 0Ah */
+ U16 EnclosureHandle; /* 0Ah */
U64 SASAddress; /* 0Ch */
U32 DiscoveryStatus; /* 14h */
U16 DevHandle; /* 18h */
@@ -2487,7 +2524,7 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_0
} CONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0,
SasExpanderPage0_t, MPI_POINTER pSasExpanderPage0_t;
-#define MPI_SASEXPANDER0_PAGEVERSION (0x02)
+#define MPI_SASEXPANDER0_PAGEVERSION (0x03)
/* values for SAS Expander Page 0 DiscoveryStatus field */
#define MPI_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001)
@@ -2527,9 +2564,9 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_1
U8 NegotiatedLinkRate; /* 1Fh */
U8 PhyIdentifier; /* 20h */
U8 AttachedPhyIdentifier; /* 21h */
- U8 NumTableEntriesProg; /* 22h */
+ U8 Reserved3; /* 22h */
U8 DiscoveryInfo; /* 23h */
- U32 Reserved3; /* 24h */
+ U32 Reserved4; /* 24h */
} CONFIG_PAGE_SAS_EXPANDER_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_1,
SasExpanderPage1_t, MPI_POINTER pSasExpanderPage1_t;
@@ -2766,16 +2803,15 @@ typedef struct _CONFIG_PAGE_SAS_ENCLOSURE_0
#define MPI_LOG_0_NUM_LOG_ENTRIES (1)
#endif
-#define MPI_LOG_0_LOG_DATA_LENGTH (20)
+#define MPI_LOG_0_LOG_DATA_LENGTH (0x1C)
typedef struct _MPI_LOG_0_ENTRY
{
- U64 WWID; /* 00h */
- U32 TimeStamp; /* 08h */
- U32 Reserved1; /* 0Ch */
- U16 LogSequence; /* 10h */
- U16 LogEntryQualifier; /* 12h */
- U8 LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 14h */
+ U32 TimeStamp; /* 00h */
+ U32 Reserved1; /* 04h */
+ U16 LogSequence; /* 08h */
+ U16 LogEntryQualifier; /* 0Ah */
+ U8 LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 0Ch */
} MPI_LOG_0_ENTRY, MPI_POINTER PTR_MPI_LOG_0_ENTRY,
MpiLog0Entry_t, MPI_POINTER pMpiLog0Entry_t;
@@ -2794,7 +2830,7 @@ typedef struct _CONFIG_PAGE_LOG_0
} CONFIG_PAGE_LOG_0, MPI_POINTER PTR_CONFIG_PAGE_LOG_0,
LogPage0_t, MPI_POINTER pLogPage0_t;
-#define MPI_LOG_0_PAGEVERSION (0x00)
+#define MPI_LOG_0_PAGEVERSION (0x01)
#endif
diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt
index 1a30ef1..4a5f8dd 100644
--- a/drivers/message/fusion/lsi/mpi_history.txt
+++ b/drivers/message/fusion/lsi/mpi_history.txt
@@ -6,25 +6,25 @@
Copyright (c) 2000-2005 LSI Logic Corporation.
---------------------------------------
- Header Set Release Version: 01.05.10
- Header Set Release Date: 03-11-05
+ Header Set Release Version: 01.05.12
+ Header Set Release Date: 08-30-05
---------------------------------------
Filename Current version Prior version
---------- --------------- -------------
- mpi.h 01.05.08 01.05.07
- mpi_ioc.h 01.05.09 01.05.08
- mpi_cnfg.h 01.05.09 01.05.08
- mpi_init.h 01.05.05 01.05.04
- mpi_targ.h 01.05.05 01.05.04
+ mpi.h 01.05.10 01.05.09
+ mpi_ioc.h 01.05.10 01.05.09
+ mpi_cnfg.h 01.05.11 01.05.10
+ mpi_init.h 01.05.06 01.05.06
+ mpi_targ.h 01.05.05 01.05.05
mpi_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.01 01.05.01
- mpi_type.h 01.05.01 01.05.01
- mpi_history.txt 01.05.09 01.05.09
+ mpi_sas.h 01.05.02 01.05.01
+ mpi_type.h 01.05.02 01.05.01
+ mpi_history.txt 01.05.12 01.05.11
* Date Version Description
@@ -91,6 +91,8 @@ mpi.h
* 06-24-05 01.05.08 Added function codes for SCSI IO 32 and
* TargetAssistExtended requests.
* Added EEDP IOCStatus codes.
+ * 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT.
+ * 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target.
* --------------------------------------------------------------------------
mpi_ioc.h
@@ -164,6 +166,10 @@ mpi_ioc.h
* Removed IOCFacts Reply EEDP Capability bit.
* 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits.
* Added Max SATA Targets to SAS Discovery Error event.
+ * 08-30-05 01.05.10 Added 4 new events and their event data structures.
+ * Added new ReasonCode value for SAS Device Status Change
+ * event.
+ * Added new family code for FC949E.
* --------------------------------------------------------------------------
mpi_cnfg.h
@@ -402,6 +408,23 @@ mpi_cnfg.h
* Added OwnerDevHandle and Flags field to SAS PHY Page 0.
* Added IOC GPIO Flags define to SAS Enclosure Page 0.
* Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT.
+ * 08-03-05 01.05.10 Removed ISDataScrubRate and ISResyncRate from
+ * Manufacturing Page 4.
+ * Added MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE bit.
+ * Added NumDevsPerEnclosure field to SAS IO Unit page 2.
+ * Added MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP
+ * define.
+ * Added EnclosureHandle field to SAS Expander page 0.
+ * Removed redundant NumTableEntriesProg field from SAS
+ * Expander Page 1.
+ * 08-30-05 01.05.11 Added DeviceID for FC949E and changed the DeviceID for
+ * SAS1078.
+ * Added more defines for Manufacturing Page 4 Flags field.
+ * Added more defines for IOCSettings and added
+ * ExpanderSpinup field to Bios Page 1.
+ * Added postpone SATA Init bit to SAS IO Unit Page 1
+ * ControlFlags.
+ * Changed LogEntry format for Log Page 0.
* --------------------------------------------------------------------------
mpi_init.h
@@ -442,6 +465,8 @@ mpi_init.h
* addressing.
* 06-24-05 01.05.05 Added SCSI IO 32 structures and defines.
* Added four new defines for SEP SlotStatus.
+ * 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
+ * unique in the first 32 characters.
* --------------------------------------------------------------------------
mpi_targ.h
@@ -582,6 +607,9 @@ mpi_inb.h
mpi_sas.h
* 08-19-04 01.05.01 Original release.
+ * 08-30-05 01.05.02 Added DeviceInfo bit for SEP.
+ * Added PrimFlags and Primitive field to SAS IO Unit
+ * Control request, and added a new operation code.
* --------------------------------------------------------------------------
mpi_type.h
@@ -592,24 +620,25 @@ mpi_type.h
* 08-08-01 01.02.01 Original release for v1.2 work.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Original release for MPI v1.5.
+ * 08-30-05 01.05.02 Added PowerPC option to #ifdef's.
* --------------------------------------------------------------------------
mpi_history.txt Parts list history
-Filename 01.05.10 01.05.09
----------- -------- --------
-mpi.h 01.05.08 01.05.07
-mpi_ioc.h 01.05.09 01.05.08
-mpi_cnfg.h 01.05.09 01.05.08
-mpi_init.h 01.05.05 01.05.04
-mpi_targ.h 01.05.05 01.05.04
-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.01 01.05.01
-mpi_type.h 01.05.01 01.05.01
+Filename 01.05.12 01.05.11 01.05.10 01.05.09
+---------- -------- -------- -------- --------
+mpi.h 01.05.10 01.05.09 01.05.08 01.05.07
+mpi_ioc.h 01.05.10 01.05.09 01.05.09 01.05.08
+mpi_cnfg.h 01.05.11 01.05.10 01.05.09 01.05.08
+mpi_init.h 01.05.06 01.05.06 01.05.05 01.05.04
+mpi_targ.h 01.05.05 01.05.05 01.05.05 01.05.04
+mpi_fc.h 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_lan.h 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_raid.h 01.05.02 01.05.02 01.05.02 01.05.02
+mpi_tool.h 01.05.03 01.05.03 01.05.03 01.05.03
+mpi_inb.h 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_sas.h 01.05.02 01.05.01 01.05.01 01.05.01
+mpi_type.h 01.05.02 01.05.01 01.05.01 01.05.01
Filename 01.05.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 d5af75a..68941f4 100644
--- a/drivers/message/fusion/lsi/mpi_init.h
+++ b/drivers/message/fusion/lsi/mpi_init.h
@@ -6,7 +6,7 @@
* Title: MPI initiator mode messages and structures
* Creation Date: June 8, 2000
*
- * mpi_init.h Version: 01.05.05
+ * mpi_init.h Version: 01.05.06
*
* Version History
* ---------------
@@ -50,6 +50,8 @@
* addressing.
* 06-24-05 01.05.05 Added SCSI IO 32 structures and defines.
* Added four new defines for SEP SlotStatus.
+ * 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
+ * unique in the first 32 characters.
* --------------------------------------------------------------------------
*/
@@ -290,8 +292,8 @@ typedef struct _MSG_SCSI_IO32_REQUEST
/* SCSI IO 32 MsgFlags bits */
#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH (0x01)
-#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_32 (0x00)
-#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_64 (0x01)
+#define MPI_SCSIIO32_MSGFLGS_32_SENSE_WIDTH (0x00)
+#define MPI_SCSIIO32_MSGFLGS_64_SENSE_WIDTH (0x01)
#define MPI_SCSIIO32_MSGFLGS_SENSE_LOCATION (0x02)
#define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_HOST (0x00)
diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h
index 93b70e2..2c5f43f 100644
--- a/drivers/message/fusion/lsi/mpi_ioc.h
+++ b/drivers/message/fusion/lsi/mpi_ioc.h
@@ -6,7 +6,7 @@
* Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
* Creation Date: August 11, 2000
*
- * mpi_ioc.h Version: 01.05.09
+ * mpi_ioc.h Version: 01.05.10
*
* Version History
* ---------------
@@ -83,6 +83,10 @@
* Removed IOCFacts Reply EEDP Capability bit.
* 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits.
* Added Max SATA Targets to SAS Discovery Error event.
+ * 08-30-05 01.05.10 Added 4 new events and their event data structures.
+ * Added new ReasonCode value for SAS Device Status Change
+ * event.
+ * Added new family code for FC949E.
* --------------------------------------------------------------------------
*/
@@ -464,6 +468,10 @@ typedef struct _MSG_EVENT_ACK_REPLY
#define MPI_EVENT_PERSISTENT_TABLE_FULL (0x00000011)
#define MPI_EVENT_SAS_PHY_LINK_STATUS (0x00000012)
#define MPI_EVENT_SAS_DISCOVERY_ERROR (0x00000013)
+#define MPI_EVENT_IR_RESYNC_UPDATE (0x00000014)
+#define MPI_EVENT_IR2 (0x00000015)
+#define MPI_EVENT_SAS_DISCOVERY (0x00000016)
+#define MPI_EVENT_LOG_ENTRY_ADDED (0x00000021)
/* AckRequired field values */
@@ -480,6 +488,29 @@ typedef struct _EVENT_DATA_EVENT_CHANGE
} EVENT_DATA_EVENT_CHANGE, MPI_POINTER PTR_EVENT_DATA_EVENT_CHANGE,
EventDataEventChange_t, MPI_POINTER pEventDataEventChange_t;
+/* LogEntryAdded Event data */
+
+/* this structure matches MPI_LOG_0_ENTRY in mpi_cnfg.h */
+#define MPI_EVENT_DATA_LOG_ENTRY_DATA_LENGTH (0x1C)
+typedef struct _EVENT_DATA_LOG_ENTRY
+{
+ U32 TimeStamp; /* 00h */
+ U32 Reserved1; /* 04h */
+ U16 LogSequence; /* 08h */
+ U16 LogEntryQualifier; /* 0Ah */
+ U8 LogData[MPI_EVENT_DATA_LOG_ENTRY_DATA_LENGTH]; /* 0Ch */
+} EVENT_DATA_LOG_ENTRY, MPI_POINTER PTR_EVENT_DATA_LOG_ENTRY,
+ MpiEventDataLogEntry_t, MPI_POINTER pMpiEventDataLogEntry_t;
+
+typedef struct _EVENT_DATA_LOG_ENTRY_ADDED
+{
+ U16 LogSequence; /* 00h */
+ U16 Reserved1; /* 02h */
+ U32 Reserved2; /* 04h */
+ EVENT_DATA_LOG_ENTRY LogEntry; /* 08h */
+} EVENT_DATA_LOG_ENTRY_ADDED, MPI_POINTER PTR_EVENT_DATA_LOG_ENTRY_ADDED,
+ MpiEventDataLogEntryAdded_t, MPI_POINTER pMpiEventDataLogEntryAdded_t;
+
/* SCSI Event data for Port, Bus and Device forms */
typedef struct _EVENT_DATA_SCSI
@@ -538,6 +569,7 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
#define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05)
#define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED (0x06)
#define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07)
+#define MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08)
/* SCSI Event data for Queue Full event */
@@ -579,6 +611,79 @@ typedef struct _EVENT_DATA_RAID
#define MPI_EVENT_RAID_RC_SMART_DATA (0x0A)
#define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED (0x0B)
+
+/* MPI Integrated RAID Resync Update Event data */
+
+typedef struct _MPI_EVENT_DATA_IR_RESYNC_UPDATE
+{
+ U8 VolumeID; /* 00h */
+ U8 VolumeBus; /* 01h */
+ U8 ResyncComplete; /* 02h */
+ U8 Reserved1; /* 03h */
+ U32 Reserved2; /* 04h */
+} MPI_EVENT_DATA_IR_RESYNC_UPDATE,
+ MPI_POINTER PTR_MPI_EVENT_DATA_IR_RESYNC_UPDATE,
+ MpiEventDataIrResyncUpdate_t, MPI_POINTER pMpiEventDataIrResyncUpdate_t;
+
+/* MPI IR2 Event data */
+
+/* MPI_LD_STATE or MPI_PD_STATE */
+typedef struct _IR2_STATE_CHANGED
+{
+ U16 PreviousState; /* 00h */
+ U16 NewState; /* 02h */
+} IR2_STATE_CHANGED, MPI_POINTER PTR_IR2_STATE_CHANGED;
+
+typedef struct _IR2_PD_INFO
+{
+ U16 DeviceHandle; /* 00h */
+ U8 TruncEnclosureHandle; /* 02h */
+ U8 TruncatedSlot; /* 03h */
+} IR2_PD_INFO, MPI_POINTER PTR_IR2_PD_INFO;
+
+typedef union _MPI_IR2_RC_EVENT_DATA
+{
+ IR2_STATE_CHANGED StateChanged;
+ U32 Lba;
+ IR2_PD_INFO PdInfo;
+} MPI_IR2_RC_EVENT_DATA, MPI_POINTER PTR_MPI_IR2_RC_EVENT_DATA;
+
+typedef struct _MPI_EVENT_DATA_IR2
+{
+ U8 TargetID; /* 00h */
+ U8 Bus; /* 01h */
+ U8 ReasonCode; /* 02h */
+ U8 PhysDiskNum; /* 03h */
+ MPI_IR2_RC_EVENT_DATA IR2EventData; /* 04h */
+} MPI_EVENT_DATA_IR2, MPI_POINTER PTR_MPI_EVENT_DATA_IR2,
+ MpiEventDataIR2_t, MPI_POINTER pMpiEventDataIR2_t;
+
+/* MPI IR2 Event data ReasonCode values */
+#define MPI_EVENT_IR2_RC_LD_STATE_CHANGED (0x01)
+#define MPI_EVENT_IR2_RC_PD_STATE_CHANGED (0x02)
+#define MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL (0x03)
+#define MPI_EVENT_IR2_RC_PD_INSERTED (0x04)
+#define MPI_EVENT_IR2_RC_PD_REMOVED (0x05)
+#define MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED (0x06)
+#define MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR (0x07)
+
+/* defines for logical disk states */
+#define MPI_LD_STATE_OPTIMAL (0x00)
+#define MPI_LD_STATE_DEGRADED (0x01)
+#define MPI_LD_STATE_FAILED (0x02)
+#define MPI_LD_STATE_MISSING (0x03)
+#define MPI_LD_STATE_OFFLINE (0x04)
+
+/* defines for physical disk states */
+#define MPI_PD_STATE_ONLINE (0x00)
+#define MPI_PD_STATE_MISSING (0x01)
+#define MPI_PD_STATE_NOT_COMPATIBLE (0x02)
+#define MPI_PD_STATE_FAILED (0x03)
+#define MPI_PD_STATE_INITIALIZING (0x04)
+#define MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST (0x05)
+#define MPI_PD_STATE_FAILED_AT_HOST_REQUEST (0x06)
+#define MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON (0xFF)
+
/* MPI Link Status Change Event data */
typedef struct _EVENT_DATA_LINK_STATUS
@@ -660,6 +765,20 @@ typedef struct _EVENT_DATA_SAS_PHY_LINK_STATUS
#define MPI_EVENT_SAS_PLS_LR_RATE_1_5 (0x08)
#define MPI_EVENT_SAS_PLS_LR_RATE_3_0 (0x09)
+/* SAS Discovery Event data */
+
+typedef struct _EVENT_DATA_SAS_DISCOVERY
+{
+ U32 DiscoveryStatus; /* 00h */
+ U32 Reserved1; /* 04h */
+} EVENT_DATA_SAS_DISCOVERY, MPI_POINTER PTR_EVENT_DATA_SAS_DISCOVERY,
+ EventDataSasDiscovery_t, MPI_POINTER pEventDataSasDiscovery_t;
+
+#define MPI_EVENT_SAS_DSCVRY_COMPLETE (0x00000000)
+#define MPI_EVENT_SAS_DSCVRY_IN_PROGRESS (0x00000001)
+#define MPI_EVENT_SAS_DSCVRY_PHY_BITS_MASK (0xFFFF0000)
+#define MPI_EVENT_SAS_DSCVRY_PHY_BITS_SHIFT (16)
+
/* SAS Discovery Errror Event data */
typedef struct _EVENT_DATA_DISCOVERY_ERROR
@@ -869,6 +988,7 @@ typedef struct _MPI_FW_HEADER
#define MPI_FW_HEADER_PID_FAMILY_919XL_FC (0x0003) /* 919XL and 929XL */
#define MPI_FW_HEADER_PID_FAMILY_939X_FC (0x0004) /* 939X and 949X */
#define MPI_FW_HEADER_PID_FAMILY_959_FC (0x0005)
+#define MPI_FW_HEADER_PID_FAMILY_949E_FC (0x0006)
/* SAS */
#define MPI_FW_HEADER_PID_FAMILY_1064_SAS (0x0001)
#define MPI_FW_HEADER_PID_FAMILY_1068_SAS (0x0002)
diff --git a/drivers/message/fusion/lsi/mpi_log_fc.h b/drivers/message/fusion/lsi/mpi_log_fc.h
new file mode 100644
index 0000000..dc98d46
--- /dev/null
+++ b/drivers/message/fusion/lsi/mpi_log_fc.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2000-2001 LSI Logic Corporation. All rights reserved.
+ *
+ * NAME: fc_log.h
+ * SUMMARY: MPI IocLogInfo definitions for the SYMFC9xx chips
+ * DESCRIPTION: Contains the enumerated list of values that may be returned
+ * in the IOCLogInfo field of a MPI Default Reply Message.
+ *
+ * CREATION DATE: 6/02/2000
+ * ID: $Id: fc_log.h,v 4.6 2001/07/26 14:41:33 sschremm Exp $
+ */
+
+
+/*
+ * MpiIocLogInfo_t enum
+ *
+ * These 32 bit values are used in the IOCLogInfo field of the MPI reply
+ * messages.
+ * The value is 0xabcccccc where
+ * a = The type of log info as per the MPI spec. Since these codes are
+ * all for Fibre Channel this value will always be 2.
+ * b = Specifies a subclass of the firmware where
+ * 0 = FCP Initiator
+ * 1 = FCP Target
+ * 2 = LAN
+ * 3 = MPI Message Layer
+ * 4 = FC Link
+ * 5 = Context Manager
+ * 6 = Invalid Field Offset
+ * 7 = State Change Info
+ * all others are reserved for future use
+ * c = A specific value within the subclass.
+ *
+ * NOTE: Any new values should be added to the end of each subclass so that the
+ * codes remain consistent across firmware releases.
+ */
+typedef enum _MpiIocLogInfoFc
+{
+ MPI_IOCLOGINFO_FC_INIT_BASE = 0x20000000,
+ MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME = 0x20000001, /* received an out of order frame - unsupported */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primative */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME = 0x20000003, /* Bad Rx Frame, bad end of frame primative */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN = 0x20000004, /* Bad Rx Frame, overrun */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER = 0x20000005, /* Other errors caught by IOC which require retries */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD = 0x20000006, /* Main processor could not initialize sub-processor */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OVERRUN = 0x20000007, /* Scatter Gather overrun */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_RX_BAD_STATUS = 0x20000008, /* Receiver detected context mismatch via invalid header */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_RX_UNEXPECTED_FRAME= 0x20000009, /* CtxMgr detected unsupported frame type */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_LINK_FAILURE = 0x2000000A, /* Link failure occurred */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_TX_TIMEOUT = 0x2000000B, /* Transmitter timeout error */
+
+ MPI_IOCLOGINFO_FC_TARGET_BASE = 0x21000000,
+ MPI_IOCLOGINFO_FC_TARGET_NO_PDISC = 0x21000001, /* not sent because we are waiting for a PDISC from the initiator */
+ MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN = 0x21000002, /* not sent because we are not logged in to the remote node */
+ MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP = 0x21000003, /* Data Out, Auto Response, not sent due to a LIP */
+ MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP = 0x21000004, /* Data In, Auto Response, not sent due to a LIP */
+ MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA = 0x21000005, /* Data In, Auto Response, missing data frames */
+ MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP = 0x21000006, /* Data Out, No Response, not sent due to a LIP */
+ MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP = 0x21000007, /* Auto-response after a write not sent due to a LIP */
+ MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP = 0x21000008, /* Data In, No Response, not completed due to a LIP */
+ MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA = 0x21000009, /* Data In, No Response, missing data frames */
+ MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP = 0x2100000a, /* Manual Response not sent due to a LIP */
+ MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3 = 0x2100000b, /* not sent because remote node does not support Class 3 */
+ MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID = 0x2100000c, /* not sent because login to remote node not validated */
+ MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND = 0x2100000e, /* cleared from the outbound queue after a logout */
+ MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN = 0x2100000f, /* cleared waiting for data after a logout */
+
+ MPI_IOCLOGINFO_FC_LAN_BASE = 0x22000000,
+ MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING = 0x22000001, /* Transaction Context Sgl Missing */
+ MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE = 0x22000002, /* Transaction Context found before an EOB */
+ MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET = 0x22000003, /* Transaction Context value has reserved bits set */
+ MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG = 0x22000004, /* Invalid SGL Flags */
+
+ MPI_IOCLOGINFO_FC_MSG_BASE = 0x23000000,
+
+ MPI_IOCLOGINFO_FC_LINK_BASE = 0x24000000,
+ MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT = 0x24000001, /* Loop initialization timed out */
+ MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED = 0x24000002, /* Another system controller already initialized the loop */
+ MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED = 0x24000003, /* Not synchronized to signal or still negotiating (possible cable problem) */
+ MPI_IOCLOGINFO_FC_LINK_CRC_ERROR = 0x24000004, /* CRC check detected error on received frame */
+
+ MPI_IOCLOGINFO_FC_CTX_BASE = 0x25000000,
+
+ MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET = 0x26000000, /* The lower 24 bits give the byte offset of the field in the request message that is invalid */
+ MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET = 0x26ffffff,
+
+ MPI_IOCLOGINFO_FC_STATE_CHANGE = 0x27000000 /* The lower 24 bits give additional information concerning state change */
+
+} MpiIocLogInfoFc_t;
diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h
new file mode 100644
index 0000000..9259d1a
--- /dev/null
+++ b/drivers/message/fusion/lsi/mpi_log_sas.h
@@ -0,0 +1,162 @@
+
+/***************************************************************************
+ * *
+ * Copyright 2003 LSI Logic Corporation. All rights reserved. *
+ * *
+ * This file is confidential and a trade secret of LSI Logic. The *
+ * receipt of or possession of this file does not convey any rights to *
+ * reproduce or disclose its contents or to manufacture, use, or sell *
+ * anything it may describe, in whole, or in part, without the specific *
+ * written consent of LSI Logic Corporation. *
+ * *
+ ***************************************************************************
+ *
+ * Name: iopiIocLogInfo.h
+ * Title: SAS Firmware IOP Interface IOC Log Info Definitions
+ * Programmer: Guy Kendall
+ * Creation Date: September 24, 2003
+ *
+ * Version History
+ * ---------------
+ *
+ * Last Updated
+ * -------------
+ * Version %version: 22 %
+ * Date Updated %date_modified: %
+ * Programmer %created_by: nperucca %
+ *
+ * Date Who Description
+ * -------- --- -------------------------------------------------------
+ * 09/24/03 GWK Initial version
+ *
+ *
+ * Description
+ * ------------
+ * This include file contains SAS firmware interface IOC Log Info codes
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef IOPI_IOCLOGINFO_H_INCLUDED
+#define IOPI_IOCLOGINFO_H_INCLUDED
+
+
+/****************************************************************************/
+/* IOC LOGINFO defines, 0x00000000 - 0x0FFFFFFF */
+/* Format: */
+/* Bits 31-28: MPI_IOCLOGINFO_TYPE_SAS (3) */
+/* Bits 27-24: IOC_LOGINFO_ORIGINATOR: 0=IOP, 1=PL, 2=IR */
+/* Bits 23-16: LOGINFO_CODE */
+/* Bits 15-0: LOGINFO_CODE Specific */
+/****************************************************************************/
+
+/****************************************************************************/
+/* IOC_LOGINFO_ORIGINATOR defines */
+/****************************************************************************/
+#define IOC_LOGINFO_ORIGINATOR_IOP (0x00000000)
+#define IOC_LOGINFO_ORIGINATOR_PL (0x01000000)
+#define IOC_LOGINFO_ORIGINATOR_IR (0x02000000)
+
+/****************************************************************************/
+/* LOGINFO_CODE defines */
+/****************************************************************************/
+#define IOC_LOGINFO_CODE_MASK (0x00FF0000)
+#define IOC_LOGINFO_CODE_SHIFT (16)
+
+/****************************************************************************/
+/* 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_TASK_TERMINATED (0x00050000)
+
+
+/****************************************************************************/
+/* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL */
+/****************************************************************************/
+#define PL_LOGINFO_CODE_OPEN_FAILURE (0x00010000)
+#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_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)
+#define PL_LOGINFO_CODE_ABORT (0x00120000)
+#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000)
+#define PL_LOGINFO_CODE_IO_EXECUTED (0x00140000)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE (0x00000100)
+#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_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 (0x00200001) /* Error occured on SMP Read */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200002) /* Error occured on SMP Write */
+#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200004) /* Encl Mgmt services not available for this WWID */
+#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200005) /* Address Mode not suppored */
+#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200006) /* Invalid Slot Number in SEP Msg */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200007) /* SGPIO not present/enabled */
+
+#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_BAD_STATUS_HDR_CHKSUM (0x00200104) /* SEP stopped or sent bad chksum in Hdr */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200105) /* SEP returned unknown scsi status */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200106) /* SEP returned unknown scsi status */
+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x00200107) /* SEP returned bad chksum after STOP */
+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x00200108) /* SEP returned bad chksum after STOP while gettin data*/
+
+
+/****************************************************************************/
+/* IR LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IR */
+/****************************************************************************/
+#define IR_LOGINFO_CODE_UNUSED1 (0x00010000)
+#define IR_LOGINFO_CODE_UNUSED2 (0x00020000)
+
+/****************************************************************************/
+/* Defines for convienence */
+/****************************************************************************/
+#define IOC_LOGINFO_PREFIX_IOP ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IOP)
+#define IOC_LOGINFO_PREFIX_PL ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_PL)
+#define IOC_LOGINFO_PREFIX_IR ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IR)
+
+#endif /* end of file */
+
diff --git a/drivers/message/fusion/lsi/mpi_sas.h b/drivers/message/fusion/lsi/mpi_sas.h
index 230fa69..7051486 100644
--- a/drivers/message/fusion/lsi/mpi_sas.h
+++ b/drivers/message/fusion/lsi/mpi_sas.h
@@ -6,7 +6,7 @@
* Title: MPI Serial Attached SCSI structures and definitions
* Creation Date: August 19, 2004
*
- * mpi_sas.h Version: 01.05.01
+ * mpi_sas.h Version: 01.05.02
*
* Version History
* ---------------
@@ -14,6 +14,9 @@
* Date Version Description
* -------- -------- ------------------------------------------------------
* 08-19-04 01.05.01 Original release.
+ * 08-30-05 01.05.02 Added DeviceInfo bit for SEP.
+ * Added PrimFlags and Primitive field to SAS IO Unit
+ * Control request, and added a new operation code.
* --------------------------------------------------------------------------
*/
@@ -51,6 +54,7 @@
* Values for the SAS DeviceInfo field used in SAS Device Status Change Event
* data and SAS IO Unit Configuration pages.
*/
+#define MPI_SAS_DEVICE_INFO_SEP (0x00004000)
#define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000)
#define MPI_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000)
#define MPI_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800)
@@ -212,20 +216,26 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST
U8 TargetID; /* 0Ch */
U8 Bus; /* 0Dh */
U8 PhyNum; /* 0Eh */
- U8 Reserved4; /* 0Fh */
- U32 Reserved5; /* 10h */
+ U8 PrimFlags; /* 0Fh */
+ U32 Primitive; /* 10h */
U64 SASAddress; /* 14h */
- U32 Reserved6; /* 1Ch */
+ U32 Reserved4; /* 1Ch */
} MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST,
SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t;
/* values for the Operation field */
-#define MPI_SAS_OP_CLEAR_NOT_PRESENT (0x01)
-#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT (0x02)
-#define MPI_SAS_OP_PHY_LINK_RESET (0x06)
-#define MPI_SAS_OP_PHY_HARD_RESET (0x07)
-#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08)
-#define MPI_SAS_OP_MAP_CURRENT (0x09)
+#define MPI_SAS_OP_CLEAR_NOT_PRESENT (0x01)
+#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT (0x02)
+#define MPI_SAS_OP_PHY_LINK_RESET (0x06)
+#define MPI_SAS_OP_PHY_HARD_RESET (0x07)
+#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08)
+#define MPI_SAS_OP_MAP_CURRENT (0x09)
+#define MPI_SAS_OP_SEND_PRIMITIVE (0x0A)
+
+/* values for the PrimFlags field */
+#define MPI_SAS_PRIMFLAGS_SINGLE (0x08)
+#define MPI_SAS_PRIMFLAGS_TRIPLE (0x02)
+#define MPI_SAS_PRIMFLAGS_REDUNDANT (0x01)
/* SAS IO Unit Control Reply */
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 5378360..d890b2b 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -148,7 +148,6 @@ static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
static int GetLanConfigPages(MPT_ADAPTER *ioc);
-static int GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
static int GetIoUnitPage2(MPT_ADAPTER *ioc);
int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
@@ -1232,12 +1231,11 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
dprintk((KERN_INFO MYNAM
": Not using 64 bit consistent mask\n"));
- ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
+ ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
if (ioc == NULL) {
printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
return -ENOMEM;
}
- memset(ioc, 0, sizeof(MPT_ADAPTER));
ioc->alloc_total = sizeof(MPT_ADAPTER);
ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
@@ -1245,6 +1243,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->pcidev = pdev;
ioc->diagPending = 0;
spin_lock_init(&ioc->diagLock);
+ spin_lock_init(&ioc->fc_rescan_work_lock);
+ spin_lock_init(&ioc->fc_rport_lock);
spin_lock_init(&ioc->initializing_hba_lock);
/* Initialize the event logging.
@@ -1268,6 +1268,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
*/
INIT_LIST_HEAD(&ioc->configQ);
+ /* Initialize the fc rport list head.
+ */
+ INIT_LIST_HEAD(&ioc->fc_rports);
+
/* Find lookup slot. */
INIT_LIST_HEAD(&ioc->list);
ioc->id = mpt_ids++;
@@ -1374,6 +1378,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->bus_type = FC;
ioc->errata_flag_1064 = 1;
}
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
+ ioc->prod_name = "LSIFC949E";
+ ioc->bus_type = FC;
+ }
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
ioc->prod_name = "LSI53C1030";
ioc->bus_type = SPI;
@@ -1622,7 +1630,7 @@ mpt_resume(struct pci_dev *pdev)
pci_enable_device(pdev);
/* enable interrupts */
- CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
+ CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
ioc->active = 1;
/* F/W not running */
@@ -1715,7 +1723,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
/* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
ioc->alt_ioc->name));
- CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
+ CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
ioc->alt_ioc->active = 1;
}
@@ -1831,7 +1839,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
if (ret == 0) {
/* Enable! (reply interrupt) */
- CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
+ CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
ioc->active = 1;
}
@@ -1839,7 +1847,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
/* (re)Enable alt-IOC! (reply interrupt) */
dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
ioc->alt_ioc->name));
- CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
+ CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
ioc->alt_ioc->active = 1;
}
@@ -1880,7 +1888,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
* (FCPortPage0_t stuff)
*/
for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
- (void) GetFcPortPage0(ioc, ii);
+ (void) mptbase_GetFcPortPage0(ioc, ii);
}
if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
@@ -4199,7 +4207,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * GetFcPortPage0 - Fetch FCPort config Page0.
+ * mptbase_GetFcPortPage0 - Fetch FCPort config Page0.
* @ioc: Pointer to MPT_ADAPTER structure
* @portnum: IOC Port number
*
@@ -4209,8 +4217,8 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
* -EAGAIN if no msg frames currently available
* -EFAULT for non-successful reply or no reply (timeout)
*/
-static int
-GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
+int
+mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
{
ConfigPageHeader_t hdr;
CONFIGPARMS cfg;
@@ -4220,6 +4228,8 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
int data_sz;
int copy_sz;
int rc;
+ int count = 400;
+
/* Get FCPort Page 0 header */
hdr.PageVersion = 0;
@@ -4243,6 +4253,8 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
rc = -ENOMEM;
ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
if (ppage0_alloc) {
+
+ try_again:
memset((u8 *)ppage0_alloc, 0, data_sz);
cfg.physAddr = page0_dma;
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
@@ -4274,6 +4286,19 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
+ /*
+ * if still doing discovery,
+ * hang loose a while until finished
+ */
+ if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
+ if (count-- > 0) {
+ msleep_interruptible(100);
+ goto try_again;
+ }
+ printk(MYIOC_s_INFO_FMT "Firmware discovery not"
+ " complete.\n",
+ ioc->name);
+ }
}
pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
@@ -6358,6 +6383,7 @@ EXPORT_SYMBOL(mpt_alloc_fw_memory);
EXPORT_SYMBOL(mpt_free_fw_memory);
EXPORT_SYMBOL(mptbase_sas_persist_operation);
EXPORT_SYMBOL(mpt_alt_ioc_wait);
+EXPORT_SYMBOL(mptbase_GetFcPortPage0);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 6c48d1f..47053ac 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -76,8 +76,8 @@
#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
#endif
-#define MPT_LINUX_VERSION_COMMON "3.03.05"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.05"
+#define MPT_LINUX_VERSION_COMMON "3.03.06"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.06"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
@@ -413,7 +413,7 @@ typedef struct _MPT_IOCTL {
u8 status; /* current command status */
u8 reset; /* 1 if bus reset allowed */
u8 target; /* target for reset */
- struct semaphore sem_ioc;
+ struct mutex ioctl_mutex;
} MPT_IOCTL;
#define MPT_SAS_MGMT_STATUS_RF_VALID 0x02 /* The Reply Frame is VALID */
@@ -421,7 +421,7 @@ typedef struct _MPT_IOCTL {
#define MPT_SAS_MGMT_STATUS_TM_FAILED 0x40 /* User TM request failed */
typedef struct _MPT_SAS_MGMT {
- struct semaphore mutex;
+ struct mutex mutex;
struct completion done;
u8 reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */
u8 status; /* current command status */
@@ -499,6 +499,22 @@ typedef struct _RaidCfgData {
int isRaid; /* bit field, 1 if RAID */
}RaidCfgData;
+#define MPT_RPORT_INFO_FLAGS_REGISTERED 0x01 /* rport registered */
+#define MPT_RPORT_INFO_FLAGS_MISSING 0x02 /* missing from DevPage0 scan */
+#define MPT_RPORT_INFO_FLAGS_MAPPED_VDEV 0x04 /* target mapped in vdev */
+
+/*
+ * data allocated for each fc rport device
+ */
+struct mptfc_rport_info
+{
+ struct list_head list;
+ struct fc_rport *rport;
+ VirtDevice *vdev;
+ FCDevicePage0_t pg0;
+ u8 flags;
+};
+
/*
* Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
*/
@@ -612,7 +628,16 @@ typedef struct _MPT_ADAPTER
struct list_head list;
struct net_device *netdev;
struct list_head sas_topology;
+ struct mutex sas_topology_mutex;
MPT_SAS_MGMT sas_mgmt;
+ int num_ports;
+
+ struct list_head fc_rports;
+ spinlock_t fc_rport_lock; /* list and ri flags */
+ spinlock_t fc_rescan_work_lock;
+ int fc_rescan_work_count;
+ struct work_struct fc_rescan_work;
+
} MPT_ADAPTER;
/*
@@ -999,6 +1024,7 @@ extern void mpt_free_fw_memory(MPT_ADAPTER *ioc);
extern int mpt_findImVolumes(MPT_ADAPTER *ioc);
extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
+extern int mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
extern int mpt_alt_ioc_wait(MPT_ADAPTER *ioc);
/*
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 7c34024..bdf7099 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -177,10 +177,10 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock));
if (nonblock) {
- if (down_trylock(&ioc->ioctl->sem_ioc))
+ if (!mutex_trylock(&ioc->ioctl->ioctl_mutex))
rc = -EAGAIN;
} else {
- if (down_interruptible(&ioc->ioctl->sem_ioc))
+ if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex))
rc = -ERESTARTSYS;
}
dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc));
@@ -557,7 +557,7 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
else
ret = -EINVAL;
- up(&iocp->ioctl->sem_ioc);
+ mutex_unlock(&iocp->ioctl->ioctl_mutex);
return ret;
}
@@ -2619,7 +2619,7 @@ compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
- up(&iocp->ioctl->sem_ioc);
+ mutex_unlock(&iocp->ioctl->ioctl_mutex);
return ret;
}
@@ -2673,7 +2673,7 @@ compat_mpt_command(struct file *filp, unsigned int cmd,
*/
ret = mptctl_do_mpt_command (karg, &uarg->MF);
- up(&iocp->ioctl->sem_ioc);
+ mutex_unlock(&iocp->ioctl->ioctl_mutex);
return ret;
}
@@ -2743,7 +2743,7 @@ mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
memset(mem, 0, sz);
ioc->ioctl = (MPT_IOCTL *) mem;
ioc->ioctl->ioc = ioc;
- sema_init(&ioc->ioctl->sem_ioc, 1);
+ mutex_init(&ioc->ioctl->ioctl_mutex);
return 0;
out_fail:
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index ba61e18..b102c76 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -55,12 +55,14 @@
#include <linux/reboot.h> /* notifier code */
#include <linux/sched.h>
#include <linux/workqueue.h>
+#include <linux/sort.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport_fc.h>
#include "mptbase.h"
#include "mptscsih.h"
@@ -79,19 +81,34 @@ static int mpt_pq_filter = 0;
module_param(mpt_pq_filter, int, 0);
MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
+#define MPTFC_DEV_LOSS_TMO (60)
+static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; /* reasonable default */
+module_param(mptfc_dev_loss_tmo, int, 0);
+MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
+ " transport to wait for an rport to "
+ " return following a device loss event."
+ " Default=60.");
+
static int mptfcDoneCtx = -1;
static int mptfcTaskCtx = -1;
static int mptfcInternalCtx = -1; /* Used only for internal commands */
+int mptfc_slave_alloc(struct scsi_device *device);
+static int mptfc_qcmd(struct scsi_cmnd *SCpnt,
+ void (*done)(struct scsi_cmnd *));
+
+static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
+static void __devexit mptfc_remove(struct pci_dev *pdev);
+
static struct scsi_host_template mptfc_driver_template = {
.module = THIS_MODULE,
.proc_name = "mptfc",
.proc_info = mptscsih_proc_info,
.name = "MPT FC Host",
.info = mptscsih_info,
- .queuecommand = mptscsih_qcmd,
+ .queuecommand = mptfc_qcmd,
.target_alloc = mptscsih_target_alloc,
- .slave_alloc = mptscsih_slave_alloc,
+ .slave_alloc = mptfc_slave_alloc,
.slave_configure = mptscsih_slave_configure,
.target_destroy = mptscsih_target_destroy,
.slave_destroy = mptscsih_slave_destroy,
@@ -128,19 +145,478 @@ static struct pci_device_id mptfc_pci_table[] = {
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,
PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949ES,
+ PCI_ANY_ID, PCI_ANY_ID },
{0} /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static struct scsi_transport_template *mptfc_transport_template = NULL;
+
+struct fc_function_template mptfc_transport_functions = {
+ .dd_fcrport_size = 8,
+ .show_host_node_name = 1,
+ .show_host_port_name = 1,
+ .show_host_supported_classes = 1,
+ .show_host_port_id = 1,
+ .show_rport_supported_classes = 1,
+ .show_starget_node_name = 1,
+ .show_starget_port_name = 1,
+ .show_starget_port_id = 1,
+ .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo,
+ .show_rport_dev_loss_tmo = 1,
+
+};
+
+/* FIXME! values controlling firmware RESCAN event
+ * need to be set low to allow dev_loss_tmo to
+ * work as expected. Currently, firmware doesn't
+ * notify driver of RESCAN event until some number
+ * of seconds elapse. This value can be set via
+ * lsiutil.
+ */
+static void
+mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
+{
+ if (timeout > 0)
+ rport->dev_loss_tmo = timeout;
+ else
+ rport->dev_loss_tmo = mptfc_dev_loss_tmo;
+}
+
+static int
+mptfc_FcDevPage0_cmp_func(const void *a, const void *b)
+{
+ FCDevicePage0_t **aa = (FCDevicePage0_t **)a;
+ FCDevicePage0_t **bb = (FCDevicePage0_t **)b;
+
+ if ((*aa)->CurrentBus == (*bb)->CurrentBus) {
+ if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)
+ return 0;
+ if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)
+ return -1;
+ return 1;
+ }
+ if ((*aa)->CurrentBus < (*bb)->CurrentBus)
+ return -1;
+ return 1;
+}
+
+static int
+mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
+ void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))
+{
+ ConfigPageHeader_t hdr;
+ CONFIGPARMS cfg;
+ FCDevicePage0_t *ppage0_alloc, *fc;
+ dma_addr_t page0_dma;
+ int data_sz;
+ int ii;
+
+ FCDevicePage0_t *p0_array=NULL, *p_p0;
+ FCDevicePage0_t **pp0_array=NULL, **p_pp0;
+
+ int rc = -ENOMEM;
+ U32 port_id = 0xffffff;
+ int num_targ = 0;
+ int max_bus = ioc->facts.MaxBuses;
+ int max_targ = ioc->facts.MaxDevices;
+
+ if (max_bus == 0 || max_targ == 0)
+ goto out;
+
+ data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
+ p_p0 = p0_array = kzalloc(data_sz, GFP_KERNEL);
+ if (!p0_array)
+ goto out;
+
+ data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;
+ p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);
+ if (!pp0_array)
+ goto out;
+
+ do {
+ /* Get FC Device Page 0 header */
+ hdr.PageVersion = 0;
+ hdr.PageLength = 0;
+ hdr.PageNumber = 0;
+ hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;
+ cfg.cfghdr.hdr = &hdr;
+ cfg.physAddr = -1;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+ cfg.dir = 0;
+ cfg.pageAddr = port_id;
+ cfg.timeout = 0;
+
+ if ((rc = mpt_config(ioc, &cfg)) != 0)
+ break;
+
+ if (hdr.PageLength <= 0)
+ break;
+
+ data_sz = hdr.PageLength * 4;
+ ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz,
+ &page0_dma);
+ rc = -ENOMEM;
+ if (!ppage0_alloc)
+ break;
+
+ cfg.physAddr = page0_dma;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+ if ((rc = mpt_config(ioc, &cfg)) == 0) {
+ ppage0_alloc->PortIdentifier =
+ le32_to_cpu(ppage0_alloc->PortIdentifier);
+
+ ppage0_alloc->WWNN.Low =
+ le32_to_cpu(ppage0_alloc->WWNN.Low);
+
+ ppage0_alloc->WWNN.High =
+ le32_to_cpu(ppage0_alloc->WWNN.High);
+
+ ppage0_alloc->WWPN.Low =
+ le32_to_cpu(ppage0_alloc->WWPN.Low);
+
+ ppage0_alloc->WWPN.High =
+ le32_to_cpu(ppage0_alloc->WWPN.High);
+
+ ppage0_alloc->BBCredit =
+ le16_to_cpu(ppage0_alloc->BBCredit);
+
+ ppage0_alloc->MaxRxFrameSize =
+ le16_to_cpu(ppage0_alloc->MaxRxFrameSize);
+
+ port_id = ppage0_alloc->PortIdentifier;
+ num_targ++;
+ *p_p0 = *ppage0_alloc; /* save data */
+ *p_pp0++ = p_p0++; /* save addr */
+ }
+ pci_free_consistent(ioc->pcidev, data_sz,
+ (u8 *) ppage0_alloc, page0_dma);
+ if (rc != 0)
+ break;
+
+ } while (port_id <= 0xff0000);
+
+ if (num_targ) {
+ /* sort array */
+ if (num_targ > 1)
+ sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),
+ mptfc_FcDevPage0_cmp_func, NULL);
+ /* call caller's func for each targ */
+ for (ii = 0; ii < num_targ; ii++) {
+ fc = *(pp0_array+ii);
+ func(ioc, ioc_port, fc);
+ }
+ }
+
+ out:
+ if (pp0_array)
+ kfree(pp0_array);
+ if (p0_array)
+ kfree(p0_array);
+ return rc;
+}
+
+static int
+mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
+{
+ /* not currently usable */
+ if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
+ MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
+ return -1;
+
+ if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
+ return -1;
+
+ if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
+ return -1;
+
+ /*
+ * board data structure already normalized to platform endianness
+ * shifted to avoid unaligned access on 64 bit architecture
+ */
+ rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
+ rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
+ rid->port_id = pg0->PortIdentifier;
+ rid->roles = FC_RPORT_ROLE_UNKNOWN;
+ rid->roles |= FC_RPORT_ROLE_FCP_TARGET;
+ if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
+ rid->roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+
+ return 0;
+}
+
+static void
+mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
+{
+ struct fc_rport_identifiers rport_ids;
+ struct fc_rport *rport;
+ struct mptfc_rport_info *ri;
+ int match = 0;
+ u64 port_name;
+ unsigned long flags;
+
+ if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
+ return;
+
+ /* scan list looking for a match */
+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+ list_for_each_entry(ri, &ioc->fc_rports, list) {
+ port_name = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
+ if (port_name == rport_ids.port_name) { /* match */
+ list_move_tail(&ri->list, &ioc->fc_rports);
+ match = 1;
+ break;
+ }
+ }
+ if (!match) { /* allocate one */
+ spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
+ ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
+ if (!ri)
+ return;
+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+ list_add_tail(&ri->list, &ioc->fc_rports);
+ }
+
+ ri->pg0 = *pg0; /* add/update pg0 data */
+ ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
+
+ if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
+ ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
+ spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
+ rport = fc_remote_port_add(ioc->sh,channel, &rport_ids);
+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+ if (rport) {
+ if (*((struct mptfc_rport_info **)rport->dd_data) != ri) {
+ ri->flags &= ~MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
+ ri->vdev = NULL;
+ ri->rport = rport;
+ *((struct mptfc_rport_info **)rport->dd_data) = ri;
+ }
+ rport->dev_loss_tmo = mptfc_dev_loss_tmo;
+ /*
+ * if already mapped, remap here. If not mapped,
+ * slave_alloc will allocate vdev and map
+ */
+ if (ri->flags & MPT_RPORT_INFO_FLAGS_MAPPED_VDEV) {
+ ri->vdev->target_id = ri->pg0.CurrentTargetID;
+ ri->vdev->bus_id = ri->pg0.CurrentBus;
+ ri->vdev->vtarget->target_id = ri->vdev->target_id;
+ ri->vdev->vtarget->bus_id = ri->vdev->bus_id;
+ }
+ #ifdef MPT_DEBUG
+ printk ("mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
+ "rport tid %d, tmo %d\n",
+ ioc->sh->host_no,
+ pg0->PortIdentifier,
+ pg0->WWNN,
+ pg0->WWPN,
+ pg0->CurrentTargetID,
+ ri->rport->scsi_target_id,
+ ri->rport->dev_loss_tmo);
+ #endif
+ } else {
+ list_del(&ri->list);
+ kfree(ri);
+ ri = NULL;
+ }
+ }
+ spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
+
+}
+
/*
- * mptfc_probe - Installs scsi devices per bus.
- * @pdev: Pointer to pci_dev structure
- *
- * Returns 0 for success, non-zero for failure.
- *
+ * 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.
+ * Init memory once per LUN.
*/
+int
+mptfc_slave_alloc(struct scsi_device *sdev)
+{
+ MPT_SCSI_HOST *hd;
+ VirtTarget *vtarget;
+ VirtDevice *vdev;
+ struct scsi_target *starget;
+ struct fc_rport *rport;
+ struct mptfc_rport_info *ri;
+ unsigned long flags;
+
+
+ rport = starget_to_rport(scsi_target(sdev));
+
+ if (!rport || fc_remote_port_chkready(rport))
+ return -ENXIO;
+
+ hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
+
+ vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+ if (!vdev) {
+ printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
+ hd->ioc->name, sizeof(VirtDevice));
+ return -ENOMEM;
+ }
+ memset(vdev, 0, sizeof(VirtDevice));
+
+ spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags);
+
+ if (!(ri = *((struct mptfc_rport_info **)rport->dd_data))) {
+ spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
+ kfree(vdev);
+ return -ENODEV;
+ }
+
+ sdev->hostdata = vdev;
+ starget = scsi_target(sdev);
+ vtarget = starget->hostdata;
+ if (vtarget->num_luns == 0) {
+ vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
+ MPT_TARGET_FLAGS_VALID_INQUIRY;
+ hd->Targets[sdev->id] = vtarget;
+ }
+
+ vtarget->target_id = vdev->target_id;
+ vtarget->bus_id = vdev->bus_id;
+
+ vdev->vtarget = vtarget;
+ vdev->ioc_id = hd->ioc->id;
+ vdev->lun = sdev->lun;
+ vdev->target_id = ri->pg0.CurrentTargetID;
+ vdev->bus_id = ri->pg0.CurrentBus;
+
+ ri->flags |= MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
+ ri->vdev = vdev;
+
+ spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
+
+ vtarget->num_luns++;
+
+#ifdef MPT_DEBUG
+ printk ("mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
+ "CurrentTargetID %d, %x %llx %llx\n",
+ sdev->host->host_no,
+ vtarget->num_luns,
+ sdev->id, ri->pg0.CurrentTargetID,
+ ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN);
+#endif
+
+ return 0;
+}
+
+static int
+mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
+{
+ struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
+ int err;
+
+ err = fc_remote_port_chkready(rport);
+ if (unlikely(err)) {
+ SCpnt->result = err;
+ done(SCpnt);
+ return 0;
+ }
+ return mptscsih_qcmd(SCpnt,done);
+}
+
+static void
+mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
+{
+ unsigned class = 0, cos = 0;
+
+ /* don't know what to do as only one scsi (fc) host was allocated */
+ if (portnum != 0)
+ return;
+
+ class = ioc->fc_port_page0[portnum].SupportedServiceClass;
+ if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)
+ cos |= FC_COS_CLASS1;
+ if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)
+ cos |= FC_COS_CLASS2;
+ if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)
+ cos |= FC_COS_CLASS3;
+
+ fc_host_node_name(ioc->sh) =
+ (u64)ioc->fc_port_page0[portnum].WWNN.High << 32
+ | (u64)ioc->fc_port_page0[portnum].WWNN.Low;
+
+ fc_host_port_name(ioc->sh) =
+ (u64)ioc->fc_port_page0[portnum].WWPN.High << 32
+ | (u64)ioc->fc_port_page0[portnum].WWPN.Low;
+
+ fc_host_port_id(ioc->sh) = ioc->fc_port_page0[portnum].PortIdentifier;
+
+ fc_host_supported_classes(ioc->sh) = cos;
+
+ fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN;
+}
+
+static void
+mptfc_rescan_devices(void *arg)
+{
+ MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
+ int ii;
+ int work_to_do;
+ unsigned long flags;
+ struct mptfc_rport_info *ri;
+
+ do {
+ /* start by tagging all ports as missing */
+ spin_lock_irqsave(&ioc->fc_rport_lock,flags);
+ list_for_each_entry(ri, &ioc->fc_rports, list) {
+ if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
+ ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
+ }
+ }
+ spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
+
+ /*
+ * now rescan devices known to adapter,
+ * will reregister existing rports
+ */
+ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+ (void) mptbase_GetFcPortPage0(ioc, ii);
+ mptfc_init_host_attr(ioc,ii); /* refresh */
+ mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
+ }
+
+ /* delete devices still missing */
+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+ list_for_each_entry(ri, &ioc->fc_rports, list) {
+ /* if newly missing, delete it */
+ if ((ri->flags & (MPT_RPORT_INFO_FLAGS_REGISTERED |
+ MPT_RPORT_INFO_FLAGS_MISSING))
+ == (MPT_RPORT_INFO_FLAGS_REGISTERED |
+ MPT_RPORT_INFO_FLAGS_MISSING)) {
+
+ ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
+ MPT_RPORT_INFO_FLAGS_MISSING);
+ fc_remote_port_delete(ri->rport);
+ /*
+ * remote port not really deleted 'cause
+ * binding is by WWPN and driver only
+ * registers FCP_TARGETs
+ */
+ #ifdef MPT_DEBUG
+ printk ("mptfc_rescan.%d: %llx deleted\n",
+ ioc->sh->host_no, ri->pg0.WWPN);
+ #endif
+ }
+ }
+ spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
+
+ /*
+ * allow multiple passes as target state
+ * might have changed during scan
+ */
+ spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+ if (ioc->fc_rescan_work_count > 2) /* only need one more */
+ ioc->fc_rescan_work_count = 2;
+ work_to_do = --ioc->fc_rescan_work_count;
+ spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+ } while (work_to_do);
+}
+
static int
mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
@@ -148,17 +624,16 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
MPT_SCSI_HOST *hd;
MPT_ADAPTER *ioc;
unsigned long flags;
- int sz, ii;
+ int ii;
int numSGE = 0;
int scale;
int ioc_cap;
- u8 *mem;
int error=0;
int r;
-
+
if ((r = mpt_attach(pdev,id)) != 0)
return r;
-
+
ioc = pci_get_drvdata(pdev);
ioc->DoneCtx = mptfcDoneCtx;
ioc->TaskCtx = mptfcTaskCtx;
@@ -194,7 +669,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 0;
+ return -ENODEV;
}
sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
@@ -207,6 +682,8 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_mptfc_probe;
}
+ INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);
+
spin_lock_irqsave(&ioc->FreeQlock, flags);
/* Attach the SCSI Host to the IOC structure
@@ -268,36 +745,27 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* SCSI needs scsi_cmnd lookup table!
* (with size equal to req_depth*PtrSz!)
*/
- sz = ioc->req_depth * sizeof(void *);
- mem = kmalloc(sz, GFP_ATOMIC);
- if (mem == NULL) {
+ hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
+ if (!hd->ScsiLookup) {
error = -ENOMEM;
goto out_mptfc_probe;
}
- memset(mem, 0, sz);
- hd->ScsiLookup = (struct scsi_cmnd **) mem;
-
- dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
- ioc->name, hd->ScsiLookup, sz));
+ 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)
*/
- sz = sh->max_id * sizeof(void *);
- mem = kmalloc(sz, GFP_ATOMIC);
- if (mem == NULL) {
+ hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
+ if (!hd->Targets) {
error = -ENOMEM;
goto out_mptfc_probe;
}
- memset(mem, 0, sz);
- hd->Targets = (VirtTarget **) mem;
-
- dprintk((KERN_INFO
- " vdev @ %p, sz=%d\n", hd->Targets, sz));
+ dprintk((KERN_INFO " vdev @ %p\n", hd->Targets));
/* Clear the TM flags
*/
@@ -332,6 +800,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hd->scandv_wait_done = 0;
hd->last_queue_full = 0;
+ sh->transportt = mptfc_transport_template;
error = scsi_add_host (sh, &ioc->pcidev->dev);
if(error) {
dprintk((KERN_ERR MYNAM
@@ -339,7 +808,11 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_mptfc_probe;
}
- scsi_scan_host(sh);
+ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+ mptfc_init_host_attr(ioc,ii);
+ mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
+ }
+
return 0;
out_mptfc_probe:
@@ -352,7 +825,7 @@ static struct pci_driver mptfc_driver = {
.name = "mptfc",
.id_table = mptfc_pci_table,
.probe = mptfc_probe,
- .remove = __devexit_p(mptscsih_remove),
+ .remove = __devexit_p(mptfc_remove),
.shutdown = mptscsih_shutdown,
#ifdef CONFIG_PM
.suspend = mptscsih_suspend,
@@ -370,9 +843,20 @@ static struct pci_driver mptfc_driver = {
static int __init
mptfc_init(void)
{
+ int error;
show_mptmod_ver(my_NAME, my_VERSION);
+ /* sanity check module parameter */
+ if (mptfc_dev_loss_tmo == 0)
+ mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
+
+ mptfc_transport_template =
+ fc_attach_transport(&mptfc_transport_functions);
+
+ if (!mptfc_transport_template)
+ return -ENODEV;
+
mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
@@ -387,7 +871,33 @@ mptfc_init(void)
": Registered for IOC reset notifications\n"));
}
- return pci_register_driver(&mptfc_driver);
+ error = pci_register_driver(&mptfc_driver);
+ if (error) {
+ fc_release_transport(mptfc_transport_template);
+ }
+
+ return error;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mptfc_remove - Removed fc infrastructure for devices
+ * @pdev: Pointer to pci_dev structure
+ *
+ */
+static void __devexit mptfc_remove(struct pci_dev *pdev)
+{
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+ struct mptfc_rport_info *p, *n;
+
+ fc_remove_host(ioc->sh);
+
+ list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
+ list_del(&p->list);
+ kfree(p);
+ }
+
+ mptscsih_remove(pdev);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -400,7 +910,8 @@ static void __exit
mptfc_exit(void)
{
pci_unregister_driver(&mptfc_driver);
-
+ fc_release_transport(mptfc_transport_template);
+
mpt_reset_deregister(mptfcDoneCtx);
dprintk((KERN_INFO MYNAM
": Deregistered for IOC reset notifications\n"));
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index 014085d..0b1b728 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -411,14 +411,12 @@ mpt_lan_open(struct net_device *dev)
goto out;
priv->mpt_txfidx_tail = -1;
- priv->SendCtl = kmalloc(priv->tx_max_out * sizeof(struct BufferControl),
+ priv->SendCtl = kcalloc(priv->tx_max_out, sizeof(struct BufferControl),
GFP_KERNEL);
if (priv->SendCtl == NULL)
goto out_mpt_txfidx;
- for (i = 0; i < priv->tx_max_out; i++) {
- memset(&priv->SendCtl[i], 0, sizeof(struct BufferControl));
+ for (i = 0; i < priv->tx_max_out; i++)
priv->mpt_txfidx[++priv->mpt_txfidx_tail] = i;
- }
dlprintk((KERN_INFO MYNAM "@lo: Finished initializing SendCtl\n"));
@@ -428,15 +426,13 @@ mpt_lan_open(struct net_device *dev)
goto out_SendCtl;
priv->mpt_rxfidx_tail = -1;
- priv->RcvCtl = kmalloc(priv->max_buckets_out *
- sizeof(struct BufferControl),
+ priv->RcvCtl = kcalloc(priv->max_buckets_out,
+ sizeof(struct BufferControl),
GFP_KERNEL);
if (priv->RcvCtl == NULL)
goto out_mpt_rxfidx;
- for (i = 0; i < priv->max_buckets_out; i++) {
- memset(&priv->RcvCtl[i], 0, sizeof(struct BufferControl));
+ for (i = 0; i < priv->max_buckets_out; i++)
priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i;
- }
/**/ dlprintk((KERN_INFO MYNAM "/lo: txfidx contains - "));
/**/ for (i = 0; i < priv->tx_max_out; i++)
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 17e9757e..5a06d8d 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 1999-2005 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
- * Copyright (c) 2005 Dell
+ * Copyright (c) 2005-2006 Dell
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -86,6 +86,24 @@ static int mptsasInternalCtx = -1; /* Used only for internal commands */
static int mptsasMgmtCtx = -1;
+enum mptsas_hotplug_action {
+ MPTSAS_ADD_DEVICE,
+ MPTSAS_DEL_DEVICE,
+};
+
+struct mptsas_hotplug_event {
+ struct work_struct work;
+ MPT_ADAPTER *ioc;
+ enum mptsas_hotplug_action event_type;
+ u64 sas_address;
+ u32 channel;
+ u32 id;
+ u32 device_info;
+ u16 handle;
+ u16 parent_handle;
+ u8 phy_id;
+};
+
/*
* SAS topology structures
*
@@ -99,8 +117,8 @@ struct mptsas_devinfo {
u8 phy_id; /* phy number of parent device */
u8 port_id; /* sas physical port this device
is assoc'd with */
- u8 target; /* logical target id of this device */
- u8 bus; /* logical bus number of this device */
+ u8 id; /* logical target id of this device */
+ u8 channel; /* logical bus number of this device */
u64 sas_address; /* WWN of this device,
SATA is assigned by HBA,expander */
u32 device_info; /* bitfield detailed info about this device */
@@ -114,6 +132,7 @@ struct mptsas_phyinfo {
u8 programmed_link_rate; /* programmed max/min phy link rate */
struct mptsas_devinfo identify; /* point to phy device info */
struct mptsas_devinfo attached; /* point to attached device info */
+ struct sas_phy *phy;
struct sas_rphy *rphy;
};
@@ -239,13 +258,12 @@ mptsas_slave_alloc(struct scsi_device *sdev)
struct scsi_target *starget;
int i;
- vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+ 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;
}
- memset(vdev, 0, sizeof(VirtDevice));
vdev->ioc_id = hd->ioc->id;
sdev->hostdata = vdev;
starget = scsi_target(sdev);
@@ -256,19 +274,32 @@ mptsas_slave_alloc(struct scsi_device *sdev)
hd->Targets[sdev->id] = vtarget;
}
+ /*
+ RAID volumes placed beyond the last expected port.
+ */
+ if (sdev->channel == hd->ioc->num_ports) {
+ vdev->target_id = sdev->id;
+ vdev->bus_id = 0;
+ vdev->lun = 0;
+ goto out;
+ }
+
rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
+ mutex_lock(&hd->ioc->sas_topology_mutex);
list_for_each_entry(p, &hd->ioc->sas_topology, list) {
for (i = 0; i < p->num_phys; i++) {
if (p->phy_info[i].attached.sas_address ==
rphy->identify.sas_address) {
vdev->target_id =
- p->phy_info[i].attached.target;
- vdev->bus_id = p->phy_info[i].attached.bus;
+ p->phy_info[i].attached.id;
+ vdev->bus_id = p->phy_info[i].attached.channel;
vdev->lun = sdev->lun;
+ mutex_unlock(&hd->ioc->sas_topology_mutex);
goto out;
}
}
}
+ mutex_unlock(&hd->ioc->sas_topology_mutex);
printk("No matching SAS device found!!\n");
kfree(vdev);
@@ -282,6 +313,42 @@ mptsas_slave_alloc(struct scsi_device *sdev)
return 0;
}
+static void
+mptsas_slave_destroy(struct scsi_device *sdev)
+{
+ struct Scsi_Host *host = sdev->host;
+ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
+ struct sas_rphy *rphy;
+ struct mptsas_portinfo *p;
+ int i;
+
+ /*
+ * Handle hotplug removal case.
+ * We need to clear out attached data structure.
+ */
+ rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
+
+ mutex_lock(&hd->ioc->sas_topology_mutex);
+ list_for_each_entry(p, &hd->ioc->sas_topology, list) {
+ for (i = 0; i < p->num_phys; i++) {
+ if (p->phy_info[i].attached.sas_address ==
+ rphy->identify.sas_address) {
+ memset(&p->phy_info[i].attached, 0,
+ sizeof(struct mptsas_devinfo));
+ p->phy_info[i].rphy = NULL;
+ goto out;
+ }
+ }
+ }
+
+ out:
+ mutex_unlock(&hd->ioc->sas_topology_mutex);
+ /*
+ * TODO: Issue target reset to flush firmware outstanding commands.
+ */
+ mptscsih_slave_destroy(sdev);
+}
+
static struct scsi_host_template mptsas_driver_template = {
.module = THIS_MODULE,
.proc_name = "mptsas",
@@ -293,7 +360,7 @@ static struct scsi_host_template mptsas_driver_template = {
.slave_alloc = mptsas_slave_alloc,
.slave_configure = mptscsih_slave_configure,
.target_destroy = mptscsih_target_destroy,
- .slave_destroy = mptscsih_slave_destroy,
+ .slave_destroy = mptsas_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth,
.eh_abort_handler = mptscsih_abort,
.eh_device_reset_handler = mptscsih_dev_reset,
@@ -399,7 +466,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
return -ENXIO;
- if (down_interruptible(&ioc->sas_mgmt.mutex))
+ if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
goto out;
mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
@@ -450,7 +517,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
error = 0;
out_unlock:
- up(&ioc->sas_mgmt.mutex);
+ mutex_unlock(&ioc->sas_mgmt.mutex);
out:
return error;
}
@@ -649,8 +716,8 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
device_info->handle = le16_to_cpu(buffer->DevHandle);
device_info->phy_id = buffer->PhyNum;
device_info->port_id = buffer->PhysicalPort;
- device_info->target = buffer->TargetID;
- device_info->bus = buffer->Bus;
+ device_info->id = buffer->TargetID;
+ device_info->channel = buffer->Bus;
memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
device_info->sas_address = le64_to_cpu(sas_address);
device_info->device_info =
@@ -858,36 +925,36 @@ mptsas_parse_device_info(struct sas_identify *identify,
static int mptsas_probe_one_phy(struct device *dev,
struct mptsas_phyinfo *phy_info, int index, int local)
{
- struct sas_phy *port;
+ struct sas_phy *phy;
int error;
- port = sas_phy_alloc(dev, index);
- if (!port)
+ phy = sas_phy_alloc(dev, index);
+ if (!phy)
return -ENOMEM;
- port->port_identifier = phy_info->port_id;
- mptsas_parse_device_info(&port->identify, &phy_info->identify);
+ phy->port_identifier = phy_info->port_id;
+ mptsas_parse_device_info(&phy->identify, &phy_info->identify);
/*
* Set Negotiated link rate.
*/
switch (phy_info->negotiated_link_rate) {
case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
- port->negotiated_linkrate = SAS_PHY_DISABLED;
+ phy->negotiated_linkrate = SAS_PHY_DISABLED;
break;
case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
- port->negotiated_linkrate = SAS_LINK_RATE_FAILED;
+ phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
break;
case MPI_SAS_IOUNIT0_RATE_1_5:
- port->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
+ phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
break;
case MPI_SAS_IOUNIT0_RATE_3_0:
- port->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
+ phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
break;
case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
default:
- port->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
+ phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
break;
}
@@ -896,10 +963,10 @@ static int mptsas_probe_one_phy(struct device *dev,
*/
switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
- port->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
+ phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
break;
case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
- port->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
+ phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
break;
default:
break;
@@ -911,10 +978,10 @@ static int mptsas_probe_one_phy(struct device *dev,
switch (phy_info->programmed_link_rate &
MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
- port->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
+ phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
break;
case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
- port->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
+ phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
break;
default:
break;
@@ -925,10 +992,10 @@ static int mptsas_probe_one_phy(struct device *dev,
*/
switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
- port->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
+ phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
break;
case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
- port->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
+ phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
break;
default:
break;
@@ -940,28 +1007,29 @@ static int mptsas_probe_one_phy(struct device *dev,
switch (phy_info->programmed_link_rate &
MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
- port->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
+ phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
break;
case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
- port->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
+ phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
break;
default:
break;
}
if (local)
- port->local_attached = 1;
+ phy->local_attached = 1;
- error = sas_phy_add(port);
+ error = sas_phy_add(phy);
if (error) {
- sas_phy_free(port);
+ sas_phy_free(phy);
return error;
}
+ phy_info->phy = phy;
if (phy_info->attached.handle) {
struct sas_rphy *rphy;
- rphy = sas_rphy_alloc(port);
+ rphy = sas_rphy_alloc(phy);
if (!rphy)
return 0; /* non-fatal: an rphy can be added later */
@@ -985,16 +1053,19 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
u32 handle = 0xFFFF;
int error = -ENOMEM, i;
- port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
+ port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
if (!port_info)
goto out;
- memset(port_info, 0, sizeof(*port_info));
error = mptsas_sas_io_unit_pg0(ioc, port_info);
if (error)
goto out_free_port_info;
+ ioc->num_ports = port_info->num_phys;
+ mutex_lock(&ioc->sas_topology_mutex);
list_add_tail(&port_info->list, &ioc->sas_topology);
+ 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 <<
@@ -1034,10 +1105,9 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
struct mptsas_portinfo *port_info, *p;
int error = -ENOMEM, i, j;
- port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
+ port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
if (!port_info)
goto out;
- memset(port_info, 0, sizeof(*port_info));
error = mptsas_sas_expander_pg0(ioc, port_info,
(MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
@@ -1047,7 +1117,10 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
*handle = port_info->handle;
+ mutex_lock(&ioc->sas_topology_mutex);
list_add_tail(&port_info->list, &ioc->sas_topology);
+ mutex_unlock(&ioc->sas_topology_mutex);
+
for (i = 0; i < port_info->num_phys; i++) {
struct device *parent;
@@ -1079,6 +1152,7 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
* HBA phys.
*/
parent = &ioc->sh->shost_gendev;
+ mutex_lock(&ioc->sas_topology_mutex);
list_for_each_entry(p, &ioc->sas_topology, list) {
for (j = 0; j < p->num_phys; j++) {
if (port_info->phy_info[i].identify.handle ==
@@ -1086,6 +1160,7 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
parent = &p->phy_info[j].rphy->dev;
}
}
+ mutex_unlock(&ioc->sas_topology_mutex);
mptsas_probe_one_phy(parent, &port_info->phy_info[i],
*index, 0);
@@ -1111,6 +1186,211 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
;
}
+static struct mptsas_phyinfo *
+mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
+{
+ struct mptsas_portinfo *port_info;
+ struct mptsas_devinfo device_info;
+ struct mptsas_phyinfo *phy_info = NULL;
+ int i, error;
+
+ /*
+ * Retrieve the parent sas_address
+ */
+ error = mptsas_sas_device_pg0(ioc, &device_info,
+ (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+ MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+ parent_handle);
+ if (error) {
+ printk("mptsas: failed to retrieve device page\n");
+ return NULL;
+ }
+
+ /*
+ * The phy_info structures are never deallocated during lifetime of
+ * a host, so the code below is safe without additional refcounting.
+ */
+ mutex_lock(&ioc->sas_topology_mutex);
+ list_for_each_entry(port_info, &ioc->sas_topology, list) {
+ for (i = 0; i < port_info->num_phys; i++) {
+ if (port_info->phy_info[i].identify.sas_address ==
+ device_info.sas_address &&
+ port_info->phy_info[i].phy_id == phy_id) {
+ phy_info = &port_info->phy_info[i];
+ break;
+ }
+ }
+ }
+ mutex_unlock(&ioc->sas_topology_mutex);
+
+ return phy_info;
+}
+
+static struct mptsas_phyinfo *
+mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
+{
+ struct mptsas_portinfo *port_info;
+ struct mptsas_phyinfo *phy_info = NULL;
+ int i;
+
+ /*
+ * The phy_info structures are never deallocated during lifetime of
+ * a host, so the code below is safe without additional refcounting.
+ */
+ mutex_lock(&ioc->sas_topology_mutex);
+ list_for_each_entry(port_info, &ioc->sas_topology, list) {
+ for (i = 0; i < port_info->num_phys; i++) {
+ if (port_info->phy_info[i].attached.handle == handle) {
+ phy_info = &port_info->phy_info[i];
+ break;
+ }
+ }
+ }
+ mutex_unlock(&ioc->sas_topology_mutex);
+
+ return phy_info;
+}
+
+static void
+mptsas_hotplug_work(void *arg)
+{
+ struct mptsas_hotplug_event *ev = arg;
+ MPT_ADAPTER *ioc = ev->ioc;
+ struct mptsas_phyinfo *phy_info;
+ struct sas_rphy *rphy;
+ char *ds = NULL;
+
+ if (ev->device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+ ds = "ssp";
+ if (ev->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
+ ds = "stp";
+ if (ev->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+ ds = "sata";
+
+ switch (ev->event_type) {
+ case MPTSAS_DEL_DEVICE:
+ printk(MYIOC_s_INFO_FMT
+ "removing %s device, channel %d, id %d, phy %d\n",
+ ioc->name, ds, ev->channel, ev->id, ev->phy_id);
+
+ phy_info = mptsas_find_phyinfo_by_handle(ioc, ev->handle);
+ if (!phy_info) {
+ printk("mptsas: remove event for non-existant PHY.\n");
+ break;
+ }
+
+ if (phy_info->rphy) {
+ sas_rphy_delete(phy_info->rphy);
+ phy_info->rphy = NULL;
+ }
+ break;
+ case MPTSAS_ADD_DEVICE:
+ printk(MYIOC_s_INFO_FMT
+ "attaching %s device, channel %d, id %d, phy %d\n",
+ ioc->name, ds, ev->channel, ev->id, ev->phy_id);
+
+ phy_info = mptsas_find_phyinfo_by_parent(ioc,
+ ev->parent_handle, ev->phy_id);
+ if (!phy_info) {
+ printk("mptsas: add event for non-existant PHY.\n");
+ break;
+ }
+
+ if (phy_info->rphy) {
+ printk("mptsas: trying to add existing device.\n");
+ break;
+ }
+
+ /* fill attached info */
+ phy_info->attached.handle = ev->handle;
+ phy_info->attached.phy_id = ev->phy_id;
+ phy_info->attached.port_id = phy_info->identify.port_id;
+ phy_info->attached.id = ev->id;
+ phy_info->attached.channel = ev->channel;
+ phy_info->attached.sas_address = ev->sas_address;
+ phy_info->attached.device_info = ev->device_info;
+
+ rphy = sas_rphy_alloc(phy_info->phy);
+ if (!rphy)
+ break; /* non-fatal: an rphy can be added later */
+
+ mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
+ if (sas_rphy_add(rphy)) {
+ sas_rphy_free(rphy);
+ break;
+ }
+
+ phy_info->rphy = rphy;
+ break;
+ }
+
+ kfree(ev);
+}
+
+static void
+mptscsih_send_sas_event(MPT_ADAPTER *ioc,
+ EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
+{
+ struct mptsas_hotplug_event *ev;
+ u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
+ __le64 sas_address;
+
+ if ((device_info &
+ (MPI_SAS_DEVICE_INFO_SSP_TARGET |
+ MPI_SAS_DEVICE_INFO_STP_TARGET |
+ MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
+ return;
+
+ if ((sas_event_data->ReasonCode &
+ (MPI_EVENT_SAS_DEV_STAT_RC_ADDED |
+ MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0)
+ return;
+
+ ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+ if (!ev) {
+ printk(KERN_WARNING "mptsas: lost hotplug event\n");
+ return;
+ }
+
+
+ INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
+ ev->ioc = ioc;
+ ev->handle = le16_to_cpu(sas_event_data->DevHandle);
+ ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle);
+ ev->channel = sas_event_data->Bus;
+ ev->id = sas_event_data->TargetID;
+ 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 = device_info;
+
+ if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
+ ev->event_type = MPTSAS_ADD_DEVICE;
+ else
+ ev->event_type = MPTSAS_DEL_DEVICE;
+
+ schedule_work(&ev->work);
+}
+
+static int
+mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
+{
+ u8 event = le32_to_cpu(reply->Event) & 0xFF;
+
+ if (!ioc->sh)
+ return 1;
+
+ switch (event) {
+ case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
+ mptscsih_send_sas_event(ioc,
+ (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
+ return 1; /* currently means nothing really */
+
+ default:
+ return mptscsih_event_process(ioc, reply);
+ }
+}
+
static int
mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
@@ -1118,11 +1398,10 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
MPT_SCSI_HOST *hd;
MPT_ADAPTER *ioc;
unsigned long flags;
- int sz, ii;
+ int ii;
int numSGE = 0;
int scale;
int ioc_cap;
- u8 *mem;
int error=0;
int r;
@@ -1203,7 +1482,9 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sh->unique_id = ioc->id;
INIT_LIST_HEAD(&ioc->sas_topology);
- init_MUTEX(&ioc->sas_mgmt.mutex);
+ mutex_init(&ioc->sas_topology_mutex);
+
+ mutex_init(&ioc->sas_mgmt.mutex);
init_completion(&ioc->sas_mgmt.done);
/* Verify that we won't exceed the maximum
@@ -1244,36 +1525,27 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* SCSI needs scsi_cmnd lookup table!
* (with size equal to req_depth*PtrSz!)
*/
- sz = ioc->req_depth * sizeof(void *);
- mem = kmalloc(sz, GFP_ATOMIC);
- if (mem == NULL) {
+ hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
+ if (!hd->ScsiLookup) {
error = -ENOMEM;
goto out_mptsas_probe;
}
- memset(mem, 0, sz);
- hd->ScsiLookup = (struct scsi_cmnd **) mem;
-
- dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
- ioc->name, hd->ScsiLookup, sz));
+ 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)
*/
- sz = sh->max_id * sizeof(void *);
- mem = kmalloc(sz, GFP_ATOMIC);
- if (mem == NULL) {
+ hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
+ if (!hd->Targets) {
error = -ENOMEM;
goto out_mptsas_probe;
}
- memset(mem, 0, sz);
- hd->Targets = (VirtTarget **) mem;
-
- dprintk((KERN_INFO
- " vtarget @ %p, sz=%d\n", hd->Targets, sz));
+ dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
/* Clear the TM flags
*/
@@ -1324,6 +1596,20 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mptsas_scan_sas_topology(ioc);
+ /*
+ Reporting RAID volumes.
+ */
+ if (!ioc->raid_data.pIocPg2)
+ return 0;
+ if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
+ return 0;
+ for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) {
+ scsi_add_device(sh,
+ ioc->num_ports,
+ ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID,
+ 0);
+ }
+
return 0;
out_mptsas_probe:
@@ -1339,10 +1625,12 @@ static void __devexit mptsas_remove(struct pci_dev *pdev)
sas_remove_host(ioc->sh);
+ mutex_lock(&ioc->sas_topology_mutex);
list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
list_del(&p->list);
kfree(p);
}
+ mutex_unlock(&ioc->sas_topology_mutex);
mptscsih_remove(pdev);
}
@@ -1393,7 +1681,7 @@ mptsas_init(void)
mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
- if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) {
+ if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
devtprintk((KERN_INFO MYNAM
": Registered for IOC event notifications\n"));
}
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 93a16fa..cdac557 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -893,6 +893,7 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
* when a lun is disable by mid-layer.
* Do NOT access the referenced scsi_cmnd structure or
* members. Will cause either a paging or NULL ptr error.
+ * (BUT, BUT, BUT, the code does reference it! - mdr)
* @hd: Pointer to a SCSI HOST structure
* @vdevice: per device private data
*
@@ -2162,10 +2163,9 @@ mptscsih_target_alloc(struct scsi_target *starget)
{
VirtTarget *vtarget;
- vtarget = kmalloc(sizeof(VirtTarget), GFP_KERNEL);
+ vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
if (!vtarget)
return -ENOMEM;
- memset(vtarget, 0, sizeof(VirtTarget));
starget->hostdata = vtarget;
return 0;
}
@@ -2185,14 +2185,13 @@ mptscsih_slave_alloc(struct scsi_device *sdev)
VirtDevice *vdev;
struct scsi_target *starget;
- vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+ 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;
}
- memset(vdev, 0, sizeof(VirtDevice));
vdev->ioc_id = hd->ioc->id;
vdev->target_id = sdev->id;
vdev->bus_id = sdev->channel;
@@ -2559,13 +2558,25 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
hd->cmdPtr = NULL;
}
- /* 7. Set flag to force DV and re-read IOC Page 3
+ /* 7. SPI: Set flag to force DV and re-read IOC Page 3
*/
if (ioc->bus_type == SPI) {
ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
ddvtprintk(("Set reload IOC Pg3 Flag\n"));
}
+ /* 7. FC: Rescan for blocked rports which might have returned.
+ */
+ else if (ioc->bus_type == FC) {
+ int work_count;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+ work_count = ++ioc->fc_rescan_work_count;
+ spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+ if (work_count == 1)
+ schedule_work(&ioc->fc_rescan_work);
+ }
dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
}
@@ -2589,6 +2600,8 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
{
MPT_SCSI_HOST *hd;
u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
+ int work_count;
+ unsigned long flags;
devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
ioc->name, event));
@@ -2610,11 +2623,18 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
/* FIXME! */
break;
+ case MPI_EVENT_RESCAN: /* 06 */
+ spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+ work_count = ++ioc->fc_rescan_work_count;
+ spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+ if (work_count == 1)
+ schedule_work(&ioc->fc_rescan_work);
+ break;
+
/*
* CHECKME! Don't think we need to do
* anything for these, but...
*/
- case MPI_EVENT_RESCAN: /* 06 */
case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
/*
@@ -3954,8 +3974,6 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
/* Search IOC page 3 to determine if this is hidden physical disk
*/
-/* Search IOC page 3 to determine if this is hidden physical disk
- */
static int
mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
{
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index ce332a6..7dce292 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -158,11 +158,10 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
MPT_SCSI_HOST *hd;
MPT_ADAPTER *ioc;
unsigned long flags;
- int sz, ii;
+ int ii;
int numSGE = 0;
int scale;
int ioc_cap;
- u8 *mem;
int error=0;
int r;
@@ -288,36 +287,27 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* SCSI needs scsi_cmnd lookup table!
* (with size equal to req_depth*PtrSz!)
*/
- sz = ioc->req_depth * sizeof(void *);
- mem = kmalloc(sz, GFP_ATOMIC);
- if (mem == NULL) {
+ hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
+ if (!hd->ScsiLookup) {
error = -ENOMEM;
goto out_mptspi_probe;
}
- memset(mem, 0, sz);
- hd->ScsiLookup = (struct scsi_cmnd **) mem;
-
- dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
- ioc->name, hd->ScsiLookup, sz));
+ 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)
*/
- sz = sh->max_id * sizeof(void *);
- mem = kmalloc(sz, GFP_ATOMIC);
- if (mem == NULL) {
+ hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
+ if (!hd->Targets) {
error = -ENOMEM;
goto out_mptspi_probe;
}
- memset(mem, 0, sz);
- hd->Targets = (VirtTarget **) mem;
-
- dprintk((KERN_INFO
- " vdev @ %p, sz=%d\n", hd->Targets, sz));
+ dprintk((KERN_INFO " vdev @ %p\n", hd->Targets));
/* Clear the TM flags
*/