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