diff options
author | Len Brown <len.brown@intel.com> | 2006-01-27 17:18:29 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2006-01-27 17:18:29 -0500 |
commit | 292dd876ee765c478b27c93cc51e93a558ed58bf (patch) | |
tree | 5b740e93253295baee2a9c414a6c66d03d44a9ef /drivers/message/fusion | |
parent | d4ec6c7cc9a15a7a529719bc3b84f46812f9842e (diff) | |
parent | 9fdb62af92c741addbea15545f214a6e89460865 (diff) |
Pull release into acpica branch
Diffstat (limited to 'drivers/message/fusion')
-rw-r--r-- | drivers/message/fusion/Kconfig | 1 | ||||
-rw-r--r-- | drivers/message/fusion/lsi/mpi.h | 10 | ||||
-rw-r--r-- | drivers/message/fusion/lsi/mpi_cnfg.h | 158 | ||||
-rw-r--r-- | drivers/message/fusion/lsi/mpi_history.txt | 77 | ||||
-rw-r--r-- | drivers/message/fusion/lsi/mpi_init.h | 8 | ||||
-rw-r--r-- | drivers/message/fusion/lsi/mpi_ioc.h | 122 | ||||
-rw-r--r-- | drivers/message/fusion/lsi/mpi_log_fc.h | 89 | ||||
-rw-r--r-- | drivers/message/fusion/lsi/mpi_log_sas.h | 162 | ||||
-rw-r--r-- | drivers/message/fusion/lsi/mpi_sas.h | 30 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.c | 48 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.h | 34 | ||||
-rw-r--r-- | drivers/message/fusion/mptctl.c | 14 | ||||
-rw-r--r-- | drivers/message/fusion/mptfc.c | 579 | ||||
-rw-r--r-- | drivers/message/fusion/mptlan.c | 18 | ||||
-rw-r--r-- | drivers/message/fusion/mptsas.c | 404 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 34 | ||||
-rw-r--r-- | drivers/message/fusion/mptspi.c | 26 |
17 files changed, 1560 insertions, 254 deletions
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index 1883d22cffeb..e67cf15e9c39 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 b61e3d175070..02cdc840a06b 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 d8339896f734..b1becec27e1b 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 1a30ef16adb4..4a5f8dd1d766 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 d5af75afbd94..68941f459ca3 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 93b70e2b4266..2c5f43fa7c73 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 000000000000..dc98d46f9071 --- /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 000000000000..9259d1ad6e6e --- /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 230fa69b5353..70514867bddf 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 537836068c49..d890b2b8a93e 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 6c48d1f54ac9..47053ac65068 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 959d2c5951b8..bdf709987982 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; } @@ -2585,8 +2585,6 @@ static struct miscdevice mptctl_miscdev = { #ifdef CONFIG_COMPAT -#include <linux/ioctl32.h> - static int compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) @@ -2621,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; } @@ -2675,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; } @@ -2745,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 ba61e1828858..b102c7666d0e 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 014085d8ec85..73f59528212a 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++) @@ -848,7 +844,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static inline void +static void mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority) /* * @priority: 0 = put it on the timer queue, 1 = put it on the immediate queue @@ -870,7 +866,7 @@ mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static inline int +static int mpt_lan_receive_skb(struct net_device *dev, struct sk_buff *skb) { struct mpt_lan_priv *priv = dev->priv; diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 17e9757e728b..5a06d8d8694e 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 93a16fa3c4ba..cdac5578fdf2 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 ce332a6085e5..7dce29277cb7 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 */ |