diff options
Diffstat (limited to 'drivers/message/fusion')
-rw-r--r-- | drivers/message/fusion/Kconfig | 17 | ||||
-rw-r--r-- | drivers/message/fusion/Makefile | 1 | ||||
-rw-r--r-- | drivers/message/fusion/lsi/mpi.h | 19 | ||||
-rw-r--r-- | drivers/message/fusion/lsi/mpi_cnfg.h | 85 | ||||
-rw-r--r-- | drivers/message/fusion/lsi/mpi_history.txt | 67 | ||||
-rw-r--r-- | drivers/message/fusion/lsi/mpi_init.h | 203 | ||||
-rw-r--r-- | drivers/message/fusion/lsi/mpi_ioc.h | 11 | ||||
-rw-r--r-- | drivers/message/fusion/lsi/mpi_targ.h | 74 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.c | 1276 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.h | 61 | ||||
-rw-r--r-- | drivers/message/fusion/mptctl.c | 18 | ||||
-rw-r--r-- | drivers/message/fusion/mptfc.c | 2 | ||||
-rw-r--r-- | drivers/message/fusion/mptlan.c | 7 | ||||
-rw-r--r-- | drivers/message/fusion/mptsas.c | 1239 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 593 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.h | 7 | ||||
-rw-r--r-- | drivers/message/fusion/mptspi.c | 8 |
17 files changed, 2953 insertions, 735 deletions
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index 33f209a39cb6..1883d22cffeb 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig @@ -35,6 +35,23 @@ config FUSION_FC LSIFC929X LSIFC929XL +config FUSION_SAS + tristate "Fusion MPT ScsiHost drivers for SAS" + depends on PCI && SCSI + select FUSION + select SCSI_SAS_ATTRS + ---help--- + SCSI HOST support for a SAS host adapters. + + List of supported controllers: + + LSISAS1064 + LSISAS1066 + LSISAS1068 + LSISAS1064E + LSISAS1066E + LSISAS1068E + config FUSION_MAX_SGE int "Maximum number of scatter gather entries (16 - 128)" depends on FUSION diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile index 1d2f9db813c1..8a2e2657f4c2 100644 --- a/drivers/message/fusion/Makefile +++ b/drivers/message/fusion/Makefile @@ -34,5 +34,6 @@ obj-$(CONFIG_FUSION_SPI) += mptbase.o mptscsih.o mptspi.o obj-$(CONFIG_FUSION_FC) += mptbase.o mptscsih.o mptfc.o +obj-$(CONFIG_FUSION_SAS) += mptbase.o mptscsih.o mptsas.o obj-$(CONFIG_FUSION_CTL) += mptctl.o obj-$(CONFIG_FUSION_LAN) += mptlan.o diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h index 9f98334e5076..b61e3d175070 100644 --- a/drivers/message/fusion/lsi/mpi.h +++ b/drivers/message/fusion/lsi/mpi.h @@ -6,7 +6,7 @@ * Title: MPI Message independent structures and definitions * Creation Date: July 27, 2000 * - * mpi.h Version: 01.05.07 + * mpi.h Version: 01.05.08 * * Version History * --------------- @@ -71,6 +71,9 @@ * 03-11-05 01.05.07 Removed function codes for SCSI IO 32 and * TargetAssistExtended requests. * Removed EEDP IOCStatus codes. + * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and + * TargetAssistExtended requests. + * Added EEDP IOCStatus codes. * -------------------------------------------------------------------------- */ @@ -101,7 +104,7 @@ /* Note: The major versions of 0xe0 through 0xff are reserved */ /* versioning for this MPI header set */ -#define MPI_HEADER_VERSION_UNIT (0x09) +#define MPI_HEADER_VERSION_UNIT (0x0A) #define MPI_HEADER_VERSION_DEV (0x00) #define MPI_HEADER_VERSION_UNIT_MASK (0xFF00) #define MPI_HEADER_VERSION_UNIT_SHIFT (8) @@ -292,10 +295,13 @@ #define MPI_FUNCTION_DIAG_BUFFER_POST (0x1D) #define MPI_FUNCTION_DIAG_RELEASE (0x1E) +#define MPI_FUNCTION_SCSI_IO_32 (0x1F) + #define MPI_FUNCTION_LAN_SEND (0x20) #define MPI_FUNCTION_LAN_RECEIVE (0x21) #define MPI_FUNCTION_LAN_RESET (0x22) +#define MPI_FUNCTION_TARGET_ASSIST_EXTENDED (0x23) #define MPI_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24) #define MPI_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25) @@ -681,6 +687,15 @@ typedef struct _MSG_DEFAULT_REPLY #define MPI_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C) /****************************************************************************/ +/* For use by SCSI Initiator and SCSI Target end-to-end data protection */ +/****************************************************************************/ + +#define MPI_IOCSTATUS_EEDP_GUARD_ERROR (0x004D) +#define MPI_IOCSTATUS_EEDP_REF_TAG_ERROR (0x004E) +#define MPI_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F) + + +/****************************************************************************/ /* SCSI Target values */ /****************************************************************************/ diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h index 15b12b06799d..d8339896f734 100644 --- a/drivers/message/fusion/lsi/mpi_cnfg.h +++ b/drivers/message/fusion/lsi/mpi_cnfg.h @@ -6,7 +6,7 @@ * Title: MPI Config message, structures, and Pages * Creation Date: July 27, 2000 * - * mpi_cnfg.h Version: 01.05.08 + * mpi_cnfg.h Version: 01.05.09 * * Version History * --------------- @@ -232,6 +232,23 @@ * New physical mapping mode in SAS IO Unit Page 2. * Added CONFIG_PAGE_SAS_ENCLOSURE_0. * Added Slot and Enclosure fields to SAS Device Page 0. + * 06-24-05 01.05.09 Added EEDP defines to IOC Page 1. + * Added more RAID type defines to IOC Page 2. + * Added Port Enable Delay settings to BIOS Page 1. + * Added Bad Block Table Full define to RAID Volume Page 0. + * Added Previous State defines to RAID Physical Disk + * Page 0. + * Added Max Sata Targets define for DiscoveryStatus field + * of SAS IO Unit Page 0. + * Added Device Self Test to Control Flags of SAS IO Unit + * Page 1. + * Added Direct Attach Starting Slot Number define for SAS + * IO Unit Page 2. + * Added new fields in SAS Device Page 2 for enclosure + * mapping. + * Added OwnerDevHandle and Flags field to SAS PHY Page 0. + * Added IOC GPIO Flags define to SAS Enclosure Page 0. + * Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT. * -------------------------------------------------------------------------- */ @@ -477,6 +494,7 @@ typedef struct _MSG_CONFIG_REPLY #define MPI_MANUFACTPAGE_DEVICEID_FC929X (0x0626) #define MPI_MANUFACTPAGE_DEVICEID_FC939X (0x0642) #define MPI_MANUFACTPAGE_DEVICEID_FC949X (0x0640) +#define MPI_MANUFACTPAGE_DEVICEID_FC949ES (0x0646) /* SCSI */ #define MPI_MANUFACTPAGE_DEVID_53C1030 (0x0030) #define MPI_MANUFACTPAGE_DEVID_53C1030ZC (0x0031) @@ -769,9 +787,13 @@ typedef struct _CONFIG_PAGE_IOC_1 } CONFIG_PAGE_IOC_1, MPI_POINTER PTR_CONFIG_PAGE_IOC_1, IOCPage1_t, MPI_POINTER pIOCPage1_t; -#define MPI_IOCPAGE1_PAGEVERSION (0x02) +#define MPI_IOCPAGE1_PAGEVERSION (0x03) /* defines for the Flags field */ +#define MPI_IOCPAGE1_EEDP_MODE_MASK (0x07000000) +#define MPI_IOCPAGE1_EEDP_MODE_OFF (0x00000000) +#define MPI_IOCPAGE1_EEDP_MODE_T10 (0x01000000) +#define MPI_IOCPAGE1_EEDP_MODE_LSI_1 (0x02000000) #define MPI_IOCPAGE1_INITIATOR_CONTEXT_REPLY_DISABLE (0x00000010) #define MPI_IOCPAGE1_REPLY_COALESCING (0x00000001) @@ -795,6 +817,11 @@ typedef struct _CONFIG_PAGE_IOC_2_RAID_VOL #define MPI_RAID_VOL_TYPE_IS (0x00) #define MPI_RAID_VOL_TYPE_IME (0x01) #define MPI_RAID_VOL_TYPE_IM (0x02) +#define MPI_RAID_VOL_TYPE_RAID_5 (0x03) +#define MPI_RAID_VOL_TYPE_RAID_6 (0x04) +#define MPI_RAID_VOL_TYPE_RAID_10 (0x05) +#define MPI_RAID_VOL_TYPE_RAID_50 (0x06) +#define MPI_RAID_VOL_TYPE_UNKNOWN (0xFF) /* IOC Page 2 Volume Flags values */ @@ -820,13 +847,17 @@ typedef struct _CONFIG_PAGE_IOC_2 } CONFIG_PAGE_IOC_2, MPI_POINTER PTR_CONFIG_PAGE_IOC_2, IOCPage2_t, MPI_POINTER pIOCPage2_t; -#define MPI_IOCPAGE2_PAGEVERSION (0x02) +#define MPI_IOCPAGE2_PAGEVERSION (0x03) /* IOC Page 2 Capabilities flags */ #define MPI_IOCPAGE2_CAP_FLAGS_IS_SUPPORT (0x00000001) #define MPI_IOCPAGE2_CAP_FLAGS_IME_SUPPORT (0x00000002) #define MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT (0x00000004) +#define MPI_IOCPAGE2_CAP_FLAGS_RAID_5_SUPPORT (0x00000008) +#define MPI_IOCPAGE2_CAP_FLAGS_RAID_6_SUPPORT (0x00000010) +#define MPI_IOCPAGE2_CAP_FLAGS_RAID_10_SUPPORT (0x00000020) +#define MPI_IOCPAGE2_CAP_FLAGS_RAID_50_SUPPORT (0x00000040) #define MPI_IOCPAGE2_CAP_FLAGS_SES_SUPPORT (0x20000000) #define MPI_IOCPAGE2_CAP_FLAGS_SAFTE_SUPPORT (0x40000000) #define MPI_IOCPAGE2_CAP_FLAGS_CROSS_CHANNEL_SUPPORT (0x80000000) @@ -945,7 +976,7 @@ typedef struct _CONFIG_PAGE_BIOS_1 } CONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1, BIOSPage1_t, MPI_POINTER pBIOSPage1_t; -#define MPI_BIOSPAGE1_PAGEVERSION (0x01) +#define MPI_BIOSPAGE1_PAGEVERSION (0x02) /* values for the BiosOptions field */ #define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE (0x00000400) @@ -954,6 +985,8 @@ typedef struct _CONFIG_PAGE_BIOS_1 #define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001) /* values for the IOCSettings field */ +#define MPI_BIOSPAGE1_IOCSET_MASK_PORT_ENABLE_DELAY (0x00F00000) +#define MPI_BIOSPAGE1_IOCSET_SHIFT_PORT_ENABLE_DELAY (20) #define MPI_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000) #define MPI_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000) #define MPI_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000) @@ -1167,6 +1200,7 @@ typedef struct _CONFIG_PAGE_BIOS_2 #define MPI_BIOSPAGE2_FORM_PCI_SLOT_NUMBER (0x03) #define MPI_BIOSPAGE2_FORM_FC_WWN (0x04) #define MPI_BIOSPAGE2_FORM_SAS_WWN (0x05) +#define MPI_BIOSPAGE2_FORM_ENCLOSURE_SLOT (0x06) /**************************************************************************** @@ -1957,11 +1991,11 @@ typedef struct _RAID_VOL0_STATUS RaidVol0Status_t, MPI_POINTER pRaidVol0Status_t; /* RAID Volume Page 0 VolumeStatus defines */ - #define MPI_RAIDVOL0_STATUS_FLAG_ENABLED (0x01) #define MPI_RAIDVOL0_STATUS_FLAG_QUIESCED (0x02) #define MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS (0x04) #define MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE (0x08) +#define MPI_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL (0x10) #define MPI_RAIDVOL0_STATUS_STATE_OPTIMAL (0x00) #define MPI_RAIDVOL0_STATUS_STATE_DEGRADED (0x01) @@ -2025,7 +2059,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 (0x04) +#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x05) /* values for RAID Volume Page 0 InactiveStatus field */ #define MPI_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00) @@ -2104,6 +2138,8 @@ typedef struct _RAID_PHYS_DISK0_STATUS #define MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC (0x01) #define MPI_PHYSDISK0_STATUS_FLAG_QUIESCED (0x02) #define MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME (0x04) +#define MPI_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS (0x00) +#define MPI_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS (0x08) #define MPI_PHYSDISK0_STATUS_ONLINE (0x00) #define MPI_PHYSDISK0_STATUS_MISSING (0x01) @@ -2132,7 +2168,7 @@ typedef struct _CONFIG_PAGE_RAID_PHYS_DISK_0 } CONFIG_PAGE_RAID_PHYS_DISK_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_0, RaidPhysDiskPage0_t, MPI_POINTER pRaidPhysDiskPage0_t; -#define MPI_RAIDPHYSDISKPAGE0_PAGEVERSION (0x01) +#define MPI_RAIDPHYSDISKPAGE0_PAGEVERSION (0x02) typedef struct _RAID_PHYS_DISK1_PATH @@ -2263,7 +2299,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0 } CONFIG_PAGE_SAS_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_0, SasIOUnitPage0_t, MPI_POINTER pSasIOUnitPage0_t; -#define MPI_SASIOUNITPAGE0_PAGEVERSION (0x02) +#define MPI_SASIOUNITPAGE0_PAGEVERSION (0x03) /* values for SAS IO Unit Page 0 PortFlags */ #define MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS (0x08) @@ -2299,6 +2335,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0 #define MPI_SAS_IOUNIT0_DS_SUBTRACTIVE_LINK (0x00000200) #define MPI_SAS_IOUNIT0_DS_TABLE_LINK (0x00000400) #define MPI_SAS_IOUNIT0_DS_UNSUPPORTED_DEVICE (0x00000800) +#define MPI_SAS_IOUNIT0_DS_MAX_SATA_TARGETS (0x00001000) typedef struct _MPI_SAS_IO_UNIT1_PHY_DATA @@ -2336,6 +2373,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1 #define MPI_SASIOUNITPAGE1_PAGEVERSION (0x04) /* values for SAS IO Unit Page 1 ControlFlags */ +#define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000) #define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX (0x4000) #define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX (0x2000) #define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000) @@ -2345,9 +2383,8 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1 #define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9) #define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x00) #define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x01) -#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x10) +#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x02) -#define MPI_SAS_IOUNIT1_CONTROL_AUTO_PORT_SAME_SAS_ADDR (0x0100) #define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080) #define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040) #define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020) @@ -2390,7 +2427,7 @@ 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 (0x03) +#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x04) /* values for SAS IO Unit Page 2 Status field */ #define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02) @@ -2406,6 +2443,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2 #define MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP (0x02) #define MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT (0x10) +#define MPI_SAS_IOUNIT2_FLAGS_DA_STARTING_SLOT (0x20) typedef struct _CONFIG_PAGE_SAS_IO_UNIT_3 @@ -2584,11 +2622,19 @@ typedef struct _CONFIG_PAGE_SAS_DEVICE_2 { CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ U64 PhysicalIdentifier; /* 08h */ - U32 Reserved1; /* 10h */ + U32 EnclosureMapping; /* 10h */ } CONFIG_PAGE_SAS_DEVICE_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_2, SasDevicePage2_t, MPI_POINTER pSasDevicePage2_t; -#define MPI_SASDEVICE2_PAGEVERSION (0x00) +#define MPI_SASDEVICE2_PAGEVERSION (0x01) + +/* defines for SAS Device Page 2 EnclosureMapping field */ +#define MPI_SASDEVICE2_ENC_MAP_MASK_MISSING_COUNT (0x0000000F) +#define MPI_SASDEVICE2_ENC_MAP_SHIFT_MISSING_COUNT (0) +#define MPI_SASDEVICE2_ENC_MAP_MASK_NUM_SLOTS (0x000007F0) +#define MPI_SASDEVICE2_ENC_MAP_SHIFT_NUM_SLOTS (4) +#define MPI_SASDEVICE2_ENC_MAP_MASK_START_INDEX (0x001FF800) +#define MPI_SASDEVICE2_ENC_MAP_SHIFT_START_INDEX (11) /**************************************************************************** @@ -2598,7 +2644,8 @@ typedef struct _CONFIG_PAGE_SAS_DEVICE_2 typedef struct _CONFIG_PAGE_SAS_PHY_0 { CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ - U32 Reserved1; /* 08h */ + U16 OwnerDevHandle; /* 08h */ + U16 Reserved1; /* 0Ah */ U64 SASAddress; /* 0Ch */ U16 AttachedDevHandle; /* 14h */ U8 AttachedPhyIdentifier; /* 16h */ @@ -2607,12 +2654,12 @@ typedef struct _CONFIG_PAGE_SAS_PHY_0 U8 ProgrammedLinkRate; /* 20h */ U8 HwLinkRate; /* 21h */ U8 ChangeCount; /* 22h */ - U8 Reserved3; /* 23h */ + U8 Flags; /* 23h */ U32 PhyInfo; /* 24h */ } CONFIG_PAGE_SAS_PHY_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_0, SasPhyPage0_t, MPI_POINTER pSasPhyPage0_t; -#define MPI_SASPHY0_PAGEVERSION (0x00) +#define MPI_SASPHY0_PAGEVERSION (0x01) /* values for SAS PHY Page 0 ProgrammedLinkRate field */ #define MPI_SAS_PHY0_PRATE_MAX_RATE_MASK (0xF0) @@ -2632,6 +2679,9 @@ typedef struct _CONFIG_PAGE_SAS_PHY_0 #define MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5 (0x08) #define MPI_SAS_PHY0_HWRATE_MIN_RATE_3_0 (0x09) +/* values for SAS PHY Page 0 Flags field */ +#define MPI_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC (0x01) + /* values for SAS PHY Page 0 PhyInfo field */ #define MPI_SAS_PHY0_PHYINFO_SATA_PORT_ACTIVE (0x00004000) #define MPI_SAS_PHY0_PHYINFO_SATA_PORT_SELECTOR (0x00002000) @@ -2690,7 +2740,7 @@ typedef struct _CONFIG_PAGE_SAS_ENCLOSURE_0 } CONFIG_PAGE_SAS_ENCLOSURE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_ENCLOSURE_0, SasEnclosurePage0_t, MPI_POINTER pSasEnclosurePage0_t; -#define MPI_SASENCLOSURE0_PAGEVERSION (0x00) +#define MPI_SASENCLOSURE0_PAGEVERSION (0x01) /* values for SAS Enclosure Page 0 Flags field */ #define MPI_SAS_ENCLS0_FLAGS_SEP_BUS_ID_VALID (0x0020) @@ -2702,6 +2752,7 @@ typedef struct _CONFIG_PAGE_SAS_ENCLOSURE_0 #define MPI_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO (0x0002) #define MPI_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO (0x0003) #define MPI_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004) +#define MPI_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO (0x0005) /**************************************************************************** diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt index c9edbee41edf..1a30ef16adb4 100644 --- a/drivers/message/fusion/lsi/mpi_history.txt +++ b/drivers/message/fusion/lsi/mpi_history.txt @@ -6,17 +6,17 @@ Copyright (c) 2000-2005 LSI Logic Corporation. --------------------------------------- - Header Set Release Version: 01.05.09 + Header Set Release Version: 01.05.10 Header Set Release Date: 03-11-05 --------------------------------------- Filename Current version Prior version ---------- --------------- ------------- - mpi.h 01.05.07 01.05.06 - mpi_ioc.h 01.05.08 01.05.07 - mpi_cnfg.h 01.05.08 01.05.07 - mpi_init.h 01.05.04 01.05.03 - mpi_targ.h 01.05.04 01.05.03 + mpi.h 01.05.08 01.05.07 + mpi_ioc.h 01.05.09 01.05.08 + mpi_cnfg.h 01.05.09 01.05.08 + mpi_init.h 01.05.05 01.05.04 + mpi_targ.h 01.05.05 01.05.04 mpi_fc.h 01.05.01 01.05.01 mpi_lan.h 01.05.01 01.05.01 mpi_raid.h 01.05.02 01.05.02 @@ -24,7 +24,7 @@ mpi_inb.h 01.05.01 01.05.01 mpi_sas.h 01.05.01 01.05.01 mpi_type.h 01.05.01 01.05.01 - mpi_history.txt 01.05.09 01.05.08 + mpi_history.txt 01.05.09 01.05.09 * Date Version Description @@ -88,6 +88,9 @@ mpi.h * 03-11-05 01.05.07 Removed function codes for SCSI IO 32 and * TargetAssistExtended requests. * Removed EEDP IOCStatus codes. + * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and + * TargetAssistExtended requests. + * Added EEDP IOCStatus codes. * -------------------------------------------------------------------------- mpi_ioc.h @@ -159,6 +162,8 @@ mpi_ioc.h * Reply and IOC Init Request. * 03-11-05 01.05.08 Added family code for 1068E family. * Removed IOCFacts Reply EEDP Capability bit. + * 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits. + * Added Max SATA Targets to SAS Discovery Error event. * -------------------------------------------------------------------------- mpi_cnfg.h @@ -380,6 +385,23 @@ mpi_cnfg.h * New physical mapping mode in SAS IO Unit Page 2. * Added CONFIG_PAGE_SAS_ENCLOSURE_0. * Added Slot and Enclosure fields to SAS Device Page 0. + * 06-24-05 01.05.09 Added EEDP defines to IOC Page 1. + * Added more RAID type defines to IOC Page 2. + * Added Port Enable Delay settings to BIOS Page 1. + * Added Bad Block Table Full define to RAID Volume Page 0. + * Added Previous State defines to RAID Physical Disk + * Page 0. + * Added Max Sata Targets define for DiscoveryStatus field + * of SAS IO Unit Page 0. + * Added Device Self Test to Control Flags of SAS IO Unit + * Page 1. + * Added Direct Attach Starting Slot Number define for SAS + * IO Unit Page 2. + * Added new fields in SAS Device Page 2 for enclosure + * mapping. + * Added OwnerDevHandle and Flags field to SAS PHY Page 0. + * Added IOC GPIO Flags define to SAS Enclosure Page 0. + * Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT. * -------------------------------------------------------------------------- mpi_init.h @@ -418,6 +440,8 @@ mpi_init.h * Modified SCSI Enclosure Processor Request and Reply to * support Enclosure/Slot addressing rather than WWID * addressing. + * 06-24-05 01.05.05 Added SCSI IO 32 structures and defines. + * Added four new defines for SEP SlotStatus. * -------------------------------------------------------------------------- mpi_targ.h @@ -461,6 +485,7 @@ mpi_targ.h * 10-05-04 01.05.02 MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY added. * 02-22-05 01.05.03 Changed a comment. * 03-11-05 01.05.04 Removed TargetAssistExtended Request. + * 06-24-05 01.05.05 Added TargetAssistExtended structures and defines. * -------------------------------------------------------------------------- mpi_fc.h @@ -571,20 +596,20 @@ mpi_type.h mpi_history.txt Parts list history -Filename 01.05.09 ----------- -------- -mpi.h 01.05.07 -mpi_ioc.h 01.05.08 -mpi_cnfg.h 01.05.08 -mpi_init.h 01.05.04 -mpi_targ.h 01.05.04 -mpi_fc.h 01.05.01 -mpi_lan.h 01.05.01 -mpi_raid.h 01.05.02 -mpi_tool.h 01.05.03 -mpi_inb.h 01.05.01 -mpi_sas.h 01.05.01 -mpi_type.h 01.05.01 +Filename 01.05.10 01.05.09 +---------- -------- -------- +mpi.h 01.05.08 01.05.07 +mpi_ioc.h 01.05.09 01.05.08 +mpi_cnfg.h 01.05.09 01.05.08 +mpi_init.h 01.05.05 01.05.04 +mpi_targ.h 01.05.05 01.05.04 +mpi_fc.h 01.05.01 01.05.01 +mpi_lan.h 01.05.01 01.05.01 +mpi_raid.h 01.05.02 01.05.02 +mpi_tool.h 01.05.03 01.05.03 +mpi_inb.h 01.05.01 01.05.01 +mpi_sas.h 01.05.01 01.05.01 +mpi_type.h 01.05.01 01.05.01 Filename 01.05.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 aca035801a86..d5af75afbd94 100644 --- a/drivers/message/fusion/lsi/mpi_init.h +++ b/drivers/message/fusion/lsi/mpi_init.h @@ -6,7 +6,7 @@ * Title: MPI initiator mode messages and structures * Creation Date: June 8, 2000 * - * mpi_init.h Version: 01.05.04 + * mpi_init.h Version: 01.05.05 * * Version History * --------------- @@ -48,6 +48,8 @@ * Modified SCSI Enclosure Processor Request and Reply to * support Enclosure/Slot addressing rather than WWID * addressing. + * 06-24-05 01.05.05 Added SCSI IO 32 structures and defines. + * Added four new defines for SEP SlotStatus. * -------------------------------------------------------------------------- */ @@ -203,6 +205,197 @@ typedef struct _MSG_SCSI_IO_REPLY /****************************************************************************/ +/* SCSI IO 32 messages and associated structures */ +/****************************************************************************/ + +typedef struct +{ + U8 CDB[20]; /* 00h */ + U32 PrimaryReferenceTag; /* 14h */ + U16 PrimaryApplicationTag; /* 18h */ + U16 PrimaryApplicationTagMask; /* 1Ah */ + U32 TransferLength; /* 1Ch */ +} MPI_SCSI_IO32_CDB_EEDP32, MPI_POINTER PTR_MPI_SCSI_IO32_CDB_EEDP32, + MpiScsiIo32CdbEedp32_t, MPI_POINTER pMpiScsiIo32CdbEedp32_t; + +typedef struct +{ + U8 CDB[16]; /* 00h */ + U32 DataLength; /* 10h */ + U32 PrimaryReferenceTag; /* 14h */ + U16 PrimaryApplicationTag; /* 18h */ + U16 PrimaryApplicationTagMask; /* 1Ah */ + U32 TransferLength; /* 1Ch */ +} MPI_SCSI_IO32_CDB_EEDP16, MPI_POINTER PTR_MPI_SCSI_IO32_CDB_EEDP16, + MpiScsiIo32CdbEedp16_t, MPI_POINTER pMpiScsiIo32CdbEedp16_t; + +typedef union +{ + U8 CDB32[32]; + MPI_SCSI_IO32_CDB_EEDP32 EEDP32; + MPI_SCSI_IO32_CDB_EEDP16 EEDP16; + SGE_SIMPLE_UNION SGE; +} MPI_SCSI_IO32_CDB_UNION, MPI_POINTER PTR_MPI_SCSI_IO32_CDB_UNION, + MpiScsiIo32Cdb_t, MPI_POINTER pMpiScsiIo32Cdb_t; + +typedef struct +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U16 Reserved1; /* 02h */ + U32 Reserved2; /* 04h */ +} MPI_SCSI_IO32_BUS_TARGET_ID_FORM, MPI_POINTER PTR_MPI_SCSI_IO32_BUS_TARGET_ID_FORM, + MpiScsiIo32BusTargetIdForm_t, MPI_POINTER pMpiScsiIo32BusTargetIdForm_t; + +typedef union +{ + MPI_SCSI_IO32_BUS_TARGET_ID_FORM SCSIID; + U64 WWID; +} MPI_SCSI_IO32_ADDRESS, MPI_POINTER PTR_MPI_SCSI_IO32_ADDRESS, + MpiScsiIo32Address_t, MPI_POINTER pMpiScsiIo32Address_t; + +typedef struct _MSG_SCSI_IO32_REQUEST +{ + U8 Port; /* 00h */ + U8 Reserved1; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 CDBLength; /* 04h */ + U8 SenseBufferLength; /* 05h */ + U8 Flags; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 LUN[8]; /* 0Ch */ + U32 Control; /* 14h */ + MPI_SCSI_IO32_CDB_UNION CDB; /* 18h */ + U32 DataLength; /* 38h */ + U32 BidirectionalDataLength; /* 3Ch */ + U32 SecondaryReferenceTag; /* 40h */ + U16 SecondaryApplicationTag; /* 44h */ + U16 Reserved2; /* 46h */ + U16 EEDPFlags; /* 48h */ + U16 ApplicationTagTranslationMask; /* 4Ah */ + U32 EEDPBlockSize; /* 4Ch */ + MPI_SCSI_IO32_ADDRESS DeviceAddress; /* 50h */ + U8 SGLOffset0; /* 58h */ + U8 SGLOffset1; /* 59h */ + U8 SGLOffset2; /* 5Ah */ + U8 SGLOffset3; /* 5Bh */ + U32 Reserved3; /* 5Ch */ + U32 Reserved4; /* 60h */ + U32 SenseBufferLowAddr; /* 64h */ + SGE_IO_UNION SGL; /* 68h */ +} MSG_SCSI_IO32_REQUEST, MPI_POINTER PTR_MSG_SCSI_IO32_REQUEST, + SCSIIO32Request_t, MPI_POINTER pSCSIIO32Request_t; + +/* SCSI IO 32 MsgFlags bits */ +#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH (0x01) +#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_32 (0x00) +#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_64 (0x01) + +#define MPI_SCSIIO32_MSGFLGS_SENSE_LOCATION (0x02) +#define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_HOST (0x00) +#define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_IOC (0x02) + +#define MPI_SCSIIO32_MSGFLGS_CMD_DETERMINES_DATA_DIR (0x04) +#define MPI_SCSIIO32_MSGFLGS_SGL_OFFSETS_CHAINS (0x08) +#define MPI_SCSIIO32_MSGFLGS_MULTICAST (0x10) +#define MPI_SCSIIO32_MSGFLGS_BIDIRECTIONAL (0x20) +#define MPI_SCSIIO32_MSGFLGS_LARGE_CDB (0x40) + +/* SCSI IO 32 Flags bits */ +#define MPI_SCSIIO32_FLAGS_FORM_MASK (0x03) +#define MPI_SCSIIO32_FLAGS_FORM_SCSIID (0x00) +#define MPI_SCSIIO32_FLAGS_FORM_WWID (0x01) + +/* SCSI IO 32 LUN fields */ +#define MPI_SCSIIO32_LUN_FIRST_LEVEL_ADDRESSING (0x0000FFFF) +#define MPI_SCSIIO32_LUN_SECOND_LEVEL_ADDRESSING (0xFFFF0000) +#define MPI_SCSIIO32_LUN_THIRD_LEVEL_ADDRESSING (0x0000FFFF) +#define MPI_SCSIIO32_LUN_FOURTH_LEVEL_ADDRESSING (0xFFFF0000) +#define MPI_SCSIIO32_LUN_LEVEL_1_WORD (0xFF00) +#define MPI_SCSIIO32_LUN_LEVEL_1_DWORD (0x0000FF00) + +/* SCSI IO 32 Control bits */ +#define MPI_SCSIIO32_CONTROL_DATADIRECTION_MASK (0x03000000) +#define MPI_SCSIIO32_CONTROL_NODATATRANSFER (0x00000000) +#define MPI_SCSIIO32_CONTROL_WRITE (0x01000000) +#define MPI_SCSIIO32_CONTROL_READ (0x02000000) +#define MPI_SCSIIO32_CONTROL_BIDIRECTIONAL (0x03000000) + +#define MPI_SCSIIO32_CONTROL_ADDCDBLEN_MASK (0xFC000000) +#define MPI_SCSIIO32_CONTROL_ADDCDBLEN_SHIFT (26) + +#define MPI_SCSIIO32_CONTROL_TASKATTRIBUTE_MASK (0x00000700) +#define MPI_SCSIIO32_CONTROL_SIMPLEQ (0x00000000) +#define MPI_SCSIIO32_CONTROL_HEADOFQ (0x00000100) +#define MPI_SCSIIO32_CONTROL_ORDEREDQ (0x00000200) +#define MPI_SCSIIO32_CONTROL_ACAQ (0x00000400) +#define MPI_SCSIIO32_CONTROL_UNTAGGED (0x00000500) +#define MPI_SCSIIO32_CONTROL_NO_DISCONNECT (0x00000700) + +#define MPI_SCSIIO32_CONTROL_TASKMANAGE_MASK (0x00FF0000) +#define MPI_SCSIIO32_CONTROL_OBSOLETE (0x00800000) +#define MPI_SCSIIO32_CONTROL_CLEAR_ACA_RSV (0x00400000) +#define MPI_SCSIIO32_CONTROL_TARGET_RESET (0x00200000) +#define MPI_SCSIIO32_CONTROL_LUN_RESET_RSV (0x00100000) +#define MPI_SCSIIO32_CONTROL_RESERVED (0x00080000) +#define MPI_SCSIIO32_CONTROL_CLR_TASK_SET_RSV (0x00040000) +#define MPI_SCSIIO32_CONTROL_ABORT_TASK_SET (0x00020000) +#define MPI_SCSIIO32_CONTROL_RESERVED2 (0x00010000) + +/* SCSI IO 32 EEDPFlags */ +#define MPI_SCSIIO32_EEDPFLAGS_MASK_OP (0x0007) +#define MPI_SCSIIO32_EEDPFLAGS_NOOP_OP (0x0000) +#define MPI_SCSIIO32_EEDPFLAGS_CHK_OP (0x0001) +#define MPI_SCSIIO32_EEDPFLAGS_STRIP_OP (0x0002) +#define MPI_SCSIIO32_EEDPFLAGS_CHKRM_OP (0x0003) +#define MPI_SCSIIO32_EEDPFLAGS_INSERT_OP (0x0004) +#define MPI_SCSIIO32_EEDPFLAGS_REPLACE_OP (0x0006) +#define MPI_SCSIIO32_EEDPFLAGS_CHKREGEN_OP (0x0007) + +#define MPI_SCSIIO32_EEDPFLAGS_PASS_REF_TAG (0x0008) +#define MPI_SCSIIO32_EEDPFLAGS_8_9THS_MODE (0x0010) + +#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_MASK (0x0700) +#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_GUARD (0x0100) +#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_REFTAG (0x0200) +#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_LBATAG (0x0400) +#define MPI_SCSIIO32_EEDPFLAGS_T10_CHK_SHIFT (8) + +#define MPI_SCSIIO32_EEDPFLAGS_INC_SEC_APPTAG (0x1000) +#define MPI_SCSIIO32_EEDPFLAGS_INC_PRI_APPTAG (0x2000) +#define MPI_SCSIIO32_EEDPFLAGS_INC_SEC_REFTAG (0x4000) +#define MPI_SCSIIO32_EEDPFLAGS_INC_PRI_REFTAG (0x8000) + + +/* SCSIIO32 IO reply structure */ +typedef struct _MSG_SCSIIO32_IO_REPLY +{ + U8 Port; /* 00h */ + U8 Reserved1; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U8 CDBLength; /* 04h */ + U8 SenseBufferLength; /* 05h */ + U8 Flags; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 SCSIStatus; /* 0Ch */ + U8 SCSIState; /* 0Dh */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 TransferCount; /* 14h */ + U32 SenseCount; /* 18h */ + U32 ResponseInfo; /* 1Ch */ + U16 TaskTag; /* 20h */ + U16 Reserved2; /* 22h */ + U32 BidirectionalTransferCount; /* 24h */ +} MSG_SCSIIO32_IO_REPLY, MPI_POINTER PTR_MSG_SCSIIO32_IO_REPLY, + SCSIIO32Reply_t, MPI_POINTER pSCSIIO32Reply_t; + + +/****************************************************************************/ /* SCSI Task Management messages */ /****************************************************************************/ @@ -310,10 +503,14 @@ typedef struct _MSG_SEP_REQUEST #define MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED (0x00000080) #define MPI_SEP_REQ_SLOTSTATUS_HOT_SPARE (0x00000100) #define MPI_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED (0x00000200) +#define MPI_SEP_REQ_SLOTSTATUS_REQ_CONSISTENCY_CHECK (0x00001000) +#define MPI_SEP_REQ_SLOTSTATUS_DISABLE (0x00002000) +#define MPI_SEP_REQ_SLOTSTATUS_REQ_RESERVED_DEVICE (0x00004000) #define MPI_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) #define MPI_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE (0x00040000) #define MPI_SEP_REQ_SLOTSTATUS_REQUEST_INSERT (0x00080000) #define MPI_SEP_REQ_SLOTSTATUS_DO_NOT_MOVE (0x00400000) +#define MPI_SEP_REQ_SLOTSTATUS_ACTIVE (0x00800000) #define MPI_SEP_REQ_SLOTSTATUS_B_ENABLE_BYPASS (0x04000000) #define MPI_SEP_REQ_SLOTSTATUS_A_ENABLE_BYPASS (0x08000000) #define MPI_SEP_REQ_SLOTSTATUS_DEV_OFF (0x10000000) @@ -352,11 +549,15 @@ typedef struct _MSG_SEP_REPLY #define MPI_SEP_REPLY_SLOTSTATUS_UNCONFIGURED (0x00000080) #define MPI_SEP_REPLY_SLOTSTATUS_HOT_SPARE (0x00000100) #define MPI_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED (0x00000200) +#define MPI_SEP_REPLY_SLOTSTATUS_CONSISTENCY_CHECK (0x00001000) +#define MPI_SEP_REPLY_SLOTSTATUS_DISABLE (0x00002000) +#define MPI_SEP_REPLY_SLOTSTATUS_RESERVED_DEVICE (0x00004000) #define MPI_SEP_REPLY_SLOTSTATUS_REPORT (0x00010000) #define MPI_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) #define MPI_SEP_REPLY_SLOTSTATUS_REMOVE_READY (0x00040000) #define MPI_SEP_REPLY_SLOTSTATUS_INSERT_READY (0x00080000) #define MPI_SEP_REPLY_SLOTSTATUS_DO_NOT_REMOVE (0x00400000) +#define MPI_SEP_REPLY_SLOTSTATUS_ACTIVE (0x00800000) #define MPI_SEP_REPLY_SLOTSTATUS_B_BYPASS_ENABLED (0x01000000) #define MPI_SEP_REPLY_SLOTSTATUS_A_BYPASS_ENABLED (0x02000000) #define MPI_SEP_REPLY_SLOTSTATUS_B_ENABLE_BYPASS (0x04000000) diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h index f91eb4efe8cc..93b70e2b4266 100644 --- a/drivers/message/fusion/lsi/mpi_ioc.h +++ b/drivers/message/fusion/lsi/mpi_ioc.h @@ -6,7 +6,7 @@ * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages * Creation Date: August 11, 2000 * - * mpi_ioc.h Version: 01.05.08 + * mpi_ioc.h Version: 01.05.09 * * Version History * --------------- @@ -81,6 +81,8 @@ * Reply and IOC Init Request. * 03-11-05 01.05.08 Added family code for 1068E family. * Removed IOCFacts Reply EEDP Capability bit. + * 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits. + * Added Max SATA Targets to SAS Discovery Error event. * -------------------------------------------------------------------------- */ @@ -261,7 +263,11 @@ typedef struct _MSG_IOC_FACTS_REPLY #define MPI_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008) #define MPI_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010) #define MPI_IOCFACTS_CAPABILITY_EXTENDED_BUFFER (0x00000020) - +#define MPI_IOCFACTS_CAPABILITY_EEDP (0x00000040) +#define MPI_IOCFACTS_CAPABILITY_BIDIRECTIONAL (0x00000080) +#define MPI_IOCFACTS_CAPABILITY_MULTICAST (0x00000100) +#define MPI_IOCFACTS_CAPABILITY_SCSIIO32 (0x00000200) +#define MPI_IOCFACTS_CAPABILITY_NO_SCSIIO16 (0x00000400) /***************************************************************************** @@ -677,6 +683,7 @@ typedef struct _EVENT_DATA_DISCOVERY_ERROR #define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_SUBTRACTIVE (0x00000200) #define MPI_EVENT_DSCVRY_ERR_DS_TABLE_TO_TABLE (0x00000400) #define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_PATHS (0x00000800) +#define MPI_EVENT_DSCVRY_ERR_DS_MAX_SATA_TARGETS (0x00001000) /***************************************************************************** diff --git a/drivers/message/fusion/lsi/mpi_targ.h b/drivers/message/fusion/lsi/mpi_targ.h index 623901fd82be..3f462859ceea 100644 --- a/drivers/message/fusion/lsi/mpi_targ.h +++ b/drivers/message/fusion/lsi/mpi_targ.h @@ -6,7 +6,7 @@ * Title: MPI Target mode messages and structures * Creation Date: June 22, 2000 * - * mpi_targ.h Version: 01.05.04 + * mpi_targ.h Version: 01.05.05 * * Version History * --------------- @@ -53,6 +53,7 @@ * 10-05-04 01.05.02 MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY added. * 02-22-05 01.05.03 Changed a comment. * 03-11-05 01.05.04 Removed TargetAssistExtended Request. + * 06-24-05 01.05.05 Added TargetAssistExtended structures and defines. * -------------------------------------------------------------------------- */ @@ -371,6 +372,77 @@ typedef struct _MSG_TARGET_ERROR_REPLY /****************************************************************************/ +/* Target Assist Extended Request */ +/****************************************************************************/ + +typedef struct _MSG_TARGET_ASSIST_EXT_REQUEST +{ + U8 StatusCode; /* 00h */ + U8 TargetAssistFlags; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 QueueTag; /* 04h */ + U8 Reserved1; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 ReplyWord; /* 0Ch */ + U8 LUN[8]; /* 10h */ + U32 RelativeOffset; /* 18h */ + U32 Reserved2; /* 1Ch */ + U32 Reserved3; /* 20h */ + U32 PrimaryReferenceTag; /* 24h */ + U16 PrimaryApplicationTag; /* 28h */ + U16 PrimaryApplicationTagMask; /* 2Ah */ + U32 Reserved4; /* 2Ch */ + U32 DataLength; /* 30h */ + U32 BidirectionalDataLength; /* 34h */ + U32 SecondaryReferenceTag; /* 38h */ + U16 SecondaryApplicationTag; /* 3Ch */ + U16 Reserved5; /* 3Eh */ + U16 EEDPFlags; /* 40h */ + U16 ApplicationTagTranslationMask; /* 42h */ + U32 EEDPBlockSize; /* 44h */ + U8 SGLOffset0; /* 48h */ + U8 SGLOffset1; /* 49h */ + U8 SGLOffset2; /* 4Ah */ + U8 SGLOffset3; /* 4Bh */ + U32 Reserved6; /* 4Ch */ + SGE_IO_UNION SGL[1]; /* 50h */ +} MSG_TARGET_ASSIST_EXT_REQUEST, MPI_POINTER PTR_MSG_TARGET_ASSIST_EXT_REQUEST, + TargetAssistExtRequest_t, MPI_POINTER pTargetAssistExtRequest_t; + +/* see the defines after MSG_TARGET_ASSIST_REQUEST for TargetAssistFlags */ + +/* defines for the MsgFlags field */ +#define TARGET_ASSIST_EXT_MSGFLAGS_BIDIRECTIONAL (0x20) +#define TARGET_ASSIST_EXT_MSGFLAGS_MULTICAST (0x10) +#define TARGET_ASSIST_EXT_MSGFLAGS_SGL_OFFSET_CHAINS (0x08) + +/* defines for the EEDPFlags field */ +#define TARGET_ASSIST_EXT_EEDP_MASK_OP (0x0007) +#define TARGET_ASSIST_EXT_EEDP_NOOP_OP (0x0000) +#define TARGET_ASSIST_EXT_EEDP_CHK_OP (0x0001) +#define TARGET_ASSIST_EXT_EEDP_STRIP_OP (0x0002) +#define TARGET_ASSIST_EXT_EEDP_CHKRM_OP (0x0003) +#define TARGET_ASSIST_EXT_EEDP_INSERT_OP (0x0004) +#define TARGET_ASSIST_EXT_EEDP_REPLACE_OP (0x0006) +#define TARGET_ASSIST_EXT_EEDP_CHKREGEN_OP (0x0007) + +#define TARGET_ASSIST_EXT_EEDP_PASS_REF_TAG (0x0008) + +#define TARGET_ASSIST_EXT_EEDP_T10_CHK_MASK (0x0700) +#define TARGET_ASSIST_EXT_EEDP_T10_CHK_GUARD (0x0100) +#define TARGET_ASSIST_EXT_EEDP_T10_CHK_APPTAG (0x0200) +#define TARGET_ASSIST_EXT_EEDP_T10_CHK_REFTAG (0x0400) +#define TARGET_ASSIST_EXT_EEDP_T10_CHK_SHIFT (8) + +#define TARGET_ASSIST_EXT_EEDP_INC_SEC_APPTAG (0x1000) +#define TARGET_ASSIST_EXT_EEDP_INC_PRI_APPTAG (0x2000) +#define TARGET_ASSIST_EXT_EEDP_INC_SEC_REFTAG (0x4000) +#define TARGET_ASSIST_EXT_EEDP_INC_PRI_REFTAG (0x8000) + + +/****************************************************************************/ /* Target Status Send Request */ /****************************************************************************/ diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index ffbe6f4720e1..790a2932ded9 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -135,13 +135,12 @@ static void mpt_adapter_dispose(MPT_ADAPTER *ioc); static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc); static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag); -//static u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked); static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason); static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag); static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag); static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag); static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag); -static int mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag); +static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag); static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag); static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag); static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag); @@ -152,6 +151,7 @@ static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag); static int GetLanConfigPages(MPT_ADAPTER *ioc); static int GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); static int GetIoUnitPage2(MPT_ADAPTER *ioc); +int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum); static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum); static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc); @@ -159,6 +159,8 @@ static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc); static void mpt_timer_expired(unsigned long data); static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch); static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp); +static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag); +static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init); #ifdef CONFIG_PROC_FS static int procmpt_summary_read(char *buf, char **start, off_t offset, @@ -175,6 +177,7 @@ static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t * static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info); +static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); /* module entry point */ static int __init fusion_init (void); @@ -206,6 +209,144 @@ pci_enable_io_access(struct pci_dev *pdev) pci_write_config_word(pdev, PCI_COMMAND, command_reg); } +/* + * Process turbo (context) reply... + */ +static void +mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa) +{ + MPT_FRAME_HDR *mf = NULL; + MPT_FRAME_HDR *mr = NULL; + int req_idx = 0; + int cb_idx; + + dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n", + ioc->name, pa)); + + switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) { + case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT: + req_idx = pa & 0x0000FFFF; + cb_idx = (pa & 0x00FF0000) >> 16; + mf = MPT_INDEX_2_MFPTR(ioc, req_idx); + break; + case MPI_CONTEXT_REPLY_TYPE_LAN: + cb_idx = mpt_lan_index; + /* + * Blind set of mf to NULL here was fatal + * after lan_reply says "freeme" + * Fix sort of combined with an optimization here; + * added explicit check for case where lan_reply + * was just returning 1 and doing nothing else. + * For this case skip the callback, but set up + * proper mf value first here:-) + */ + if ((pa & 0x58000000) == 0x58000000) { + req_idx = pa & 0x0000FFFF; + mf = MPT_INDEX_2_MFPTR(ioc, req_idx); + mpt_free_msg_frame(ioc, mf); + mb(); + return; + break; + } + mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); + break; + case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET: + cb_idx = mpt_stm_index; + mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); + break; + default: + cb_idx = 0; + BUG(); + } + + /* Check for (valid) IO callback! */ + if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS || + MptCallbacks[cb_idx] == NULL) { + printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n", + __FUNCTION__, ioc->name, cb_idx); + goto out; + } + + if (MptCallbacks[cb_idx](ioc, mf, mr)) + mpt_free_msg_frame(ioc, mf); + out: + mb(); +} + +static void +mpt_reply(MPT_ADAPTER *ioc, u32 pa) +{ + MPT_FRAME_HDR *mf; + MPT_FRAME_HDR *mr; + int req_idx; + int cb_idx; + int freeme; + + u32 reply_dma_low; + u16 ioc_stat; + + /* non-TURBO reply! Hmmm, something may be up... + * Newest turbo reply mechanism; get address + * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)! + */ + + /* Map DMA address of reply header to cpu address. + * pa is 32 bits - but the dma address may be 32 or 64 bits + * get offset based only only the low addresses + */ + + reply_dma_low = (pa <<= 1); + mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames + + (reply_dma_low - ioc->reply_frames_low_dma)); + + req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx); + cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx; + mf = MPT_INDEX_2_MFPTR(ioc, req_idx); + + dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n", + ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function)); + DBG_DUMP_REPLY_FRAME(mr) + + /* Check/log IOC log info + */ + ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus); + if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { + u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo); + if (ioc->bus_type == FC) + mpt_fc_log_info(ioc, log_info); + else if (ioc->bus_type == SCSI) + mpt_sp_log_info(ioc, log_info); + else if (ioc->bus_type == SAS) + mpt_sas_log_info(ioc, log_info); + } + if (ioc_stat & MPI_IOCSTATUS_MASK) { + if (ioc->bus_type == SCSI && + cb_idx != mpt_stm_index && + cb_idx != mpt_lan_index) + mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf); + } + + + /* Check for (valid) IO callback! */ + if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS || + MptCallbacks[cb_idx] == NULL) { + printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n", + __FUNCTION__, ioc->name, cb_idx); + freeme = 0; + goto out; + } + + freeme = MptCallbacks[cb_idx](ioc, mf, mr); + + out: + /* Flush (non-TURBO) reply with a WRITE! */ + CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa); + + if (freeme) + mpt_free_msg_frame(ioc, mf); + mb(); +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mpt_interrupt - MPT adapter (IOC) specific interrupt handler. @@ -218,8 +359,7 @@ pci_enable_io_access(struct pci_dev *pdev) * (also referred to as a IO Controller or IOC). * This routine must clear the interrupt from the adapter and does * so by reading the reply FIFO. Multiple replies may be processed - * per single call to this routine; up to MPT_MAX_REPLIES_PER_ISR - * which is currently set to 32 in mptbase.h. + * per single call to this routine. * * This routine handles register-level access of the adapter but * dispatches (calls) a protocol-specific callback routine to handle @@ -228,164 +368,21 @@ pci_enable_io_access(struct pci_dev *pdev) static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r) { - MPT_ADAPTER *ioc; - MPT_FRAME_HDR *mf; - MPT_FRAME_HDR *mr; - u32 pa; - int req_idx; - int cb_idx; - int type; - int freeme; - - ioc = (MPT_ADAPTER *)bus_id; + MPT_ADAPTER *ioc = bus_id; + u32 pa; /* * Drain the reply FIFO! - * - * NOTES: I've seen up to 10 replies processed in this loop, so far... - * Update: I've seen up to 9182 replies processed in this loop! ?? - * Update: Limit ourselves to processing max of N replies - * (bottom of loop). */ while (1) { - - if ((pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo)) == 0xFFFFFFFF) + pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo); + if (pa == 0xFFFFFFFF) return IRQ_HANDLED; - - cb_idx = 0; - freeme = 0; - - /* - * Check for non-TURBO reply! - */ - if (pa & MPI_ADDRESS_REPLY_A_BIT) { - u32 reply_dma_low; - u16 ioc_stat; - - /* non-TURBO reply! Hmmm, something may be up... - * Newest turbo reply mechanism; get address - * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)! - */ - - /* Map DMA address of reply header to cpu address. - * pa is 32 bits - but the dma address may be 32 or 64 bits - * get offset based only only the low addresses - */ - reply_dma_low = (pa = (pa << 1)); - mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames + - (reply_dma_low - ioc->reply_frames_low_dma)); - - req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx); - cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx; - mf = MPT_INDEX_2_MFPTR(ioc, req_idx); - - dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x\n", - ioc->name, mr, req_idx)); - DBG_DUMP_REPLY_FRAME(mr) - - /* Check/log IOC log info - */ - ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus); - if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { - u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo); - if (ioc->bus_type == FC) - mpt_fc_log_info(ioc, log_info); - else if (ioc->bus_type == SCSI) - mpt_sp_log_info(ioc, log_info); - } - if (ioc_stat & MPI_IOCSTATUS_MASK) { - if (ioc->bus_type == SCSI) - mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf); - } - } else { - /* - * Process turbo (context) reply... - */ - dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n", ioc->name, pa)); - type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT); - if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) { - cb_idx = mpt_stm_index; - mf = NULL; - mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); - } else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) { - cb_idx = mpt_lan_index; - /* Blind set of mf to NULL here was fatal - * after lan_reply says "freeme" - * Fix sort of combined with an optimization here; - * added explicit check for case where lan_reply - * was just returning 1 and doing nothing else. - * For this case skip the callback, but set up - * proper mf value first here:-) - */ - if ((pa & 0x58000000) == 0x58000000) { - req_idx = pa & 0x0000FFFF; - mf = MPT_INDEX_2_MFPTR(ioc, req_idx); - freeme = 1; - /* - * IMPORTANT! Invalidate the callback! - */ - cb_idx = 0; - } else { - mf = NULL; - } - mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); - } else { - req_idx = pa & 0x0000FFFF; - cb_idx = (pa & 0x00FF0000) >> 16; - mf = MPT_INDEX_2_MFPTR(ioc, req_idx); - mr = NULL; - } - pa = 0; /* No reply flush! */ - } - -#ifdef MPT_DEBUG_IRQ - if (ioc->bus_type == SCSI) { - /* Verify mf, mr are reasonable. - */ - if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth)) - || (mf < ioc->req_frames)) ) { - printk(MYIOC_s_WARN_FMT - "mpt_interrupt: Invalid mf (%p) req_idx (%d)!\n", ioc->name, (void *)mf, req_idx); - cb_idx = 0; - pa = 0; - freeme = 0; - } - if ((pa) && (mr) && ((mr >= MPT_INDEX_2_RFPTR(ioc, ioc->req_depth)) - || (mr < ioc->reply_frames)) ) { - printk(MYIOC_s_WARN_FMT - "mpt_interrupt: Invalid rf (%p)!\n", ioc->name, (void *)mr); - cb_idx = 0; - pa = 0; - freeme = 0; - } - if (cb_idx > (MPT_MAX_PROTOCOL_DRIVERS-1)) { - printk(MYIOC_s_WARN_FMT - "mpt_interrupt: Invalid cb_idx (%d)!\n", ioc->name, cb_idx); - cb_idx = 0; - pa = 0; - freeme = 0; - } - } -#endif - - /* Check for (valid) IO callback! */ - if (cb_idx) { - /* Do the callback! */ - freeme = (*(MptCallbacks[cb_idx]))(ioc, mf, mr); - } - - if (pa) { - /* Flush (non-TURBO) reply with a WRITE! */ - CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa); - } - - if (freeme) { - /* Put Request back on FreeQ! */ - mpt_free_msg_frame(ioc, mf); - } - - mb(); - } /* drain reply FIFO */ + else if (pa & MPI_ADDRESS_REPLY_A_BIT) + mpt_reply(ioc, pa); + else + mpt_turbo_reply(ioc, pa); + } return IRQ_HANDLED; } @@ -399,7 +396,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r) * @mf: Pointer to original MPT request frame * @reply: Pointer to MPT reply frame (NULL if TurboReply) * - * Returns 1 indicating original alloc'd request frame ptr + * Returns 1 indicating original alloc'd request frame ptr * should be freed, or 0 if it shouldn't. */ static int @@ -408,28 +405,17 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) int freereq = 1; u8 func; - dprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name)); - - if ((mf == NULL) || - (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) { - printk(MYIOC_s_ERR_FMT "NULL or BAD request frame ptr! (=%p)\n", - ioc->name, (void *)mf); - return 1; - } - - if (reply == NULL) { - dprintk((MYIOC_s_ERR_FMT "Unexpected NULL Event (turbo?) reply!\n", - ioc->name)); - return 1; - } + dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name)); +#if defined(MPT_DEBUG_MSG_FRAME) if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) { dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf)); DBG_DUMP_REQUEST_FRAME_HDR(mf) } +#endif func = reply->u.hdr.Function; - dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n", + dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n", ioc->name, func)); if (func == MPI_FUNCTION_EVENT_NOTIFICATION) { @@ -448,8 +434,14 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) * Hmmm... It seems that EventNotificationReply is an exception * to the rule of one reply per request. */ - if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) + if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) { freereq = 0; + devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n", + ioc->name, pEvReply)); + } else { + devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n", + ioc->name, pEvReply)); + } #ifdef CONFIG_PROC_FS // LogEvent(ioc, pEvReply); @@ -491,10 +483,21 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) pCfg->status = status; if (status == MPI_IOCSTATUS_SUCCESS) { - pCfg->hdr->PageVersion = pReply->Header.PageVersion; - pCfg->hdr->PageLength = pReply->Header.PageLength; - pCfg->hdr->PageNumber = pReply->Header.PageNumber; - pCfg->hdr->PageType = pReply->Header.PageType; + if ((pReply->Header.PageType & + MPI_CONFIG_PAGETYPE_MASK) == + MPI_CONFIG_PAGETYPE_EXTENDED) { + pCfg->cfghdr.ehdr->ExtPageLength = + le16_to_cpu(pReply->ExtPageLength); + pCfg->cfghdr.ehdr->ExtPageType = + pReply->ExtPageType; + } + pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion; + + /* If this is a regular header, save PageLength. */ + /* LMP Do this better so not using a reserved field! */ + pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength; + pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber; + pCfg->cfghdr.hdr->PageType = pReply->Header.PageType; } } @@ -504,6 +507,14 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) pCfg->wait_done = 1; wake_up(&mpt_waitq); } + } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) { + /* we should be always getting a reply frame */ + memcpy(ioc->persist_reply_frame, reply, + min(MPT_DEFAULT_FRAME_SIZE, + 4*reply->u.reply.MsgLength)); + del_timer(&ioc->persist_timer); + ioc->persist_wait_done = 1; + wake_up(&mpt_waitq); } else { printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n", ioc->name, func); @@ -705,7 +716,7 @@ mpt_device_driver_deregister(int cb_idx) if (dd_cbfunc->remove) dd_cbfunc->remove(ioc->pcidev); } - + MptDeviceDriverHandlers[cb_idx] = NULL; } @@ -745,6 +756,7 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc) mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR, u.frame.linkage.list); list_del(&mf->u.frame.linkage.list); + mf->u.frame.linkage.arg1 = 0; mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ req_offset = (u8 *)mf - (u8 *)ioc->req_frames; /* u16! */ @@ -818,7 +830,7 @@ mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) } #endif - mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx]; + mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx]; dsgprintk((MYIOC_s_INFO_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx])); CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr); } @@ -840,6 +852,7 @@ mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) /* Put Request back on FreeQ! */ spin_lock_irqsave(&ioc->FreeQlock, flags); + mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */ list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ); #ifdef MFCNT ioc->mfcnt--; @@ -920,7 +933,7 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, /* Make sure there are no doorbells */ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - + CHIPREG_WRITE32(&ioc->chip->Doorbell, ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) | ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT))); @@ -935,14 +948,14 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, return -5; dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n", - ioc->name, ii)); + ioc->name, ii)); CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) { return -2; } - + /* Send request via doorbell handshake */ req_as_bytes = (u8 *) req; for (ii = 0; ii < reqBytes/4; ii++) { @@ -966,12 +979,123 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, /* Make sure there are no doorbells */ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - + return r; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** + * mpt_host_page_access_control - provides mechanism for the host + * driver to control the IOC's Host Page Buffer access. + * @ioc: Pointer to MPT adapter structure + * @access_control_value: define bits below + * + * Access Control Value - bits[15:12] + * 0h Reserved + * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS } + * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS } + * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER } + * + * Returns 0 for success, non-zero for failure. + */ + +static int +mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag) +{ + int r = 0; + + /* return if in use */ + if (CHIPREG_READ32(&ioc->chip->Doorbell) + & MPI_DOORBELL_ACTIVE) + return -1; + + CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); + + CHIPREG_WRITE32(&ioc->chip->Doorbell, + ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL + <<MPI_DOORBELL_FUNCTION_SHIFT) | + (access_control_value<<12))); + + /* Wait for IOC to clear Doorbell Status bit */ + if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) { + return -2; + }else + return 0; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** + * mpt_host_page_alloc - allocate system memory for the fw + * If we already allocated memory in past, then resend the same pointer. + * ioc@: Pointer to pointer to IOC adapter + * ioc_init@: Pointer to ioc init config page + * + * Returns 0 for success, non-zero for failure. + */ +static int +mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init) +{ + char *psge; + int flags_length; + u32 host_page_buffer_sz=0; + + if(!ioc->HostPageBuffer) { + + host_page_buffer_sz = + le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF; + + if(!host_page_buffer_sz) + return 0; /* fw doesn't need any host buffers */ + + /* spin till we get enough memory */ + while(host_page_buffer_sz > 0) { + + if((ioc->HostPageBuffer = pci_alloc_consistent( + ioc->pcidev, + host_page_buffer_sz, + &ioc->HostPageBuffer_dma)) != NULL) { + + dinitprintk((MYIOC_s_INFO_FMT + "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n", + ioc->name, + ioc->HostPageBuffer, + ioc->HostPageBuffer_dma, + host_page_buffer_sz)); + ioc->alloc_total += host_page_buffer_sz; + ioc->HostPageBuffer_sz = host_page_buffer_sz; + break; + } + + host_page_buffer_sz -= (4*1024); + } + } + + if(!ioc->HostPageBuffer) { + printk(MYIOC_s_ERR_FMT + "Failed to alloc memory for host_page_buffer!\n", + ioc->name); + return -999; + } + + psge = (char *)&ioc_init->HostPageBufferSGE; + flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT | + MPI_SGE_FLAGS_SYSTEM_ADDRESS | + MPI_SGE_FLAGS_32_BIT_ADDRESSING | + MPI_SGE_FLAGS_HOST_TO_IOC | + MPI_SGE_FLAGS_END_OF_BUFFER; + if (sizeof(dma_addr_t) == sizeof(u64)) { + flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING; + } + flags_length = flags_length << MPI_SGE_FLAGS_SHIFT; + flags_length |= ioc->HostPageBuffer_sz; + mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma); + ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE; + +return 0; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** * mpt_verify_adapter - Given a unique IOC identifier, set pointer to * the associated MPT adapter structure. * @iocid: IOC unique identifier (integer) @@ -988,9 +1112,9 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) if (ioc->id == iocid) { *iocpp =ioc; return iocid; - } + } } - + *iocpp = NULL; return -1; } @@ -1032,9 +1156,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) if (pci_enable_device(pdev)) return r; - + dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n")); - + if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { dprintk((KERN_INFO MYNAM ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n")); @@ -1059,7 +1183,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) ioc->alloc_total = sizeof(MPT_ADAPTER); ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */ ioc->reply_sz = MPT_REPLY_FRAME_SIZE; - + ioc->pcidev = pdev; ioc->diagPending = 0; spin_lock_init(&ioc->diagLock); @@ -1079,7 +1203,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) /* Initilize SCSI Config Data structure */ - memset(&ioc->spi_data, 0, sizeof(ScsiCfgData)); + memset(&ioc->spi_data, 0, sizeof(SpiCfgData)); /* Initialize the running configQ head. */ @@ -1088,7 +1212,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) /* Find lookup slot. */ INIT_LIST_HEAD(&ioc->list); ioc->id = mpt_ids++; - + mem_phys = msize = 0; port = psize = 0; for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) { @@ -1143,7 +1267,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) ioc->prod_name = "LSIFC909"; ioc->bus_type = FC; } - if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) { + else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) { ioc->prod_name = "LSIFC929"; ioc->bus_type = FC; } @@ -1208,6 +1332,33 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) ioc->prod_name = "LSI53C1035"; ioc->bus_type = SCSI; } + else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) { + ioc->prod_name = "LSISAS1064"; + ioc->bus_type = SAS; + ioc->errata_flag_1064 = 1; + } + else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066) { + ioc->prod_name = "LSISAS1066"; + ioc->bus_type = SAS; + ioc->errata_flag_1064 = 1; + } + else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) { + ioc->prod_name = "LSISAS1068"; + ioc->bus_type = SAS; + ioc->errata_flag_1064 = 1; + } + else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) { + ioc->prod_name = "LSISAS1064E"; + ioc->bus_type = SAS; + } + else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) { + ioc->prod_name = "LSISAS1066E"; + ioc->bus_type = SAS; + } + else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) { + ioc->prod_name = "LSISAS1068E"; + ioc->bus_type = SAS; + } if (ioc->errata_flag_1064) pci_disable_io_access(pdev); @@ -1322,7 +1473,7 @@ mpt_detach(struct pci_dev *pdev) remove_proc_entry(pname, NULL); sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name); remove_proc_entry(pname, NULL); - + /* call per device driver remove entry point */ for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) { if(MptDeviceDriverHandlers[ii] && @@ -1330,7 +1481,7 @@ mpt_detach(struct pci_dev *pdev) MptDeviceDriverHandlers[ii]->remove(pdev); } } - + /* Disable interrupts! */ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); @@ -1403,7 +1554,7 @@ mpt_resume(struct pci_dev *pdev) u32 device_state = pdev->current_state; int recovery_state; int ii; - + printk(MYIOC_s_INFO_FMT "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n", ioc->name, pdev, pci_name(pdev), device_state); @@ -1534,7 +1685,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0) break; } - + if (ii == 5) { dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc)); @@ -1542,7 +1693,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { MptDisplayIocCapabilities(ioc); } - + if (alt_ioc_ready) { if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) { dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc)); @@ -1599,8 +1750,23 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) */ if (ret == 0) { rc = mpt_do_upload(ioc, sleepFlag); - if (rc != 0) + if (rc == 0) { + if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) { + /* + * Maintain only one pointer to FW memory + * so there will not be two attempt to + * downloadboot onboard dual function + * chips (mpt_adapter_disable, + * mpt_diag_reset) + */ + ioc->cached_fw = NULL; + ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n", + ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw)); + } + } else { printk(KERN_WARNING MYNAM ": firmware upload failure!\n"); + ret = -5; + } } } } @@ -1613,7 +1779,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if (reset_alt_ioc_active && ioc->alt_ioc) { /* (re)Enable alt-IOC! (reply interrupt) */ - dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", + dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", ioc->alt_ioc->name)); CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM)); ioc->alt_ioc->active = 1; @@ -1635,7 +1801,22 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) * and we try GetLanConfigPages again... */ if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { - if (ioc->bus_type == FC) { + if (ioc->bus_type == SAS) { + + /* clear persistency table */ + if(ioc->facts.IOCExceptions & + MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) { + ret = mptbase_sas_persist_operation(ioc, + MPI_SAS_OP_CLEAR_NOT_PRESENT); + if(ret != 0) + return -1; + } + + /* Find IM volumes + */ + mpt_findImVolumes(ioc); + + } else if (ioc->bus_type == FC) { /* * Pre-fetch FC port WWN and stuff... * (FCPortPage0_t stuff) @@ -1670,7 +1851,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) /* Find IM volumes */ - if (ioc->facts.MsgVersion >= 0x0102) + if (ioc->facts.MsgVersion >= MPI_VERSION_01_02) mpt_findImVolumes(ioc); /* Check, and possibly reset, the coalescing value @@ -1700,7 +1881,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) } if (alt_ioc_ready && MptResetHandlers[ii]) { - dprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n", + drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n", ioc->name, ioc->alt_ioc->name, ii)); rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET); handlers++; @@ -1733,8 +1914,8 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev) dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x," " searching for devfn match on %x or %x\n", - ioc->name, pci_name(pdev), pdev->devfn, - func-1, func+1)); + ioc->name, pci_name(pdev), pdev->bus->number, + pdev->devfn, func-1, func+1)); peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1)); if (!peer) { @@ -1778,7 +1959,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) if (ioc->cached_fw != NULL) { ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n")); - if ((ret = mpt_downloadboot(ioc, NO_SLEEP)) < 0) { + if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) { printk(KERN_WARNING MYNAM ": firmware downloadboot failure (%d)!\n", ret); } @@ -1826,9 +2007,9 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) } kfree(ioc->spi_data.nvram); - kfree(ioc->spi_data.pIocPg3); + kfree(ioc->raid_data.pIocPg3); ioc->spi_data.nvram = NULL; - ioc->spi_data.pIocPg3 = NULL; + ioc->raid_data.pIocPg3 = NULL; if (ioc->spi_data.pIocPg4 != NULL) { sz = ioc->spi_data.IocPg4Sz; @@ -1847,6 +2028,23 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) kfree(ioc->ChainToChain); ioc->ChainToChain = NULL; + + if (ioc->HostPageBuffer != NULL) { + if((ret = mpt_host_page_access_control(ioc, + MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) { + printk(KERN_ERR MYNAM + ": %s: host page buffers free failed (%d)!\n", + __FUNCTION__, ret); + } + dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n", + ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz)); + pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz, + ioc->HostPageBuffer, + ioc->HostPageBuffer_dma); + ioc->HostPageBuffer = NULL; + ioc->HostPageBuffer_sz = 0; + ioc->alloc_total -= ioc->HostPageBuffer_sz; + } } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1861,36 +2059,39 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) static void mpt_adapter_dispose(MPT_ADAPTER *ioc) { - if (ioc != NULL) { - int sz_first, sz_last; + int sz_first, sz_last; - sz_first = ioc->alloc_total; + if (ioc == NULL) + return; - mpt_adapter_disable(ioc); + sz_first = ioc->alloc_total; - if (ioc->pci_irq != -1) { - free_irq(ioc->pci_irq, ioc); - ioc->pci_irq = -1; - } + mpt_adapter_disable(ioc); - if (ioc->memmap != NULL) - iounmap(ioc->memmap); + if (ioc->pci_irq != -1) { + free_irq(ioc->pci_irq, ioc); + ioc->pci_irq = -1; + } + + if (ioc->memmap != NULL) { + iounmap(ioc->memmap); + ioc->memmap = NULL; + } #if defined(CONFIG_MTRR) && 0 - if (ioc->mtrr_reg > 0) { - mtrr_del(ioc->mtrr_reg, 0, 0); - dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name)); - } + if (ioc->mtrr_reg > 0) { + mtrr_del(ioc->mtrr_reg, 0, 0); + dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name)); + } #endif - /* Zap the adapter lookup ptr! */ - list_del(&ioc->list); + /* Zap the adapter lookup ptr! */ + list_del(&ioc->list); - sz_last = ioc->alloc_total; - dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n", - ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first)); - kfree(ioc); - } + sz_last = ioc->alloc_total; + dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n", + ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first)); + kfree(ioc); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1977,7 +2178,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) } /* Is it already READY? */ - if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) + if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) return 0; /* @@ -1995,7 +2196,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) * Hmmm... Did it get left operational? */ if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) { - dinitprintk((MYIOC_s_WARN_FMT "IOC operational unexpected\n", + dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n", ioc->name)); /* Check WhoInit. @@ -2004,8 +2205,8 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) * Else, fall through to KickStart case */ whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT; - dprintk((KERN_WARNING MYNAM - ": whoinit 0x%x\n statefault %d force %d\n", + dinitprintk((KERN_INFO MYNAM + ": whoinit 0x%x statefault %d force %d\n", whoinit, statefault, force)); if (whoinit == MPI_WHOINIT_PCI_PEER) return -4; @@ -2026,7 +2227,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) * Loop here waiting for IOC to come READY. */ ii = 0; - cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */ + cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */ while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) { if (ioc_state == MPI_IOC_STATE_OPERATIONAL) { @@ -2140,8 +2341,8 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) get_facts.Function = MPI_FUNCTION_IOC_FACTS; /* Assert: All other get_facts fields are zero! */ - dinitprintk((MYIOC_s_INFO_FMT - "Sending get IocFacts request req_sz=%d reply_sz=%d\n", + dinitprintk((MYIOC_s_INFO_FMT + "Sending get IocFacts request req_sz=%d reply_sz=%d\n", ioc->name, req_sz, reply_sz)); /* No non-zero fields in the get_facts request are greater than @@ -2174,7 +2375,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions); facts->IOCStatus = le16_to_cpu(facts->IOCStatus); facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo); - status = facts->IOCStatus & MPI_IOCSTATUS_MASK; + status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK; /* CHECKME! IOCStatus, IOCLogInfo */ facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth); @@ -2204,6 +2405,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) le32_to_cpu(facts->CurrentSenseBufferHighAddr); facts->CurReplyFrameSize = le16_to_cpu(facts->CurReplyFrameSize); + facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities); /* * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx @@ -2221,7 +2423,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) if ( sz & 0x02 ) sz += 2; facts->FWImageSize = sz; - + if (!facts->RequestFrameSize) { /* Something is wrong! */ printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n", @@ -2240,7 +2442,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) ioc->NBShiftFactor = shiftFactor; dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n", ioc->name, vv, shiftFactor, r)); - + if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { /* * Set values for this IOC's request & reply frame sizes, @@ -2261,7 +2463,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) return r; } } else { - printk(MYIOC_s_ERR_FMT + printk(MYIOC_s_ERR_FMT "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n", ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32))); @@ -2375,13 +2577,25 @@ 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 == FC) + 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; - + dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n", + ioc->name, ioc->facts.MsgVersion)); + if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) { + // set MsgVersion and HeaderVersion host driver was built with + ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION); + ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION); + + if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) { + ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE; + } else if(mpt_host_page_alloc(ioc, &ioc_init)) + return -99; + } ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */ if (sizeof(dma_addr_t) == sizeof(u64)) { @@ -2395,17 +2609,21 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) ioc_init.HostMfaHighAddr = cpu_to_le32(0); ioc_init.SenseBufferHighAddr = cpu_to_le32(0); } - + ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr; ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr; + ioc->facts.MaxDevices = ioc_init.MaxDevices; + ioc->facts.MaxBuses = ioc_init.MaxBuses; dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n", ioc->name, &ioc_init)); r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init, sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag); - if (r != 0) + if (r != 0) { + printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r); return r; + } /* No need to byte swap the multibyte fields in the reply * since we don't even look at it's contents. @@ -2413,9 +2631,11 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n", ioc->name, &ioc_init)); - - if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) + + if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) { + printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r); return r; + } /* YIKES! SUPER IMPORTANT!!! * Poll IocState until _OPERATIONAL while IOC is doing @@ -2440,7 +2660,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) state = mpt_GetIocState(ioc, 1); count++; } - dhsprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n", + dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n", ioc->name, count)); return r; @@ -2462,7 +2682,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) { PortEnable_t port_enable; MPIDefaultReply_t reply_buf; - int ii; + int rc; int req_sz; int reply_sz; @@ -2484,22 +2704,15 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) /* RAID FW may take a long time to enable */ - if (ioc->bus_type == FC) { - ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, - reply_sz, (u16*)&reply_buf, 65 /*seconds*/, sleepFlag); - } else { - ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, + if ( (ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) + > MPI_FW_HEADER_PID_PROD_TARGET_SCSI ) { + rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag); + } else { + rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, + reply_sz, (u16*)&reply_buf, 30 /*seconds*/, sleepFlag); } - - if (ii != 0) - return ii; - - /* We do not even look at the reply, so we need not - * swap the multi-byte fields. - */ - - return 0; + return rc; } /* @@ -2529,7 +2742,7 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc) int sz; sz = ioc->facts.FWImageSize; - dinitprintk((KERN_WARNING MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n", + dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n", ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz)); pci_free_consistent(ioc->pcidev, sz, ioc->cached_fw, ioc->cached_fw_dma); @@ -2573,9 +2786,9 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) mpt_alloc_fw_memory(ioc, sz); - dinitprintk((KERN_WARNING MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n", + dinitprintk((KERN_INFO MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n", ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz)); - + if (ioc->cached_fw == NULL) { /* Major Failure. */ @@ -2605,14 +2818,14 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma); sgeoffset += sizeof(u32) + sizeof(dma_addr_t); - dinitprintk((KERN_WARNING MYNAM "Sending FW Upload (req @ %p) sgeoffset=%d \n", + dinitprintk((KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n", prequest, sgeoffset)); DBG_DUMP_FW_REQUEST_FRAME(prequest) ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest, reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag); - dinitprintk((KERN_WARNING MYNAM "FW Upload completed rc=%x \n", ii)); + dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii)); cmdStatus = -EFAULT; if (ii == 0) { @@ -2627,10 +2840,10 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) cmdStatus = 0; } } - dinitprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n", + dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n", ioc->name, cmdStatus)); - + if (cmdStatus) { ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n", @@ -2656,9 +2869,8 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) * <0 for fw upload failure. */ static int -mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) +mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) { - MpiFwHeader_t *pFwHeader; MpiExtImageHeader_t *pExtImage; u32 fwSize; u32 diag0val; @@ -2669,18 +2881,8 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) u32 load_addr; u32 ioc_state=0; - ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x, ioc FW Ptr %p\n", - ioc->name, ioc->facts.FWImageSize, ioc->cached_fw)); - - if ( ioc->facts.FWImageSize == 0 ) - return -1; - - if (ioc->cached_fw == NULL) - return -2; - - /* prevent a second downloadboot and memory free with alt_ioc */ - if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) - ioc->alt_ioc->cached_fw = NULL; + ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n", + ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader)); CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); @@ -2708,16 +2910,17 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) ioc->name, count)); break; } - /* wait 1 sec */ + /* wait .1 sec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (1000); + msleep_interruptible (100); } else { - mdelay (1000); + mdelay (100); } } if ( count == 30 ) { - ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! Unable to RESET_ADAPTER diag0val=%x\n", + ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! " + "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n", ioc->name, diag0val)); return -3; } @@ -2732,7 +2935,6 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) /* Set the DiagRwEn and Disable ARM bits */ CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM)); - pFwHeader = (MpiFwHeader_t *) ioc->cached_fw; fwSize = (pFwHeader->ImageSize + 3)/4; ptrFw = (u32 *) pFwHeader; @@ -2761,8 +2963,8 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) fwSize = (pExtImage->ImageSize + 3) >> 2; ptrFw = (u32 *)pExtImage; - ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x bytes @ %p load_addr=%x\n", - ioc->name, fwSize*4, ptrFw, load_addr)); + ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n", + ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr)); CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr); while (fwSize--) { @@ -2782,19 +2984,38 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) /* Clear the internal flash bad bit - autoincrementing register, * so must do two writes. */ - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); - diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData); - diagRwData |= 0x4000000; - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData); + if (ioc->bus_type == SCSI) { + /* + * 1030 and 1035 H/W errata, workaround to access + * the ClearFlashBadSignatureBit + */ + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); + diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData); + diagRwData |= 0x40000000; + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData); + + } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ { + diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); + CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | + MPI_DIAG_CLEAR_FLASH_BAD_SIG); + + /* wait 1 msec */ + if (sleepFlag == CAN_SLEEP) { + msleep_interruptible (1); + } else { + mdelay (1); + } + } if (ioc->errata_flag_1064) pci_disable_io_access(ioc->pcidev); diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM\n", + ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, " + "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n", ioc->name, diag0val)); - diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM); + diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE); ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n", ioc->name, diag0val)); CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); @@ -2802,10 +3023,23 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) /* Write 0xFF to reset the sequencer */ CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); + if (ioc->bus_type == SAS) { + ioc_state = mpt_GetIocState(ioc, 0); + if ( (GetIocFacts(ioc, sleepFlag, + MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) { + ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n", + ioc->name, ioc_state)); + return -EFAULT; + } + } + for (count=0; count<HZ*20; count++) { if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) { ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n", ioc->name, count, ioc_state)); + if (ioc->bus_type == SAS) { + return 0; + } if ((SendIocInit(ioc, sleepFlag)) != 0) { ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n", ioc->name)); @@ -2845,9 +3079,9 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) * 0 else * * Returns: - * 1 - hard reset, READY - * 0 - no reset due to History bit, READY - * -1 - no reset due to History bit but not READY + * 1 - hard reset, READY + * 0 - no reset due to History bit, READY + * -1 - no reset due to History bit but not READY * OR reset but failed to come READY * -2 - no reset, could not enter DIAG mode * -3 - reset but bad FW bit @@ -2990,7 +3224,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) * */ CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM); - mdelay (1); + mdelay(1); /* * Now hit the reset bit in the Diagnostic register @@ -3039,12 +3273,13 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* wait 1 sec */ if (sleepFlag == CAN_SLEEP) { - ssleep(1); + msleep_interruptible (1000); } else { mdelay (1000); } } - if ((count = mpt_downloadboot(ioc, sleepFlag)) < 0) { + if ((count = mpt_downloadboot(ioc, + (MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) { printk(KERN_WARNING MYNAM ": firmware downloadboot failure (%d)!\n", count); } @@ -3170,7 +3405,7 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag) u32 state; int cntdn, count; - drsprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n", + drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n", ioc->name, reset_type)); CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT); if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) @@ -3374,6 +3609,9 @@ PrimeIocFifos(MPT_ADAPTER *ioc) ioc->reply_frames = (MPT_FRAME_HDR *) mem; ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF); + dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n", + ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma)); + alloc_dma += reply_sz; mem += reply_sz; @@ -3382,7 +3620,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc) ioc->req_frames = (MPT_FRAME_HDR *) mem; ioc->req_frames_dma = alloc_dma; - dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffers @ %p[%p]\n", + dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n", ioc->name, mem, (void *)(ulong)alloc_dma)); ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF); @@ -3408,7 +3646,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc) ioc->ChainBuffer = mem; ioc->ChainBufferDMA = alloc_dma; - dinitprintk((KERN_INFO MYNAM " :%s.ChainBuffers @ %p(%p)\n", + dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n", ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA)); /* Initialize the free chain Q. @@ -3513,7 +3751,7 @@ out_fail: */ static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, - int replyBytes, u16 *u16reply, int maxwait, int sleepFlag) + int replyBytes, u16 *u16reply, int maxwait, int sleepFlag) { MPIDefaultReply_t *mptReply; int failcnt = 0; @@ -3588,7 +3826,7 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, */ if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0) failcnt++; - + dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n", ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : "")); @@ -3624,7 +3862,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag) int count = 0; u32 intstat=0; - cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong; + cntdn = 1000 * howlong; if (sleepFlag == CAN_SLEEP) { while (--cntdn) { @@ -3674,7 +3912,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag) int count = 0; u32 intstat=0; - cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong; + cntdn = 1000 * howlong; if (sleepFlag == CAN_SLEEP) { while (--cntdn) { intstat = CHIPREG_READ32(&ioc->chip->IntStatus); @@ -3747,7 +3985,7 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag) } dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n", - ioc->name, t, le32_to_cpu(*(u32 *)hs_reply), + ioc->name, t, le32_to_cpu(*(u32 *)hs_reply), failcnt ? " - MISSING DOORBELL HANDSHAKE!" : "")); /* @@ -3819,7 +4057,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc) hdr.PageLength = 0; hdr.PageNumber = 0; hdr.PageType = MPI_CONFIG_PAGETYPE_LAN; - cfg.hdr = &hdr; + cfg.cfghdr.hdr = &hdr; cfg.physAddr = -1; cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; cfg.dir = 0; @@ -3863,7 +4101,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc) hdr.PageLength = 0; hdr.PageNumber = 1; hdr.PageType = MPI_CONFIG_PAGETYPE_LAN; - cfg.hdr = &hdr; + cfg.cfghdr.hdr = &hdr; cfg.physAddr = -1; cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; cfg.dir = 0; @@ -3930,7 +4168,7 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) hdr.PageLength = 0; hdr.PageNumber = 0; hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; - cfg.hdr = &hdr; + cfg.cfghdr.hdr = &hdr; cfg.physAddr = -1; cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; cfg.dir = 0; @@ -3988,6 +4226,85 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* + * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table + * @ioc: Pointer to MPT_ADAPTER structure + * @sas_address: 64bit SAS Address for operation. + * @target_id: specified target for operation + * @bus: specified bus for operation + * @persist_opcode: see below + * + * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for + * devices not currently present. + * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings + * + * NOTE: Don't use not this function during interrupt time. + * + * Returns: 0 for success, non-zero error + */ + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +int +mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) +{ + SasIoUnitControlRequest_t *sasIoUnitCntrReq; + SasIoUnitControlReply_t *sasIoUnitCntrReply; + MPT_FRAME_HDR *mf = NULL; + MPIHeader_t *mpi_hdr; + + + /* insure garbage is not sent to fw */ + switch(persist_opcode) { + + case MPI_SAS_OP_CLEAR_NOT_PRESENT: + case MPI_SAS_OP_CLEAR_ALL_PERSISTENT: + break; + + default: + return -1; + break; + } + + printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode); + + /* Get a MF for this command. + */ + if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { + printk("%s: no msg frames!\n",__FUNCTION__); + return -1; + } + + mpi_hdr = (MPIHeader_t *) mf; + sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf; + memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t)); + sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL; + sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext; + sasIoUnitCntrReq->Operation = persist_opcode; + + init_timer(&ioc->persist_timer); + ioc->persist_timer.data = (unsigned long) ioc; + ioc->persist_timer.function = mpt_timer_expired; + ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */; + ioc->persist_wait_done=0; + add_timer(&ioc->persist_timer); + mpt_put_msg_frame(mpt_base_index, ioc, mf); + wait_event(mpt_waitq, ioc->persist_wait_done); + + sasIoUnitCntrReply = + (SasIoUnitControlReply_t *)ioc->persist_reply_frame; + if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) { + printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n", + __FUNCTION__, + sasIoUnitCntrReply->IOCStatus, + sasIoUnitCntrReply->IOCLogInfo); + return -1; + } + + printk("%s: success\n",__FUNCTION__); + return 0; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* * GetIoUnitPage2 - Retrieve BIOS version and boot order information. * @ioc: Pointer to MPT_ADAPTER structure * @@ -4012,7 +4329,7 @@ GetIoUnitPage2(MPT_ADAPTER *ioc) hdr.PageLength = 0; hdr.PageNumber = 2; hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT; - cfg.hdr = &hdr; + cfg.cfghdr.hdr = &hdr; cfg.physAddr = -1; cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; cfg.dir = 0; @@ -4102,7 +4419,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) header.PageLength = 0; header.PageNumber = 0; header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT; - cfg.hdr = &header; + cfg.cfghdr.hdr = &header; cfg.physAddr = -1; cfg.pageAddr = portnum; cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; @@ -4122,6 +4439,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) ioc->spi_data.minSyncFactor = MPT_ASYNC; ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN; rc = 1; + ddvprintk((MYIOC_s_INFO_FMT "Unable to read PortPage0 minSyncFactor=%x\n", + ioc->name, ioc->spi_data.minSyncFactor)); } else { /* Save the Port Page 0 data */ @@ -4131,7 +4450,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) { ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS; - dinitprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n", + ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n", ioc->name, pPP0->Capabilities)); } ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0; @@ -4140,6 +4459,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) ioc->spi_data.maxSyncOffset = (u8) (data >> 16); data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK; ioc->spi_data.minSyncFactor = (u8) (data >> 8); + ddvprintk((MYIOC_s_INFO_FMT "PortPage0 minSyncFactor=%x\n", + ioc->name, ioc->spi_data.minSyncFactor)); } else { ioc->spi_data.maxSyncOffset = 0; ioc->spi_data.minSyncFactor = MPT_ASYNC; @@ -4152,8 +4473,11 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) || (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) { - if (ioc->spi_data.minSyncFactor < MPT_ULTRA) + if (ioc->spi_data.minSyncFactor < MPT_ULTRA) { ioc->spi_data.minSyncFactor = MPT_ULTRA; + ddvprintk((MYIOC_s_INFO_FMT "HVD or SE detected, minSyncFactor=%x\n", + ioc->name, ioc->spi_data.minSyncFactor)); + } } } if (pbuf) { @@ -4168,7 +4492,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) header.PageLength = 0; header.PageNumber = 2; header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT; - cfg.hdr = &header; + cfg.cfghdr.hdr = &header; cfg.physAddr = -1; cfg.pageAddr = portnum; cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; @@ -4236,7 +4560,7 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) header.PageLength = 0; header.PageNumber = 1; header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; - cfg.hdr = &header; + cfg.cfghdr.hdr = &header; cfg.physAddr = -1; cfg.pageAddr = portnum; cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; @@ -4245,8 +4569,8 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) if (mpt_config(ioc, &cfg) != 0) return -EFAULT; - ioc->spi_data.sdp1version = cfg.hdr->PageVersion; - ioc->spi_data.sdp1length = cfg.hdr->PageLength; + ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion; + ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength; header.PageVersion = 0; header.PageLength = 0; @@ -4255,8 +4579,8 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) if (mpt_config(ioc, &cfg) != 0) return -EFAULT; - ioc->spi_data.sdp0version = cfg.hdr->PageVersion; - ioc->spi_data.sdp0length = cfg.hdr->PageLength; + ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion; + ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength; dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n", ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length)); @@ -4298,7 +4622,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) header.PageLength = 0; header.PageNumber = 2; header.PageType = MPI_CONFIG_PAGETYPE_IOC; - cfg.hdr = &header; + cfg.cfghdr.hdr = &header; cfg.physAddr = -1; cfg.pageAddr = 0; cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; @@ -4320,10 +4644,10 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) if (mpt_config(ioc, &cfg) != 0) goto done_and_free; - if ( (mem = (u8 *)ioc->spi_data.pIocPg2) == NULL ) { + if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) { mem = kmalloc(iocpage2sz, GFP_ATOMIC); if (mem) { - ioc->spi_data.pIocPg2 = (IOCPage2_t *) mem; + ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem; } else { goto done_and_free; } @@ -4340,7 +4664,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) /* At least 1 RAID Volume */ pIocRv = pIoc2->RaidVolume; - ioc->spi_data.isRaid = 0; + ioc->raid_data.isRaid = 0; for (jj = 0; jj < nVols; jj++, pIocRv++) { vid = pIocRv->VolumeID; vbus = pIocRv->VolumeBus; @@ -4349,7 +4673,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) /* find the match */ if (vbus == 0) { - ioc->spi_data.isRaid |= (1 << vid); + ioc->raid_data.isRaid |= (1 << vid); } else { /* Error! Always bus 0 */ @@ -4384,8 +4708,8 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) /* Free the old page */ - kfree(ioc->spi_data.pIocPg3); - ioc->spi_data.pIocPg3 = NULL; + kfree(ioc->raid_data.pIocPg3); + ioc->raid_data.pIocPg3 = NULL; /* There is at least one physical disk. * Read and save IOC Page 3 @@ -4394,7 +4718,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) header.PageLength = 0; header.PageNumber = 3; header.PageType = MPI_CONFIG_PAGETYPE_IOC; - cfg.hdr = &header; + cfg.cfghdr.hdr = &header; cfg.physAddr = -1; cfg.pageAddr = 0; cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; @@ -4422,7 +4746,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) mem = kmalloc(iocpage3sz, GFP_ATOMIC); if (mem) { memcpy(mem, (u8 *)pIoc3, iocpage3sz); - ioc->spi_data.pIocPg3 = (IOCPage3_t *) mem; + ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem; } } @@ -4446,7 +4770,7 @@ mpt_read_ioc_pg_4(MPT_ADAPTER *ioc) header.PageLength = 0; header.PageNumber = 4; header.PageType = MPI_CONFIG_PAGETYPE_IOC; - cfg.hdr = &header; + cfg.cfghdr.hdr = &header; cfg.physAddr = -1; cfg.pageAddr = 0; cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; @@ -4498,7 +4822,7 @@ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc) header.PageLength = 0; header.PageNumber = 1; header.PageType = MPI_CONFIG_PAGETYPE_IOC; - cfg.hdr = &header; + cfg.cfghdr.hdr = &header; cfg.physAddr = -1; cfg.pageAddr = 0; cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; @@ -4580,13 +4904,13 @@ SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch) evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc); if (evnp == NULL) { - dprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n", + devtprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n", ioc->name)); return 0; } memset(evnp, 0, sizeof(*evnp)); - dprintk((MYIOC_s_INFO_FMT "Sending EventNotification(%d)\n", ioc->name, EvSwitch)); + devtprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp)); evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION; evnp->ChainOffset = 0; @@ -4610,8 +4934,10 @@ SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp) EventAck_t *pAck; if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { - printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK request frame!\n", - ioc->name); + printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK " + "request frame for Event=%x EventContext=%x EventData=%x!\n", + ioc->name, evnp->Event, le32_to_cpu(evnp->EventContext), + le32_to_cpu(evnp->Data[0])); return -1; } memset(pAck, 0, sizeof(*pAck)); @@ -4647,10 +4973,11 @@ int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) { Config_t *pReq; + ConfigExtendedPageHeader_t *pExtHdr = NULL; MPT_FRAME_HDR *mf; unsigned long flags; int ii, rc; - u32 flagsLength; + int flagsLength; int in_isr; /* Prevent calling wait_event() (below), if caller happens @@ -4675,16 +5002,30 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) pReq->Reserved = 0; pReq->ChainOffset = 0; pReq->Function = MPI_FUNCTION_CONFIG; + + /* Assume page type is not extended and clear "reserved" fields. */ pReq->ExtPageLength = 0; pReq->ExtPageType = 0; pReq->MsgFlags = 0; + for (ii=0; ii < 8; ii++) pReq->Reserved2[ii] = 0; - pReq->Header.PageVersion = pCfg->hdr->PageVersion; - pReq->Header.PageLength = pCfg->hdr->PageLength; - pReq->Header.PageNumber = pCfg->hdr->PageNumber; - pReq->Header.PageType = (pCfg->hdr->PageType & MPI_CONFIG_PAGETYPE_MASK); + pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion; + pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength; + pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber; + pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK); + + if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) { + pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr; + pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength); + pReq->ExtPageType = pExtHdr->ExtPageType; + pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; + + /* Page Length must be treated as a reserved field for the extended header. */ + pReq->Header.PageLength = 0; + } + pReq->PageAddress = cpu_to_le32(pCfg->pageAddr); /* Add a SGE to the config request. @@ -4694,12 +5035,20 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) else flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; - flagsLength |= pCfg->hdr->PageLength * 4; + if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) { + flagsLength |= pExtHdr->ExtPageLength * 4; - mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr); + dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n", + ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action)); + } + else { + flagsLength |= pCfg->cfghdr.hdr->PageLength * 4; + + dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n", + ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action)); + } - dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n", - ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action)); + mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr); /* Append pCfg pointer to end of mf */ @@ -4789,8 +5138,8 @@ mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) pReq->Reserved3 = 0; pReq->NumAddressBytes = 0x01; pReq->Reserved4 = 0; - pReq->DataLength = 0x04; - pdev = (struct pci_dev *) ioc->pcidev; + pReq->DataLength = cpu_to_le16(0x04); + pdev = ioc->pcidev; if (pdev->devfn & 1) pReq->DeviceAddr = 0xB2; else @@ -5321,8 +5670,8 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static char * -EventDescriptionStr(u8 event, u32 evData0) +static void +EventDescriptionStr(u8 event, u32 evData0, char *evStr) { char *ds; @@ -5375,8 +5724,95 @@ EventDescriptionStr(u8 event, u32 evData0) ds = "Events(OFF) Change"; break; case MPI_EVENT_INTEGRATED_RAID: - ds = "Integrated Raid"; + { + u8 ReasonCode = (u8)(evData0 >> 16); + switch (ReasonCode) { + case MPI_EVENT_RAID_RC_VOLUME_CREATED : + ds = "Integrated Raid: Volume Created"; + break; + case MPI_EVENT_RAID_RC_VOLUME_DELETED : + ds = "Integrated Raid: Volume Deleted"; + break; + case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED : + ds = "Integrated Raid: Volume Settings Changed"; + break; + case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED : + ds = "Integrated Raid: Volume Status Changed"; + break; + case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED : + ds = "Integrated Raid: Volume Physdisk Changed"; + break; + case MPI_EVENT_RAID_RC_PHYSDISK_CREATED : + ds = "Integrated Raid: Physdisk Created"; + break; + case MPI_EVENT_RAID_RC_PHYSDISK_DELETED : + ds = "Integrated Raid: Physdisk Deleted"; + break; + case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED : + ds = "Integrated Raid: Physdisk Settings Changed"; + break; + case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED : + ds = "Integrated Raid: Physdisk Status Changed"; + break; + case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED : + ds = "Integrated Raid: Domain Validation Needed"; + break; + case MPI_EVENT_RAID_RC_SMART_DATA : + ds = "Integrated Raid; Smart Data"; + break; + case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED : + ds = "Integrated Raid: Replace Action Started"; + break; + default: + ds = "Integrated Raid"; + break; + } + break; + } + case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE: + ds = "SCSI Device Status Change"; + break; + case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: + { + u8 ReasonCode = (u8)(evData0 >> 16); + switch (ReasonCode) { + case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: + ds = "SAS Device Status Change: Added"; + break; + case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: + ds = "SAS Device Status Change: Deleted"; + break; + case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: + ds = "SAS Device Status Change: SMART Data"; + break; + case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: + ds = "SAS Device Status Change: No Persistancy Added"; + break; + default: + ds = "SAS Device Status Change: Unknown"; + break; + } + break; + } + case MPI_EVENT_ON_BUS_TIMER_EXPIRED: + ds = "Bus Timer Expired"; + break; + case MPI_EVENT_QUEUE_FULL: + ds = "Queue Full"; break; + case MPI_EVENT_SAS_SES: + ds = "SAS SES Event"; + break; + case MPI_EVENT_PERSISTENT_TABLE_FULL: + ds = "Persistent Table Full"; + break; + case MPI_EVENT_SAS_PHY_LINK_STATUS: + ds = "SAS PHY Link Status"; + break; + case MPI_EVENT_SAS_DISCOVERY_ERROR: + ds = "SAS Discovery Error"; + break; + /* * MPT base "custom" events may be added here... */ @@ -5384,7 +5820,7 @@ EventDescriptionStr(u8 event, u32 evData0) ds = "Unknown"; break; } - return ds; + strcpy(evStr,ds); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -5406,7 +5842,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply int ii; int r = 0; int handlers = 0; - char *evStr; + char evStr[100]; u8 event; /* @@ -5419,7 +5855,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply evData0 = le32_to_cpu(pEventReply->Data[0]); } - evStr = EventDescriptionStr(event, evData0); + EventDescriptionStr(event, evData0, evStr); devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n", ioc->name, evStr, @@ -5436,20 +5872,6 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply * Do general / base driver event processing */ switch(event) { - case MPI_EVENT_NONE: /* 00 */ - case MPI_EVENT_LOG_DATA: /* 01 */ - case MPI_EVENT_STATE_CHANGE: /* 02 */ - case MPI_EVENT_UNIT_ATTENTION: /* 03 */ - case MPI_EVENT_IOC_BUS_RESET: /* 04 */ - case MPI_EVENT_EXT_BUS_RESET: /* 05 */ - case MPI_EVENT_RESCAN: /* 06 */ - case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */ - case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */ - case MPI_EVENT_LOGOUT: /* 09 */ - case MPI_EVENT_INTEGRATED_RAID: /* 0B */ - case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE: /* 0C */ - default: - break; case MPI_EVENT_EVENT_CHANGE: /* 0A */ if (evDataLen) { u8 evState = evData0 & 0xFF; @@ -5462,6 +5884,8 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply } } break; + default: + break; } /* @@ -5504,6 +5928,8 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply * If needed, send (a single) EventAck. */ if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) { + devtprintk((MYIOC_s_WARN_FMT + "EventAck required\n",ioc->name)); if ((ii = SendEventAck(ioc, pEventReply)) != 0) { devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n", ioc->name, ii)); @@ -5584,7 +6010,7 @@ mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info) case 0x00080000: desc = "Outbound DMA Overrun"; break; - + case 0x00090000: desc = "Task Management"; break; @@ -5600,12 +6026,117 @@ mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info) case 0x000C0000: desc = "Untagged Table Size"; break; - + } printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc); } +/* strings for sas loginfo */ + static char *originator_str[] = { + "IOP", /* 00h */ + "PL", /* 01h */ + "IR" /* 02h */ + }; + static char *iop_code_str[] = { + NULL, /* 00h */ + "Invalid SAS Address", /* 01h */ + NULL, /* 02h */ + "Invalid Page", /* 03h */ + NULL, /* 04h */ + "Task Terminated" /* 05h */ + }; + static char *pl_code_str[] = { + NULL, /* 00h */ + "Open Failure", /* 01h */ + "Invalid Scatter Gather List", /* 02h */ + "Wrong Relative Offset or Frame Length", /* 03h */ + "Frame Transfer Error", /* 04h */ + "Transmit Frame Connected Low", /* 05h */ + "SATA Non-NCQ RW Error Bit Set", /* 06h */ + "SATA Read Log Receive Data Error", /* 07h */ + "SATA NCQ Fail All Commands After Error", /* 08h */ + "SATA Error in Receive Set Device Bit FIS", /* 09h */ + "Receive Frame Invalid Message", /* 0Ah */ + "Receive Context Message Valid Error", /* 0Bh */ + "Receive Frame Current Frame Error", /* 0Ch */ + "SATA Link Down", /* 0Dh */ + "Discovery SATA Init W IOS", /* 0Eh */ + "Config Invalid Page", /* 0Fh */ + "Discovery SATA Init Timeout", /* 10h */ + "Reset", /* 11h */ + "Abort", /* 12h */ + "IO Not Yet Executed", /* 13h */ + "IO Executed", /* 14h */ + NULL, /* 15h */ + NULL, /* 16h */ + NULL, /* 17h */ + NULL, /* 18h */ + NULL, /* 19h */ + NULL, /* 1Ah */ + NULL, /* 1Bh */ + NULL, /* 1Ch */ + NULL, /* 1Dh */ + NULL, /* 1Eh */ + NULL, /* 1Fh */ + "Enclosure Management" /* 20h */ + }; + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + * mpt_sas_log_info - Log information returned from SAS IOC. + * @ioc: Pointer to MPT_ADAPTER structure + * @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) +{ +union loginfo_type { + u32 loginfo; + struct { + u32 subcode:16; + u32 code:8; + u32 originator:4; + u32 bus_type:4; + }dw; +}; + union loginfo_type sas_loginfo; + char *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]; + } + + 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, + 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); +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC. @@ -5692,7 +6223,7 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) break; case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ - /* This error is checked in scsi_io_done(). Skip. + /* This error is checked in scsi_io_done(). Skip. desc = "SCSI Data Underrun"; */ break; @@ -5767,6 +6298,7 @@ EXPORT_SYMBOL(mpt_findImVolumes); EXPORT_SYMBOL(mpt_read_ioc_pg_3); EXPORT_SYMBOL(mpt_alloc_fw_memory); EXPORT_SYMBOL(mpt_free_fw_memory); +EXPORT_SYMBOL(mptbase_sas_persist_operation); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 848fb236b175..75105277e22f 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -65,6 +65,7 @@ #include "lsi/mpi_fc.h" /* Fibre Channel (lowlevel) support */ #include "lsi/mpi_targ.h" /* SCSI/FCP Target protcol support */ #include "lsi/mpi_tool.h" /* Tools support */ +#include "lsi/mpi_sas.h" /* SAS support */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -76,8 +77,8 @@ #define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.03.02" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.02" +#define MPT_LINUX_VERSION_COMMON "3.03.03" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.03" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ @@ -423,7 +424,7 @@ typedef struct _MPT_IOCTL { /* * Event Structure and define */ -#define MPTCTL_EVENT_LOG_SIZE (0x0000000A) +#define MPTCTL_EVENT_LOG_SIZE (0x000000032) typedef struct _mpt_ioctl_events { u32 event; /* Specified by define above */ u32 eventContext; /* Index or counter */ @@ -451,16 +452,13 @@ typedef struct _mpt_ioctl_events { #define MPT_SCSICFG_ALL_IDS 0x02 /* WriteSDP1 to all IDS */ /* #define MPT_SCSICFG_BLK_NEGO 0x10 WriteSDP1 with WDTR and SDTR disabled */ -typedef struct _ScsiCfgData { +typedef struct _SpiCfgData { u32 PortFlags; int *nvram; /* table of device NVRAM values */ - IOCPage2_t *pIocPg2; /* table of Raid Volumes */ - IOCPage3_t *pIocPg3; /* table of physical disks */ IOCPage4_t *pIocPg4; /* SEP devices addressing */ dma_addr_t IocPg4_dma; /* Phys Addr of IOCPage4 data */ int IocPg4Sz; /* IOCPage4 size */ u8 dvStatus[MPT_MAX_SCSI_DEVICES]; - int isRaid; /* bit field, 1 if RAID */ u8 minSyncFactor; /* 0xFF if async */ u8 maxSyncOffset; /* 0 if async */ u8 maxBusWidth; /* 0 if narrow, 1 if wide */ @@ -472,10 +470,28 @@ typedef struct _ScsiCfgData { u8 dvScheduled; /* 1 if scheduled */ u8 forceDv; /* 1 to force DV scheduling */ u8 noQas; /* Disable QAS for this adapter */ - u8 Saf_Te; /* 1 to force all Processors as SAF-TE if Inquiry data length is too short to check for SAF-TE */ + u8 Saf_Te; /* 1 to force all Processors as + * SAF-TE if Inquiry data length + * is too short to check for SAF-TE + */ u8 mpt_dv; /* command line option: enhanced=1, basic=0 */ + u8 bus_reset; /* 1 to allow bus reset */ u8 rsvd[1]; -} ScsiCfgData; +}SpiCfgData; + +typedef struct _SasCfgData { + u8 ptClear; /* 1 to automatically clear the + * persistent table. + * 0 to disable + * automatic clearing. + */ +}SasCfgData; + +typedef struct _RaidCfgData { + IOCPage2_t *pIocPg2; /* table of Raid Volumes */ + IOCPage3_t *pIocPg3; /* table of physical disks */ + int isRaid; /* bit field, 1 if RAID */ +}RaidCfgData; /* * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS @@ -530,11 +546,16 @@ typedef struct _MPT_ADAPTER u8 *sense_buf_pool; dma_addr_t sense_buf_pool_dma; u32 sense_buf_low_dma; + u8 *HostPageBuffer; /* SAS - host page buffer support */ + u32 HostPageBuffer_sz; + dma_addr_t HostPageBuffer_dma; int mtrr_reg; struct pci_dev *pcidev; /* struct pci_dev pointer */ u8 __iomem *memmap; /* mmap address */ struct Scsi_Host *sh; /* Scsi Host pointer */ - ScsiCfgData spi_data; /* Scsi config. data */ + SpiCfgData spi_data; /* Scsi config. data */ + RaidCfgData raid_data; /* Raid config. data */ + SasCfgData sas_data; /* Sas config. data */ MPT_IOCTL *ioctl; /* ioctl data pointer */ struct proc_dir_entry *ioc_dentry; struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */ @@ -554,31 +575,35 @@ typedef struct _MPT_ADAPTER #else u32 mfcnt; #endif - u32 NB_for_64_byte_frame; + u32 NB_for_64_byte_frame; u32 hs_req[MPT_MAX_FRAME_SIZE/sizeof(u32)]; u16 hs_reply[MPT_MAX_FRAME_SIZE/sizeof(u16)]; IOCFactsReply_t facts; PortFactsReply_t pfacts[2]; FCPortPage0_t fc_port_page0[2]; + struct timer_list persist_timer; /* persist table timer */ + int persist_wait_done; /* persist completion flag */ + u8 persist_reply_frame[MPT_DEFAULT_FRAME_SIZE]; /* persist reply */ LANPage0_t lan_cnfg_page0; LANPage1_t lan_cnfg_page1; - /* + /* * Description: errata_flag_1064 * If a PCIX read occurs within 1 or 2 cycles after the chip receives * a split completion for a read data, an internal address pointer incorrectly * increments by 32 bytes */ - int errata_flag_1064; + int errata_flag_1064; u8 FirstWhoInit; u8 upload_fw; /* If set, do a fw upload */ u8 reload_fw; /* Force a FW Reload on next reset */ - u8 NBShiftFactor; /* NB Shift Factor based on Block Size (Facts) */ + u8 NBShiftFactor; /* NB Shift Factor based on Block Size (Facts) */ u8 pad1[4]; int DoneCtx; int TaskCtx; int InternalCtx; - struct list_head list; + struct list_head list; struct net_device *netdev; + struct list_head sas_topology; } MPT_ADAPTER; /* @@ -915,7 +940,10 @@ struct scsi_cmnd; typedef struct _x_config_parms { struct list_head linkage; /* linked list */ struct timer_list timer; /* timer function for this request */ - ConfigPageHeader_t *hdr; + union { + ConfigExtendedPageHeader_t *ehdr; + ConfigPageHeader_t *hdr; + } cfghdr; dma_addr_t physAddr; int wait_done; /* wait for this request */ u32 pageAddr; /* properly formatted */ @@ -961,6 +989,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 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); +extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); /* * Public data decl's... diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 05ea5944c487..cb2d59d5f5af 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -242,7 +242,7 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) /* Set the command status to GOOD if IOC Status is GOOD * OR if SCSI I/O cmd and data underrun or recovered error. */ - iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK; + iocStatus = le16_to_cpu(reply->u.reply.IOCStatus) & MPI_IOCSTATUS_MASK; if (iocStatus == MPI_IOCSTATUS_SUCCESS) ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD; @@ -1326,7 +1326,7 @@ mptctl_gettargetinfo (unsigned long arg) */ if (hd && hd->Targets) { mpt_findImVolumes(ioc); - pIoc2 = ioc->spi_data.pIocPg2; + pIoc2 = ioc->raid_data.pIocPg2; for ( id = 0; id <= max_id; ) { if ( pIoc2 && pIoc2->NumActiveVolumes ) { if ( id == pIoc2->RaidVolume[0].VolumeID ) { @@ -1348,7 +1348,7 @@ mptctl_gettargetinfo (unsigned long arg) --maxWordsLeft; goto next_id; } else { - pIoc3 = ioc->spi_data.pIocPg3; + pIoc3 = ioc->raid_data.pIocPg3; for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) { if ( pIoc3->PhysDisk[jj].PhysDiskID == id ) goto next_id; @@ -2324,7 +2324,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) hdr.PageLength = 0; hdr.PageNumber = 0; hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING; - cfg.hdr = &hdr; + cfg.cfghdr.hdr = &hdr; cfg.physAddr = -1; cfg.pageAddr = 0; cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; @@ -2333,7 +2333,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) strncpy(karg.serial_number, " ", 24); if (mpt_config(ioc, &cfg) == 0) { - if (cfg.hdr->PageLength > 0) { + if (cfg.cfghdr.hdr->PageLength > 0) { /* Issue the second config page request */ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; @@ -2479,7 +2479,7 @@ mptctl_hp_targetinfo(unsigned long arg) hdr.PageNumber = 0; hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; - cfg.hdr = &hdr; + cfg.cfghdr.hdr = &hdr; cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; cfg.dir = 0; cfg.timeout = 0; @@ -2527,15 +2527,15 @@ mptctl_hp_targetinfo(unsigned long arg) hdr.PageNumber = 3; hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; - cfg.hdr = &hdr; + cfg.cfghdr.hdr = &hdr; cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; cfg.dir = 0; cfg.timeout = 0; cfg.physAddr = -1; - if ((mpt_config(ioc, &cfg) == 0) && (cfg.hdr->PageLength > 0)) { + if ((mpt_config(ioc, &cfg) == 0) && (cfg.cfghdr.hdr->PageLength > 0)) { /* Issue the second config page request */ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; - data_sz = (int) cfg.hdr->PageLength * 4; + data_sz = (int) cfg.cfghdr.hdr->PageLength * 4; pg3_alloc = (SCSIDevicePage3_t *) pci_alloc_consistent( ioc->pcidev, data_sz, &page_dma); if (pg3_alloc) { diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 13771abea13f..a628be9bbbad 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -189,7 +189,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)); diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 52794be5a95c..ed3c891e388f 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -312,7 +312,12 @@ static int mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) { struct net_device *dev = ioc->netdev; - struct mpt_lan_priv *priv = netdev_priv(dev); + struct mpt_lan_priv *priv; + + if (dev == NULL) + return(1); + else + priv = netdev_priv(dev); dlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to LAN driver!\n", reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c new file mode 100644 index 000000000000..7de19a84dc74 --- /dev/null +++ b/drivers/message/fusion/mptsas.c @@ -0,0 +1,1239 @@ +/* + * linux/drivers/message/fusion/mptsas.c + * For use with LSI Logic PCI chip/adapter(s) + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * + * Copyright (c) 1999-2005 LSI Logic Corporation + * (mailto:mpt_linux_developer@lsil.com) + * Copyright (c) 2005 Dell + */ +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + NO WARRANTY + THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT + LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is + solely responsible for determining the appropriateness of using and + distributing the Program and assumes all risks associated with its + exercise of rights under this Agreement, including but not limited to + the risks and costs of program errors, damage to or loss of data, + programs or equipment, and unavailability or interruption of operations. + + DISCLAIMER OF LIABILITY + NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/workqueue.h> + +#include <scsi/scsi_cmnd.h> +#include <scsi/scsi_device.h> +#include <scsi/scsi_host.h> +#include <scsi/scsi_transport_sas.h> + +#include "mptbase.h" +#include "mptscsih.h" + + +#define my_NAME "Fusion MPT SAS Host driver" +#define my_VERSION MPT_LINUX_VERSION_COMMON +#define MYNAM "mptsas" + +MODULE_AUTHOR(MODULEAUTHOR); +MODULE_DESCRIPTION(my_NAME); +MODULE_LICENSE("GPL"); + +static int mpt_pq_filter; +module_param(mpt_pq_filter, int, 0); +MODULE_PARM_DESC(mpt_pq_filter, + "Enable peripheral qualifier filter: enable=1 " + "(default=0)"); + +static int mpt_pt_clear; +module_param(mpt_pt_clear, int, 0); +MODULE_PARM_DESC(mpt_pt_clear, + "Clear persistency table: enable=1 " + "(default=MPTSCSIH_PT_CLEAR=0)"); + +static int mptsasDoneCtx = -1; +static int mptsasTaskCtx = -1; +static int mptsasInternalCtx = -1; /* Used only for internal commands */ + + +/* + * SAS topology structures + * + * The MPT Fusion firmware interface spreads information about the + * SAS topology over many manufacture pages, thus we need some data + * structure to collect it and process it for the SAS transport class. + */ + +struct mptsas_devinfo { + u16 handle; /* unique id to address this device */ + u8 phy_id; /* phy number of parent device */ + u8 port_id; /* sas physical port this device + is assoc'd with */ + u8 target; /* logical target id of this device */ + u8 bus; /* logical bus number of this device */ + u64 sas_address; /* WWN of this device, + SATA is assigned by HBA,expander */ + u32 device_info; /* bitfield detailed info about this device */ +}; + +struct mptsas_phyinfo { + u8 phy_id; /* phy index */ + u8 port_id; /* port number this phy is part of */ + u8 negotiated_link_rate; /* nego'd link rate for this phy */ + u8 hw_link_rate; /* hardware max/min phys link rate */ + u8 programmed_link_rate; /* programmed max/min phy link rate */ + struct mptsas_devinfo identify; /* point to phy device info */ + struct mptsas_devinfo attached; /* point to attached device info */ + struct sas_rphy *rphy; +}; + +struct mptsas_portinfo { + struct list_head list; + u16 handle; /* unique id to address this */ + u8 num_phys; /* number of phys */ + struct mptsas_phyinfo *phy_info; +}; + +/* + * This is pretty ugly. We will be able to seriously clean it up + * once the DV code in mptscsih goes away and we can properly + * implement ->target_alloc. + */ +static int +mptsas_slave_alloc(struct scsi_device *device) +{ + struct Scsi_Host *host = device->host; + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + struct sas_rphy *rphy; + struct mptsas_portinfo *p; + VirtDevice *vdev; + uint target = device->id; + int i; + + if ((vdev = hd->Targets[target]) != NULL) + goto out; + + vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL); + if (!vdev) { + printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", + hd->ioc->name, sizeof(VirtDevice)); + return -ENOMEM; + } + + memset(vdev, 0, sizeof(VirtDevice)); + vdev->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY; + vdev->ioc_id = hd->ioc->id; + + rphy = dev_to_rphy(device->sdev_target->dev.parent); + list_for_each_entry(p, &hd->ioc->sas_topology, list) { + for (i = 0; i < p->num_phys; i++) { + if (p->phy_info[i].attached.sas_address == + rphy->identify.sas_address) { + vdev->target_id = + p->phy_info[i].attached.target; + vdev->bus_id = p->phy_info[i].attached.bus; + hd->Targets[device->id] = vdev; + goto out; + } + } + } + + printk("No matching SAS device found!!\n"); + kfree(vdev); + return -ENODEV; + + out: + vdev->num_luns++; + device->hostdata = vdev; + return 0; +} + +static struct scsi_host_template mptsas_driver_template = { + .proc_name = "mptsas", + .proc_info = mptscsih_proc_info, + .name = "MPT SPI Host", + .info = mptscsih_info, + .queuecommand = mptscsih_qcmd, + .slave_alloc = mptsas_slave_alloc, + .slave_configure = mptscsih_slave_configure, + .slave_destroy = mptscsih_slave_destroy, + .change_queue_depth = mptscsih_change_queue_depth, + .eh_abort_handler = mptscsih_abort, + .eh_device_reset_handler = mptscsih_dev_reset, + .eh_bus_reset_handler = mptscsih_bus_reset, + .eh_host_reset_handler = mptscsih_host_reset, + .bios_param = mptscsih_bios_param, + .can_queue = MPT_FC_CAN_QUEUE, + .this_id = -1, + .sg_tablesize = MPT_SCSI_SG_DEPTH, + .max_sectors = 8192, + .cmd_per_lun = 7, + .use_clustering = ENABLE_CLUSTERING, +}; + +static struct sas_function_template mptsas_transport_functions = { +}; + +static struct scsi_transport_template *mptsas_transport_template; + +#ifdef SASDEBUG +static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) +{ + printk("---- IO UNIT PAGE 0 ------------\n"); + printk("Handle=0x%X\n", + le16_to_cpu(phy_data->AttachedDeviceHandle)); + printk("Controller Handle=0x%X\n", + le16_to_cpu(phy_data->ControllerDevHandle)); + printk("Port=0x%X\n", phy_data->Port); + printk("Port Flags=0x%X\n", phy_data->PortFlags); + printk("PHY Flags=0x%X\n", phy_data->PhyFlags); + printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate); + printk("Controller PHY Device Info=0x%X\n", + le32_to_cpu(phy_data->ControllerPhyDeviceInfo)); + printk("DiscoveryStatus=0x%X\n", + le32_to_cpu(phy_data->DiscoveryStatus)); + printk("\n"); +} + +static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0) +{ + __le64 sas_address; + + memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64)); + + printk("---- SAS PHY PAGE 0 ------------\n"); + printk("Attached Device Handle=0x%X\n", + le16_to_cpu(pg0->AttachedDevHandle)); + printk("SAS Address=0x%llX\n", + (unsigned long long)le64_to_cpu(sas_address)); + printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier); + printk("Attached Device Info=0x%X\n", + le32_to_cpu(pg0->AttachedDeviceInfo)); + printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate); + printk("Change Count=0x%X\n", pg0->ChangeCount); + printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo)); + printk("\n"); +} + +static void mptsas_print_device_pg0(SasDevicePage0_t *pg0) +{ + __le64 sas_address; + + memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64)); + + printk("---- SAS DEVICE PAGE 0 ---------\n"); + printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle)); + printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle)); + printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot)); + printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address)); + printk("Target ID=0x%X\n", pg0->TargetID); + printk("Bus=0x%X\n", pg0->Bus); + printk("Parent Phy Num=0x%X\n", pg0->PhyNum); + printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus)); + printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo)); + printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags)); + printk("Physical Port=0x%X\n", pg0->PhysicalPort); + printk("\n"); +} + +static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1) +{ + printk("---- SAS EXPANDER PAGE 1 ------------\n"); + + printk("Physical Port=0x%X\n", pg1->PhysicalPort); + printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier); + printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate); + printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate); + printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate); + printk("Owner Device Handle=0x%X\n", + le16_to_cpu(pg1->OwnerDevHandle)); + printk("Attached Device Handle=0x%X\n", + le16_to_cpu(pg1->AttachedDevHandle)); +} +#else +#define mptsas_print_phy_data(phy_data) do { } while (0) +#define mptsas_print_phy_pg0(pg0) do { } while (0) +#define mptsas_print_device_pg0(pg0) do { } while (0) +#define mptsas_print_expander_pg1(pg1) do { } while (0) +#endif + +static int +mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) +{ + ConfigExtendedPageHeader_t hdr; + CONFIGPARMS cfg; + SasIOUnitPage0_t *buffer; + dma_addr_t dma_handle; + int error, i; + + hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION; + hdr.ExtPageLength = 0; + hdr.PageNumber = 0; + hdr.Reserved1 = 0; + hdr.Reserved2 = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; + hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; + + cfg.cfghdr.ehdr = &hdr; + cfg.physAddr = -1; + cfg.pageAddr = 0; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; /* read */ + cfg.timeout = 10; + + error = mpt_config(ioc, &cfg); + if (error) + goto out; + if (!hdr.ExtPageLength) { + error = -ENXIO; + goto out; + } + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + &dma_handle); + if (!buffer) { + error = -ENOMEM; + goto out; + } + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + error = mpt_config(ioc, &cfg); + if (error) + goto out_free_consistent; + + port_info->num_phys = buffer->NumPhys; + port_info->phy_info = kcalloc(port_info->num_phys, + sizeof(struct mptsas_phyinfo),GFP_KERNEL); + if (!port_info->phy_info) { + error = -ENOMEM; + goto out_free_consistent; + } + + for (i = 0; i < port_info->num_phys; i++) { + mptsas_print_phy_data(&buffer->PhyData[i]); + port_info->phy_info[i].phy_id = i; + port_info->phy_info[i].port_id = + buffer->PhyData[i].Port; + port_info->phy_info[i].negotiated_link_rate = + buffer->PhyData[i].NegotiatedLinkRate; + } + + out_free_consistent: + pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + buffer, dma_handle); + out: + return error; +} + +static int +mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, + u32 form, u32 form_specific) +{ + ConfigExtendedPageHeader_t hdr; + CONFIGPARMS cfg; + SasPhyPage0_t *buffer; + dma_addr_t dma_handle; + int error; + + hdr.PageVersion = MPI_SASPHY0_PAGEVERSION; + hdr.ExtPageLength = 0; + hdr.PageNumber = 0; + hdr.Reserved1 = 0; + hdr.Reserved2 = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; + hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY; + + cfg.cfghdr.ehdr = &hdr; + cfg.dir = 0; /* read */ + cfg.timeout = 10; + + /* Get Phy Pg 0 for each Phy. */ + cfg.physAddr = -1; + cfg.pageAddr = form + form_specific; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + + error = mpt_config(ioc, &cfg); + if (error) + goto out; + + if (!hdr.ExtPageLength) { + error = -ENXIO; + goto out; + } + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + &dma_handle); + if (!buffer) { + error = -ENOMEM; + goto out; + } + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + error = mpt_config(ioc, &cfg); + if (error) + goto out_free_consistent; + + mptsas_print_phy_pg0(buffer); + + phy_info->hw_link_rate = buffer->HwLinkRate; + phy_info->programmed_link_rate = buffer->ProgrammedLinkRate; + phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle); + phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle); + + out_free_consistent: + pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + buffer, dma_handle); + out: + return error; +} + +static int +mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, + u32 form, u32 form_specific) +{ + ConfigExtendedPageHeader_t hdr; + CONFIGPARMS cfg; + SasDevicePage0_t *buffer; + dma_addr_t dma_handle; + __le64 sas_address; + int error; + + hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION; + hdr.ExtPageLength = 0; + hdr.PageNumber = 0; + hdr.Reserved1 = 0; + hdr.Reserved2 = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; + hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE; + + cfg.cfghdr.ehdr = &hdr; + cfg.pageAddr = form + form_specific; + cfg.physAddr = -1; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; /* read */ + cfg.timeout = 10; + + error = mpt_config(ioc, &cfg); + if (error) + goto out; + if (!hdr.ExtPageLength) { + error = -ENXIO; + goto out; + } + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + &dma_handle); + if (!buffer) { + error = -ENOMEM; + goto out; + } + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + error = mpt_config(ioc, &cfg); + if (error) + goto out_free_consistent; + + mptsas_print_device_pg0(buffer); + + device_info->handle = le16_to_cpu(buffer->DevHandle); + device_info->phy_id = buffer->PhyNum; + device_info->port_id = buffer->PhysicalPort; + device_info->target = buffer->TargetID; + device_info->bus = buffer->Bus; + memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64)); + device_info->sas_address = le64_to_cpu(sas_address); + device_info->device_info = + le32_to_cpu(buffer->DeviceInfo); + + out_free_consistent: + pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + buffer, dma_handle); + out: + return error; +} + +static int +mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info, + u32 form, u32 form_specific) +{ + ConfigExtendedPageHeader_t hdr; + CONFIGPARMS cfg; + SasExpanderPage0_t *buffer; + dma_addr_t dma_handle; + int error; + + hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION; + hdr.ExtPageLength = 0; + hdr.PageNumber = 0; + hdr.Reserved1 = 0; + hdr.Reserved2 = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; + hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER; + + cfg.cfghdr.ehdr = &hdr; + cfg.physAddr = -1; + cfg.pageAddr = form + form_specific; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; /* read */ + cfg.timeout = 10; + + error = mpt_config(ioc, &cfg); + if (error) + goto out; + + if (!hdr.ExtPageLength) { + error = -ENXIO; + goto out; + } + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + &dma_handle); + if (!buffer) { + error = -ENOMEM; + goto out; + } + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + error = mpt_config(ioc, &cfg); + if (error) + goto out_free_consistent; + + /* 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(struct mptsas_phyinfo),GFP_KERNEL); + if (!port_info->phy_info) { + error = -ENOMEM; + goto out_free_consistent; + } + + out_free_consistent: + pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + buffer, dma_handle); + out: + return error; +} + +static int +mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, + u32 form, u32 form_specific) +{ + ConfigExtendedPageHeader_t hdr; + CONFIGPARMS cfg; + SasExpanderPage1_t *buffer; + dma_addr_t dma_handle; + int error; + + hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION; + hdr.ExtPageLength = 0; + hdr.PageNumber = 1; + hdr.Reserved1 = 0; + hdr.Reserved2 = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; + hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER; + + cfg.cfghdr.ehdr = &hdr; + cfg.physAddr = -1; + cfg.pageAddr = form + form_specific; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; /* read */ + cfg.timeout = 10; + + error = mpt_config(ioc, &cfg); + if (error) + goto out; + + if (!hdr.ExtPageLength) { + error = -ENXIO; + goto out; + } + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + &dma_handle); + if (!buffer) { + error = -ENOMEM; + goto out; + } + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + error = mpt_config(ioc, &cfg); + if (error) + goto out_free_consistent; + + + mptsas_print_expander_pg1(buffer); + + /* save config data */ + phy_info->phy_id = buffer->PhyIdentifier; + phy_info->port_id = buffer->PhysicalPort; + phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate; + phy_info->programmed_link_rate = buffer->ProgrammedLinkRate; + phy_info->hw_link_rate = buffer->HwLinkRate; + phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle); + phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle); + + + out_free_consistent: + pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + buffer, dma_handle); + out: + return error; +} + +static void +mptsas_parse_device_info(struct sas_identify *identify, + struct mptsas_devinfo *device_info) +{ + u16 protocols; + + identify->sas_address = device_info->sas_address; + identify->phy_identifier = device_info->phy_id; + + /* + * Fill in Phy Initiator Port Protocol. + * Bits 6:3, more than one bit can be set, fall through cases. + */ + protocols = device_info->device_info & 0x78; + identify->initiator_port_protocols = 0; + if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR) + identify->initiator_port_protocols |= SAS_PROTOCOL_SSP; + if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR) + identify->initiator_port_protocols |= SAS_PROTOCOL_STP; + if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR) + identify->initiator_port_protocols |= SAS_PROTOCOL_SMP; + if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST) + identify->initiator_port_protocols |= SAS_PROTOCOL_SATA; + + /* + * Fill in Phy Target Port Protocol. + * Bits 10:7, more than one bit can be set, fall through cases. + */ + protocols = device_info->device_info & 0x780; + identify->target_port_protocols = 0; + if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET) + identify->target_port_protocols |= SAS_PROTOCOL_SSP; + if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET) + identify->target_port_protocols |= SAS_PROTOCOL_STP; + if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET) + identify->target_port_protocols |= SAS_PROTOCOL_SMP; + if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE) + identify->target_port_protocols |= SAS_PROTOCOL_SATA; + + /* + * Fill in Attached device type. + */ + switch (device_info->device_info & + MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) { + case MPI_SAS_DEVICE_INFO_NO_DEVICE: + identify->device_type = SAS_PHY_UNUSED; + break; + case MPI_SAS_DEVICE_INFO_END_DEVICE: + identify->device_type = SAS_END_DEVICE; + break; + case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER: + identify->device_type = SAS_EDGE_EXPANDER_DEVICE; + break; + case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER: + identify->device_type = SAS_FANOUT_EXPANDER_DEVICE; + break; + } +} + +static int mptsas_probe_one_phy(struct device *dev, + struct mptsas_phyinfo *phy_info, int index) +{ + struct sas_phy *port; + int error; + + port = sas_phy_alloc(dev, index); + if (!port) + return -ENOMEM; + + port->port_identifier = phy_info->port_id; + mptsas_parse_device_info(&port->identify, &phy_info->identify); + + /* + * Set Negotiated link rate. + */ + switch (phy_info->negotiated_link_rate) { + case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED: + port->negotiated_linkrate = SAS_PHY_DISABLED; + break; + case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION: + port->negotiated_linkrate = SAS_LINK_RATE_FAILED; + break; + case MPI_SAS_IOUNIT0_RATE_1_5: + port->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS; + break; + case MPI_SAS_IOUNIT0_RATE_3_0: + port->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS; + break; + case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE: + case MPI_SAS_IOUNIT0_RATE_UNKNOWN: + default: + port->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN; + break; + } + + /* + * Set Max hardware link rate. + */ + switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { + case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5: + port->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; + break; + case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: + port->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; + break; + default: + break; + } + + /* + * Set Max programmed link rate. + */ + switch (phy_info->programmed_link_rate & + MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { + case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5: + port->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS; + break; + case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: + port->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS; + break; + default: + break; + } + + /* + * Set Min hardware link rate. + */ + switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) { + case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5: + port->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; + break; + case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: + port->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; + break; + default: + break; + } + + /* + * Set Min programmed link rate. + */ + switch (phy_info->programmed_link_rate & + MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) { + case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5: + port->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS; + break; + case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: + port->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS; + break; + default: + break; + } + + error = sas_phy_add(port); + if (error) { + sas_phy_free(port); + return error; + } + + if (phy_info->attached.handle) { + struct sas_rphy *rphy; + + rphy = sas_rphy_alloc(port); + if (!rphy) + return 0; /* non-fatal: an rphy can be added later */ + + mptsas_parse_device_info(&rphy->identify, &phy_info->attached); + error = sas_rphy_add(rphy); + if (error) { + sas_rphy_free(rphy); + return error; + } + + phy_info->rphy = rphy; + } + + return 0; +} + +static int +mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index) +{ + struct mptsas_portinfo *port_info; + u32 handle = 0xFFFF; + int error = -ENOMEM, i; + + port_info = kmalloc(sizeof(*port_info), GFP_KERNEL); + if (!port_info) + goto out; + memset(port_info, 0, sizeof(*port_info)); + + error = mptsas_sas_io_unit_pg0(ioc, port_info); + if (error) + goto out_free_port_info; + + list_add_tail(&port_info->list, &ioc->sas_topology); + + 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); + port_info->phy_info[i].identify.phy_id = + port_info->phy_info[i].phy_id; + handle = port_info->phy_info[i].identify.handle; + + if (port_info->phy_info[i].attached.handle) { + mptsas_sas_device_pg0(ioc, + &port_info->phy_info[i].attached, + (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << + MPI_SAS_DEVICE_PGAD_FORM_SHIFT), + port_info->phy_info[i].attached.handle); + } + + mptsas_probe_one_phy(&ioc->sh->shost_gendev, + &port_info->phy_info[i], *index); + (*index)++; + } + + return 0; + + out_free_port_info: + kfree(port_info); + out: + return error; +} + +static int +mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) +{ + struct mptsas_portinfo *port_info, *p; + int error = -ENOMEM, i, j; + + port_info = kmalloc(sizeof(*port_info), GFP_KERNEL); + if (!port_info) + goto out; + memset(port_info, 0, sizeof(*port_info)); + + error = mptsas_sas_expander_pg0(ioc, port_info, + (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << + MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle); + if (error) + goto out_free_port_info; + + *handle = port_info->handle; + + list_add_tail(&port_info->list, &ioc->sas_topology); + for (i = 0; i < port_info->num_phys; i++) { + struct device *parent; + + mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i], + (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM << + MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle); + + if (port_info->phy_info[i].identify.handle) { + mptsas_sas_device_pg0(ioc, + &port_info->phy_info[i].identify, + (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << + MPI_SAS_DEVICE_PGAD_FORM_SHIFT), + port_info->phy_info[i].identify.handle); + port_info->phy_info[i].identify.phy_id = + port_info->phy_info[i].phy_id; + } + + if (port_info->phy_info[i].attached.handle) { + mptsas_sas_device_pg0(ioc, + &port_info->phy_info[i].attached, + (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << + MPI_SAS_DEVICE_PGAD_FORM_SHIFT), + port_info->phy_info[i].attached.handle); + } + + /* + * If we find a parent port handle this expander is + * attached to another expander, else it hangs of the + * HBA phys. + */ + parent = &ioc->sh->shost_gendev; + list_for_each_entry(p, &ioc->sas_topology, list) { + for (j = 0; j < p->num_phys; j++) { + if (port_info->phy_info[i].identify.handle == + p->phy_info[j].attached.handle) + parent = &p->phy_info[j].rphy->dev; + } + } + + mptsas_probe_one_phy(parent, &port_info->phy_info[i], *index); + (*index)++; + } + + return 0; + + out_free_port_info: + kfree(port_info); + out: + return error; +} + +static void +mptsas_scan_sas_topology(MPT_ADAPTER *ioc) +{ + u32 handle = 0xFFFF; + int index = 0; + + mptsas_probe_hba_phys(ioc, &index); + while (!mptsas_probe_expander_phys(ioc, &handle, &index)) + ; +} + +static int +mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct Scsi_Host *sh; + MPT_SCSI_HOST *hd; + MPT_ADAPTER *ioc; + unsigned long flags; + int sz, ii; + int numSGE = 0; + int scale; + int ioc_cap; + u8 *mem; + int error=0; + int r; + + r = mpt_attach(pdev,id); + if (r) + return r; + + ioc = pci_get_drvdata(pdev); + ioc->DoneCtx = mptsasDoneCtx; + ioc->TaskCtx = mptsasTaskCtx; + ioc->InternalCtx = mptsasInternalCtx; + + /* Added sanity check on readiness of the MPT adapter. + */ + if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) { + printk(MYIOC_s_WARN_FMT + "Skipping because it's not operational!\n", + ioc->name); + return -ENODEV; + } + + if (!ioc->active) { + printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n", + ioc->name); + return -ENODEV; + } + + /* Sanity check - ensure at least 1 port is INITIATOR capable + */ + ioc_cap = 0; + for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) { + if (ioc->pfacts[ii].ProtocolFlags & + MPI_PORTFACTS_PROTOCOL_INITIATOR) + ioc_cap++; + } + + if (!ioc_cap) { + printk(MYIOC_s_WARN_FMT + "Skipping ioc=%p because SCSI Initiator mode " + "is NOT enabled!\n", ioc->name, ioc); + return 0; + } + + sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST)); + if (!sh) { + printk(MYIOC_s_WARN_FMT + "Unable to register controller with SCSI subsystem\n", + ioc->name); + return -1; + } + + spin_lock_irqsave(&ioc->FreeQlock, flags); + + /* Attach the SCSI Host to the IOC structure + */ + ioc->sh = sh; + + sh->io_port = 0; + sh->n_io_port = 0; + sh->irq = 0; + + /* set 16 byte cdb's */ + sh->max_cmd_len = 16; + + sh->max_id = ioc->pfacts->MaxDevices + 1; + + 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. + */ + sh->unique_id = ioc->id; + + INIT_LIST_HEAD(&ioc->sas_topology); + + /* Verify that we won't exceed the maximum + * number of chain buffers + * We can optimize: ZZ = req_sz/sizeof(SGE) + * For 32bit SGE's: + * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ + * + (req_sz - 64)/sizeof(SGE) + * A slightly different algorithm is required for + * 64bit SGEs. + */ + scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); + if (sizeof(dma_addr_t) == sizeof(u64)) { + numSGE = (scale - 1) * + (ioc->facts.MaxChainDepth-1) + scale + + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + + sizeof(u32)); + } else { + numSGE = 1 + (scale - 1) * + (ioc->facts.MaxChainDepth-1) + scale + + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + + sizeof(u32)); + } + + if (numSGE < sh->sg_tablesize) { + /* Reset this value */ + dprintk((MYIOC_s_INFO_FMT + "Resetting sg_tablesize to %d from %d\n", + ioc->name, numSGE, sh->sg_tablesize)); + sh->sg_tablesize = numSGE; + } + + spin_unlock_irqrestore(&ioc->FreeQlock, flags); + + hd = (MPT_SCSI_HOST *) sh->hostdata; + hd->ioc = ioc; + + /* SCSI needs scsi_cmnd lookup table! + * (with size equal to req_depth*PtrSz!) + */ + sz = ioc->req_depth * sizeof(void *); + mem = kmalloc(sz, GFP_ATOMIC); + if (mem == NULL) { + error = -ENOMEM; + goto mptsas_probe_failed; + } + + memset(mem, 0, sz); + hd->ScsiLookup = (struct scsi_cmnd **) mem; + + dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", + ioc->name, hd->ScsiLookup, sz)); + + /* Allocate memory for the device structures. + * A non-Null pointer at an offset + * indicates a device exists. + * max_id = 1 + maximum id (hosts.h) + */ + sz = sh->max_id * sizeof(void *); + mem = kmalloc(sz, GFP_ATOMIC); + if (mem == NULL) { + error = -ENOMEM; + goto mptsas_probe_failed; + } + + memset(mem, 0, sz); + hd->Targets = (VirtDevice **) mem; + + dprintk((KERN_INFO + " Targets @ %p, sz=%d\n", hd->Targets, sz)); + + /* Clear the TM flags + */ + hd->tmPending = 0; + hd->tmState = TM_STATE_NONE; + hd->resetPending = 0; + hd->abortSCpnt = NULL; + + /* Clear the pointer used to store + * single-threaded commands, i.e., those + * issued during a bus scan, dv and + * configuration pages. + */ + hd->cmdPtr = NULL; + + /* Initialize this SCSI Hosts' timers + * To use, set the timer expires field + * and add_timer + */ + init_timer(&hd->timer); + hd->timer.data = (unsigned long) hd; + hd->timer.function = mptscsih_timer_expired; + + hd->mpt_pq_filter = mpt_pq_filter; + ioc->sas_data.ptClear = mpt_pt_clear; + + if (ioc->sas_data.ptClear==1) { + mptbase_sas_persist_operation( + ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT); + } + + ddvprintk((MYIOC_s_INFO_FMT + "mpt_pq_filter %x mpt_pq_filter %x\n", + ioc->name, + mpt_pq_filter, + mpt_pq_filter)); + + 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 + "scsi_add_host failed\n")); + goto mptsas_probe_failed; + } + + mptsas_scan_sas_topology(ioc); + + return 0; + +mptsas_probe_failed: + + mptscsih_remove(pdev); + return error; +} + +static void __devexit mptsas_remove(struct pci_dev *pdev) +{ + MPT_ADAPTER *ioc = pci_get_drvdata(pdev); + struct mptsas_portinfo *p, *n; + + sas_remove_host(ioc->sh); + + list_for_each_entry_safe(p, n, &ioc->sas_topology, list) { + list_del(&p->list); + kfree(p); + } + + mptscsih_remove(pdev); +} + +static struct pci_device_id mptsas_pci_table[] = { + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E, + PCI_ANY_ID, PCI_ANY_ID }, + {0} /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(pci, mptsas_pci_table); + + +static struct pci_driver mptsas_driver = { + .name = "mptsas", + .id_table = mptsas_pci_table, + .probe = mptsas_probe, + .remove = __devexit_p(mptsas_remove), + .shutdown = mptscsih_shutdown, +#ifdef CONFIG_PM + .suspend = mptscsih_suspend, + .resume = mptscsih_resume, +#endif +}; + +static int __init +mptsas_init(void) +{ + show_mptmod_ver(my_NAME, my_VERSION); + + mptsas_transport_template = + sas_attach_transport(&mptsas_transport_functions); + if (!mptsas_transport_template) + return -ENODEV; + + mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER); + mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER); + mptsasInternalCtx = + mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); + + if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) { + devtprintk((KERN_INFO MYNAM + ": Registered for IOC event notifications\n")); + } + + if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) { + dprintk((KERN_INFO MYNAM + ": Registered for IOC reset notifications\n")); + } + + return pci_register_driver(&mptsas_driver); +} + +static void __exit +mptsas_exit(void) +{ + pci_unregister_driver(&mptsas_driver); + sas_release_transport(mptsas_transport_template); + + mpt_reset_deregister(mptsasDoneCtx); + mpt_event_deregister(mptsasDoneCtx); + + mpt_deregister(mptsasInternalCtx); + mpt_deregister(mptsasTaskCtx); + mpt_deregister(mptsasDoneCtx); +} + +module_init(mptsas_init); +module_exit(mptsas_exit); diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index b9d4f78725b4..5cb07eb224d7 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -62,6 +62,7 @@ #include <scsi/scsi_device.h> #include <scsi/scsi_host.h> #include <scsi/scsi_tcq.h> +#include <scsi/scsi_dbg.h> #include "mptbase.h" #include "mptscsih.h" @@ -93,8 +94,9 @@ typedef struct _BIG_SENSE_BUF { #define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */ #define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */ -#define MPT_ICFLAG_PHYS_DISK 0x04 /* Any SCSI IO but do Phys Disk Format */ -#define MPT_ICFLAG_TAGGED_CMD 0x08 /* Do tagged IO */ +#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 */ @@ -159,6 +161,8 @@ int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum); +static struct work_struct mptscsih_persistTask; + #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io); static void mptscsih_domainValidation(void *hd); @@ -167,6 +171,7 @@ static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id); static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target); static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage); static void mptscsih_fillbuf(char *buffer, int size, int index, int width); +static void mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id); #endif void mptscsih_remove(struct pci_dev *); @@ -281,12 +286,12 @@ mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex) offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer; chain_idx = offset / ioc->req_sz; rc = SUCCESS; - dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n", - ioc->name, *retIndex, chainBuf)); + dsgprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n", + ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx)); } else { rc = FAILED; chain_idx = MPT_HOST_NO_CHAIN; - dfailprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer failed\n", + dfailprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer failed\n", ioc->name)); } spin_unlock_irqrestore(&ioc->FreeQlock, flags); @@ -432,7 +437,7 @@ nextSGEset: */ pReq->ChainOffset = 0; RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03; - dsgprintk((MYIOC_s_ERR_FMT + dsgprintk((MYIOC_s_INFO_FMT "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset)); ioc->RequestNB[req_idx] = RequestNB; } @@ -491,11 +496,12 @@ nextSGEset: /* NOTE: psge points to the beginning of the chain element * in current buffer. Get a chain buffer. */ - dsgprintk((MYIOC_s_INFO_FMT - "calling getFreeChainBuffer SCSI cmd=%02x (%p)\n", - ioc->name, pReq->CDB[0], SCpnt)); - if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) + if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) { + dfailprintk((MYIOC_s_INFO_FMT + "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n", + ioc->name, pReq->CDB[0], SCpnt)); return FAILED; + } /* Update the tracking arrays. * If chainSge == NULL, update ReqToChain, else ChainToChain @@ -577,14 +583,20 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) return 1; } - dmfprintk((MYIOC_s_INFO_FMT - "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n", - ioc->name, mf, mr, sc, req_idx)); - sc->result = DID_OK << 16; /* Set default reply as OK */ pScsiReq = (SCSIIORequest_t *) mf; pScsiReply = (SCSIIOReply_t *) mr; + if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){ + dmfprintk((MYIOC_s_INFO_FMT + "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n", + ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag)); + }else{ + dmfprintk((MYIOC_s_INFO_FMT + "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n", + ioc->name, mf, mr, sc, req_idx)); + } + if (pScsiReply == NULL) { /* special context reply handling */ ; @@ -599,11 +611,24 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); sc->resid = sc->request_bufflen - xfer_cnt; + /* + * if we get a data underrun indication, yet no data was + * transferred and the SCSI status indicates that the + * command was never started, change the data underrun + * to success + */ + if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 && + (scsi_status == MPI_SCSI_STATUS_BUSY || + scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT || + scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) { + 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, pScsiReq->TargetID, pScsiReq->LUN[1], - status, scsi_state, scsi_status, sc->resid, + status, scsi_state, scsi_status, sc->resid, sc->request_bufflen, xfer_cnt)); if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) @@ -612,8 +637,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) /* * Look for + dump FCP ResponseInfo[]! */ - if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) { - printk(KERN_NOTICE " FCP_ResponseInfo=%08xh\n", + if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID && + pScsiReply->ResponseInfo) { + printk(KERN_NOTICE "ha=%d id=%d lun=%d: " + "FCP_ResponseInfo=%08xh\n", + ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1], le32_to_cpu(pScsiReply->ResponseInfo)); } @@ -654,21 +682,13 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) break; case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ - if ( xfer_cnt >= sc->underflow ) { - /* Sufficient data transfer occurred */ + sc->resid = sc->request_bufflen - xfer_cnt; + if((xfer_cnt==0)||(sc->underflow > xfer_cnt)) + sc->result=DID_SOFT_ERROR << 16; + else /* Sufficient data transfer occurred */ sc->result = (DID_OK << 16) | scsi_status; - } else if ( xfer_cnt == 0 ) { - /* A CRC Error causes this condition; retry */ - sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | - (CHECK_CONDITION << 1); - sc->sense_buffer[0] = 0x70; - sc->sense_buffer[2] = NO_SENSE; - sc->sense_buffer[12] = 0; - sc->sense_buffer[13] = 0; - } else { - sc->result = DID_SOFT_ERROR << 16; - } - dreplyprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target)); + dreplyprintk((KERN_NOTICE + "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id)); break; case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ @@ -683,7 +703,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) ; } else { if (xfer_cnt < sc->underflow) { - sc->result = DID_SOFT_ERROR << 16; + if (scsi_status == SAM_STAT_BUSY) + sc->result = SAM_STAT_BUSY; + else + sc->result = DID_SOFT_ERROR << 16; } if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) { /* What to do? @@ -708,8 +731,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ - scsi_status = pScsiReply->SCSIStatus; - sc->result = (DID_OK << 16) | scsi_status; + if (scsi_status == MPI_SCSI_STATUS_BUSY) + sc->result = (DID_BUS_BUSY << 16) | scsi_status; + else + sc->result = (DID_OK << 16) | scsi_status; if (scsi_state == 0) { ; } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) { @@ -796,7 +821,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) return 1; } - /* * mptscsih_flush_running_cmds - For each command found, search * Scsi_Host instance taskQ and reply to OS. @@ -882,12 +906,13 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun) SCSIIORequest_t *mf = NULL; int ii; int max = hd->ioc->req_depth; + struct scsi_cmnd *sc; dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n", target, lun, max)); for (ii=0; ii < max; ii++) { - if (hd->ScsiLookup[ii] != NULL) { + if ((sc = hd->ScsiLookup[ii]) != NULL) { mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii); @@ -902,9 +927,22 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun) hd->ScsiLookup[ii] = NULL; mptscsih_freeChainBuffers(hd->ioc, ii); mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf); + if (sc->use_sg) { + pci_unmap_sg(hd->ioc->pcidev, + (struct scatterlist *) sc->request_buffer, + sc->use_sg, + sc->sc_data_direction); + } else if (sc->request_bufflen) { + pci_unmap_single(hd->ioc->pcidev, + sc->SCp.dma_handle, + sc->request_bufflen, + sc->sc_data_direction); + } + sc->host_scribble = NULL; + sc->result = DID_NO_CONNECT << 16; + sc->scsi_done(sc); } } - return; } @@ -959,8 +997,10 @@ mptscsih_remove(struct pci_dev *pdev) unsigned long flags; int sz1; - if(!host) + if(!host) { + mpt_detach(pdev); return; + } scsi_remove_host(host); @@ -1017,7 +1057,7 @@ mptscsih_remove(struct pci_dev *pdev) scsi_host_put(host); mpt_detach(pdev); - + } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1072,7 +1112,7 @@ mptscsih_resume(struct pci_dev *pdev) MPT_SCSI_HOST *hd; mpt_resume(pdev); - + if(!host) return 0; @@ -1214,8 +1254,8 @@ mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t off int size = 0; if (func) { - /* - * write is not supported + /* + * write is not supported */ } else { if (start) @@ -1248,8 +1288,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) MPT_SCSI_HOST *hd; MPT_FRAME_HDR *mf; SCSIIORequest_t *pScsiReq; - VirtDevice *pTarget; - int target; + VirtDevice *pTarget = SCpnt->device->hostdata; int lun; u32 datalen; u32 scsictl; @@ -1259,12 +1298,9 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) int ii; hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; - target = SCpnt->device->id; lun = SCpnt->device->lun; SCpnt->scsi_done = done; - pTarget = hd->Targets[target]; - dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n", (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done)); @@ -1307,7 +1343,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) /* Default to untagged. Once a target structure has been allocated, * use the Inquiry data to determine if device supports tagged. */ - if ( pTarget + if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES) && (SCpnt->device->tagged_supported)) { scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ; @@ -1317,8 +1353,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) target; - pScsiReq->Bus = (u8) SCpnt->device->channel; + pScsiReq->TargetID = (u8) pTarget->target_id; + pScsiReq->Bus = pTarget->bus_id; pScsiReq->ChainOffset = 0; pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; pScsiReq->CDBLength = SCpnt->cmd_len; @@ -1370,7 +1406,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION if (hd->ioc->bus_type == SCSI) { - int dvStatus = hd->ioc->spi_data.dvStatus[target]; + int dvStatus = hd->ioc->spi_data.dvStatus[pTarget->target_id]; int issueCmd = 1; if (dvStatus || hd->ioc->spi_data.forceDv) { @@ -1418,6 +1454,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) return 0; fail: + hd->ScsiLookup[my_idx] = NULL; mptscsih_freeChainBuffers(hd->ioc, my_idx); mpt_free_msg_frame(hd->ioc, mf); return SCSI_MLQUEUE_HOST_BUSY; @@ -1535,17 +1572,17 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in */ if (mptscsih_tm_pending_wait(hd) == FAILED) { if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { - dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler abort: " + dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: " "Timed out waiting for last TM (%d) to complete! \n", hd->ioc->name, hd->tmPending)); return FAILED; } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { - dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler 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)); return FAILED; } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { - dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler bus reset: " + 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)) @@ -1631,8 +1668,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) { dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n", hd->ioc->name)); - //return FAILED; - return -999; + return FAILED; } dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n", hd->ioc->name, mf)); @@ -1661,9 +1697,8 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun 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); @@ -1707,24 +1742,23 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) MPT_FRAME_HDR *mf; u32 ctx2abort; int scpnt_idx; + int retval; /* If we can't locate our host adapter structure, return FAILED status. */ if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) { SCpnt->result = DID_RESET << 16; SCpnt->scsi_done(SCpnt); - dfailprintk((KERN_WARNING MYNAM ": mptscsih_abort: " + dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: " "Can't locate host! (sc=%p)\n", SCpnt)); return FAILED; } ioc = hd->ioc; - if (hd->resetPending) + if (hd->resetPending) { return FAILED; - - printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n", - hd->ioc->name, SCpnt); + } if (hd->timeouts < -1) hd->timeouts++; @@ -1732,16 +1766,20 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) /* Find this command */ if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { - /* Cmd not found in ScsiLookup. + /* Cmd not found in ScsiLookup. * Do OS callback. */ SCpnt->result = DID_RESET << 16; - dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " + dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: " "Command not in the active list! (sc=%p)\n", hd->ioc->name, SCpnt)); return SUCCESS; } + printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n", + hd->ioc->name, SCpnt); + scsi_print_command(SCpnt); + /* Most important! Set TaskMsgContext to SCpnt's MsgContext! * (the IO to be ABORT'd) * @@ -1754,38 +1792,22 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) hd->abortSCpnt = SCpnt; - if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, + retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun, - ctx2abort, 2 /* 2 second timeout */) - < 0) { + ctx2abort, 2 /* 2 second timeout */); - /* The TM request failed and the subsequent FW-reload failed! - * Fatal error case. - */ - printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n", - hd->ioc->name, SCpnt); + printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", + hd->ioc->name, + ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); - /* We must clear our pending flag before clearing our state. - */ + if (retval == 0) + return SUCCESS; + + if(retval != FAILED ) { hd->tmPending = 0; hd->tmState = TM_STATE_NONE; - - /* Unmap the DMA buffers, if any. */ - if (SCpnt->use_sg) { - pci_unmap_sg(ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer, - SCpnt->use_sg, SCpnt->sc_data_direction); - } else if (SCpnt->request_bufflen) { - pci_unmap_single(ioc->pcidev, SCpnt->SCp.dma_handle, - SCpnt->request_bufflen, SCpnt->sc_data_direction); - } - hd->ScsiLookup[scpnt_idx] = NULL; - SCpnt->result = DID_RESET << 16; - SCpnt->scsi_done(SCpnt); /* Issue the command callback */ - mptscsih_freeChainBuffers(ioc, scpnt_idx); - mpt_free_msg_frame(ioc, mf); - return FAILED; } - return SUCCESS; + return FAILED; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1801,11 +1823,12 @@ int mptscsih_dev_reset(struct scsi_cmnd * SCpnt) { MPT_SCSI_HOST *hd; + int retval; /* If we can't locate our host adapter structure, return FAILED status. */ if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){ - dtmprintk((KERN_WARNING MYNAM ": mptscsih_dev_reset: " + dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: " "Can't locate host! (sc=%p)\n", SCpnt)); return FAILED; @@ -1814,24 +1837,26 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) if (hd->resetPending) return FAILED; - printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n", + printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n", hd->ioc->name, SCpnt); + scsi_print_command(SCpnt); - if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, + retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, SCpnt->device->channel, SCpnt->device->id, - 0, 0, 5 /* 5 second timeout */) - < 0){ - /* The TM request failed and the subsequent FW-reload failed! - * Fatal error case. - */ - printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n", - hd->ioc->name, SCpnt); + 0, 0, 5 /* 5 second timeout */); + + printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n", + hd->ioc->name, + ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); + + if (retval == 0) + return SUCCESS; + + if(retval != FAILED ) { hd->tmPending = 0; hd->tmState = TM_STATE_NONE; - return FAILED; } - - return SUCCESS; + return FAILED; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1847,41 +1872,39 @@ int mptscsih_bus_reset(struct scsi_cmnd * SCpnt) { MPT_SCSI_HOST *hd; - spinlock_t *host_lock = SCpnt->device->host->host_lock; + int retval; /* If we can't locate our host adapter structure, return FAILED status. */ if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){ - dtmprintk((KERN_WARNING MYNAM ": mptscsih_bus_reset: " + dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: " "Can't locate host! (sc=%p)\n", SCpnt ) ); return FAILED; } - printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n", + printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n", hd->ioc->name, SCpnt); + scsi_print_command(SCpnt); if (hd->timeouts < -1) hd->timeouts++; - /* We are now ready to execute the task management request. */ - if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */) - < 0){ + retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, + SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */); - /* The TM request failed and the subsequent FW-reload failed! - * Fatal error case. - */ - printk(MYIOC_s_WARN_FMT - "Error processing TaskMgmt request (sc=%p)\n", - hd->ioc->name, SCpnt); + printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n", + hd->ioc->name, + ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); + + if (retval == 0) + return SUCCESS; + + if(retval != FAILED ) { hd->tmPending = 0; hd->tmState = TM_STATE_NONE; - spin_lock_irq(host_lock); - return FAILED; } - - return SUCCESS; + return FAILED; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1902,13 +1925,13 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt) /* If we can't locate the host to reset, then we failed. */ if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){ - dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: " + dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: " "Can't locate host! (sc=%p)\n", SCpnt ) ); return FAILED; } - printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)\n", + printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n", hd->ioc->name, SCpnt); /* If our attempts to reset the host failed, then return a failed @@ -1924,7 +1947,7 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt) hd->tmState = TM_STATE_NONE; } - dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: " + dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: " "Status = %s\n", (status == SUCCESS) ? "SUCCESS" : "FAILED" ) ); @@ -1951,8 +1974,8 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd) if (hd->tmState == TM_STATE_NONE) { hd->tmState = TM_STATE_IN_PROGRESS; hd->tmPending = 1; - status = SUCCESS; spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + status = SUCCESS; break; } spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); @@ -1980,7 +2003,7 @@ mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ) spin_lock_irqsave(&hd->ioc->FreeQlock, flags); if(hd->tmPending == 0) { status = SUCCESS; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); break; } spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); @@ -2163,7 +2186,7 @@ mptscsih_slave_alloc(struct scsi_device *device) vdev->raidVolume = 0; hd->Targets[device->id] = vdev; if (hd->ioc->bus_type == SCSI) { - if (hd->ioc->spi_data.isRaid & (1 << device->id)) { + if (hd->ioc->raid_data.isRaid & (1 << device->id)) { vdev->raidVolume = 1; ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", device->id)); @@ -2174,22 +2197,7 @@ mptscsih_slave_alloc(struct scsi_device *device) out: vdev->num_luns++; - return 0; -} - -static int -mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id) -{ - int i; - - if (!hd->ioc->spi_data.isRaid || !hd->ioc->spi_data.pIocPg3) - return 0; - - for (i = 0; i < hd->ioc->spi_data.pIocPg3->NumPhysDisks; i++) { - if (id == hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID) - return 1; - } - + device->hostdata = vdev; return 0; } @@ -2220,7 +2228,7 @@ mptscsih_slave_destroy(struct scsi_device *device) hd->Targets[target] = NULL; if (hd->ioc->bus_type == SCSI) { - if (mptscsih_is_raid_volume(hd, target)) { + if (mptscsih_is_phys_disk(hd->ioc, target)) { hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3; } else { hd->ioc->spi_data.dvStatus[target] = @@ -2318,10 +2326,10 @@ mptscsih_slave_configure(struct scsi_device *device) if (pTarget == NULL) { /* Driver doesn't know about this device. * Kernel may generate a "Dummy Lun 0" which - * may become a real Lun if a + * may become a real Lun if a * "scsi add-single-device" command is executed - * while the driver is active (hot-plug a - * device). LSI Raid controllers need + * while the driver is active (hot-plug a + * device). LSI Raid controllers need * queue_depth set to DEV_HIGH for this reason. */ scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG, @@ -2433,6 +2441,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) { MPT_SCSI_HOST *hd; unsigned long flags; + int ii; dtmprintk((KERN_WARNING MYNAM ": IOC %s_reset routed to SCSI host driver!\n", @@ -2490,11 +2499,8 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) /* ScsiLookup initialization */ - { - int ii; - for (ii=0; ii < hd->ioc->req_depth; ii++) - hd->ScsiLookup[ii] = NULL; - } + for (ii=0; ii < hd->ioc->req_depth; ii++) + hd->ScsiLookup[ii] = NULL; /* 2. Chain Buffer initialization */ @@ -2543,6 +2549,16 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* work queue thread to clear the persitency table */ +static void +mptscsih_sas_persist_clear_table(void * arg) +{ + MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; + + mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) { @@ -2552,18 +2568,18 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", ioc->name, event)); + if (ioc->sh == NULL || + ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) + return 1; + switch (event) { case MPI_EVENT_UNIT_ATTENTION: /* 03 */ /* FIXME! */ break; case MPI_EVENT_IOC_BUS_RESET: /* 04 */ case MPI_EVENT_EXT_BUS_RESET: /* 05 */ - hd = NULL; - if (ioc->sh) { - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1)) - hd->soft_resets++; - } + if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1)) + hd->soft_resets++; break; case MPI_EVENT_LOGOUT: /* 09 */ /* FIXME! */ @@ -2582,69 +2598,24 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) break; case MPI_EVENT_INTEGRATED_RAID: /* 0B */ + { + pMpiEventDataRaid_t pRaidEventData = + (pMpiEventDataRaid_t) pEvReply->Data; #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION - /* negoNvram set to 0 if DV enabled and to USE_NVRAM if - * if DV disabled. Need to check for target mode. - */ - hd = NULL; - if (ioc->sh) - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - - if (hd && (ioc->bus_type == SCSI) && (hd->negoNvram == 0)) { - ScsiCfgData *pSpi; - Ioc3PhysDisk_t *pPDisk; - int numPDisk; - u8 reason; - u8 physDiskNum; - - reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16; - if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) { - /* New or replaced disk. - * Set DV flag and schedule DV. - */ - pSpi = &ioc->spi_data; - physDiskNum = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24; - ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum)); - if (pSpi->pIocPg3) { - pPDisk = pSpi->pIocPg3->PhysDisk; - numPDisk =pSpi->pIocPg3->NumPhysDisks; - - while (numPDisk) { - if (physDiskNum == pPDisk->PhysDiskNum) { - pSpi->dvStatus[pPDisk->PhysDiskID] = (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE); - pSpi->forceDv = MPT_SCSICFG_NEED_DV; - ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID)); - break; - } - pPDisk++; - numPDisk--; - } - - if (numPDisk == 0) { - /* The physical disk that needs DV was not found - * in the stored IOC Page 3. The driver must reload - * this page. DV routine will set the NEED_DV flag for - * all phys disks that have DV_NOT_DONE set. - */ - pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; - ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum)); - } - } - } - } + /* Domain Validation Needed */ + if (ioc->bus_type == SCSI && + pRaidEventData->ReasonCode == + MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) + mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum); #endif + break; + } -#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) - printk("Raid Event RF: "); - { - u32 *m = (u32 *)pEvReply; - int ii; - int n = (int)pEvReply->MsgLength; - for (ii=6; ii < n; ii++) - printk(" %08x", le32_to_cpu(m[ii])); - printk("\n"); - } -#endif + /* Persistent table is full. */ + case MPI_EVENT_PERSISTENT_TABLE_FULL: + INIT_WORK(&mptscsih_persistTask, + mptscsih_sas_persist_clear_table,(void *)ioc); + schedule_work(&mptscsih_persistTask); break; case MPI_EVENT_NONE: /* 00 */ @@ -2681,7 +2652,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char * { int indexed_lun, lun_index; VirtDevice *vdev; - ScsiCfgData *pSpi; + SpiCfgData *pSpi; char data_56; dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n", @@ -2691,7 +2662,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char * * If the peripheral qualifier filter is enabled then if the target reports a 0x1 * (i.e. The targer is capable of supporting the specified peripheral device type * on this logical unit; however, the physical device is not currently connected - * to this logical unit) it will be converted to a 0x3 (i.e. The target is not + * to this logical unit) it will be converted to a 0x3 (i.e. The target is not * capable of supporting a physical device on this logical unit). This is to work * around a bug in th emid-layer in some distributions in which the mid-layer will * continue to try to communicate to the LUN and evntually create a dummy LUN. @@ -2788,7 +2759,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char * static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56) { - ScsiCfgData *pspi_data = &hd->ioc->spi_data; + SpiCfgData *pspi_data = &hd->ioc->spi_data; int id = (int) target->target_id; int nvram; VirtDevice *vdev; @@ -2967,11 +2938,13 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56) static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq) { + MPT_ADAPTER *ioc = hd->ioc; u8 cmd; - ScsiCfgData *pSpi; + SpiCfgData *pSpi; - ddvtprintk((" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n", - pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0])); + ddvtprintk((MYIOC_s_NOTE_FMT + " set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n", + hd->ioc->name, pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0])); if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0)) return; @@ -2979,12 +2952,12 @@ mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq) cmd = pReq->CDB[0]; if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) { - pSpi = &hd->ioc->spi_data; - if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) { + pSpi = &ioc->spi_data; + if ((ioc->raid_data.isRaid & (1 << pReq->TargetID)) && ioc->raid_data.pIocPg3) { /* Set NEED_DV for all hidden disks */ - Ioc3PhysDisk_t *pPDisk = pSpi->pIocPg3->PhysDisk; - int numPDisk = pSpi->pIocPg3->NumPhysDisks; + Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; + int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; while (numPDisk) { pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV; @@ -2998,6 +2971,50 @@ mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq) } } +/* mptscsih_raid_set_dv_flags() + * + * New or replaced disk. Set DV flag and schedule DV. + */ +static void +mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id) +{ + MPT_ADAPTER *ioc = hd->ioc; + SpiCfgData *pSpi = &ioc->spi_data; + Ioc3PhysDisk_t *pPDisk; + int numPDisk; + + if (hd->negoNvram != 0) + return; + + ddvtprintk(("DV requested for phys disk id %d\n", id)); + if (ioc->raid_data.pIocPg3) { + pPDisk = ioc->raid_data.pIocPg3->PhysDisk; + numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; + while (numPDisk) { + if (id == pPDisk->PhysDiskNum) { + pSpi->dvStatus[pPDisk->PhysDiskID] = + (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE); + pSpi->forceDv = MPT_SCSICFG_NEED_DV; + ddvtprintk(("NEED_DV set for phys disk id %d\n", + pPDisk->PhysDiskID)); + break; + } + pPDisk++; + numPDisk--; + } + + if (numPDisk == 0) { + /* The physical disk that needs DV was not found + * in the stored IOC Page 3. The driver must reload + * this page. DV routine will set the NEED_DV flag for + * all phys disks that have DV_NOT_DONE set. + */ + pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; + ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id)); + } + } +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * If no Target, bus reset on 1st I/O. Set the flag to @@ -3085,7 +3102,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags) MPT_ADAPTER *ioc = hd->ioc; Config_t *pReq; SCSIDevicePage1_t *pData; - VirtDevice *pTarget; + VirtDevice *pTarget=NULL; MPT_FRAME_HDR *mf; dma_addr_t dataDma; u16 req_idx; @@ -3184,7 +3201,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags) #endif if (flags & MPT_SCSICFG_BLK_NEGO) - negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC; + negoFlags |= MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC; mptscsih_setDevicePage1Flags(width, factor, offset, &requested, &configuration, negoFlags); @@ -3194,8 +3211,8 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags) /* Get a MF for this command. */ if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { - dprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n", - ioc->name)); + dfailprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n", + ioc->name)); return -EAGAIN; } @@ -3289,7 +3306,7 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus) /* Get a MF for this command. */ if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { - dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n", + dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n", ioc->name)); return -EAGAIN; } @@ -3447,7 +3464,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) * some type of error occurred. */ MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr; - if (pr->ActionStatus == MPI_RAID_ACTION_ASTATUS_SUCCESS) + if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS) completionCode = MPT_SCANDV_GOOD; else completionCode = MPT_SCANDV_SOME_ERROR; @@ -3955,7 +3972,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum) header1.PageLength = ioc->spi_data.sdp1length; header1.PageNumber = 1; header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; - cfg.hdr = &header1; + cfg.cfghdr.hdr = &header1; cfg.physAddr = cfg1_dma_addr; cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; cfg.dir = 1; @@ -3996,16 +4013,16 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum) dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC " "offset=0 negoFlags=%x request=%x config=%x\n", id, flags, requested, configuration)); - pcfg1Data->RequestedParameters = le32_to_cpu(requested); + pcfg1Data->RequestedParameters = cpu_to_le32(requested); pcfg1Data->Reserved = 0; - pcfg1Data->Configuration = le32_to_cpu(configuration); + pcfg1Data->Configuration = cpu_to_le32(configuration); cfg.pageAddr = (bus<<8) | id; mpt_config(hd->ioc, &cfg); } /* If target Ptr NULL or if this target is NOT a disk, skip. */ - if ((pTarget) && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)){ + if ((pTarget) && (pTarget->inq_data[0] == TYPE_DISK)){ for (lun=0; lun <= MPT_LAST_LUN; lun++) { /* If LUN present, issue the command */ @@ -4100,9 +4117,9 @@ mptscsih_domainValidation(void *arg) if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) { mpt_read_ioc_pg_3(ioc); - if (ioc->spi_data.pIocPg3) { - Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk; - int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks; + if (ioc->raid_data.pIocPg3) { + Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; + int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; while (numPDisk) { if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE) @@ -4141,7 +4158,7 @@ mptscsih_domainValidation(void *arg) isPhysDisk = mptscsih_is_phys_disk(ioc, id); if (isPhysDisk) { for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { - if (hd->ioc->spi_data.isRaid & (1 << ii)) { + if (hd->ioc->raid_data.isRaid & (1 << ii)) { hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING; } } @@ -4160,7 +4177,7 @@ mptscsih_domainValidation(void *arg) if (isPhysDisk) { for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { - if (hd->ioc->spi_data.isRaid & (1 << ii)) { + if (hd->ioc->raid_data.isRaid & (1 << ii)) { hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING; } } @@ -4182,21 +4199,21 @@ mptscsih_domainValidation(void *arg) /* Search IOC page 3 to determine if this is hidden physical disk */ -static int +/* Search IOC page 3 to determine if this is hidden physical disk + */ +static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) { - if (ioc->spi_data.pIocPg3) { - Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk; - int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks; + int i; - while (numPDisk) { - if (pPDisk->PhysDiskID == id) { - return 1; - } - pPDisk++; - numPDisk--; - } + if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3) + return 0; + + for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { + if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) + return 1; } + return 0; } @@ -4353,7 +4370,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) /* Prep cfg structure */ cfg.pageAddr = (bus<<8) | id; - cfg.hdr = NULL; + cfg.cfghdr.hdr = NULL; /* Prep SDP0 header */ @@ -4399,10 +4416,10 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz); cfg1_dma_addr = dvbuf_dma + sz; - /* Skip this ID? Set cfg.hdr to force config page write + /* Skip this ID? Set cfg.cfghdr.hdr to force config page write */ { - ScsiCfgData *pspi_data = &hd->ioc->spi_data; + SpiCfgData *pspi_data = &hd->ioc->spi_data; if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { /* Set the factor from nvram */ nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8; @@ -4417,7 +4434,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) dv.cmd = MPT_SET_MAX; mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); - cfg.hdr = &header1; + cfg.cfghdr.hdr = &header1; /* Save the final negotiated settings to * SCSI device page 1. @@ -4432,11 +4449,11 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) } /* Finish iocmd inititialization - hidden or visible disk? */ - if (ioc->spi_data.pIocPg3) { + if (ioc->raid_data.pIocPg3) { /* Search IOC page 3 for matching id */ - Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk; - int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks; + Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; + int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; while (numPDisk) { if (pPDisk->PhysDiskID == id) { @@ -4460,7 +4477,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) /* RAID Volume ID's may double for a physical device. If RAID but * not a physical ID as well, skip DV. */ - if ((hd->ioc->spi_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK)) + if ((hd->ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK)) goto target_done; @@ -4483,7 +4500,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) dv.cmd = MPT_SET_MIN; mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); - cfg.hdr = &header1; + cfg.cfghdr.hdr = &header1; cfg.physAddr = cfg1_dma_addr; cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; cfg.dir = 1; @@ -4596,8 +4613,8 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) if ((pbuf1[56] & 0x02) == 0) { pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS; hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS; - ddvprintk((MYIOC_s_NOTE_FMT - "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n", + ddvprintk((MYIOC_s_NOTE_FMT + "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n", ioc->name, id, pbuf1[56])); } } @@ -4637,7 +4654,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) u32 sdp0_info; u32 sdp0_nego; - cfg.hdr = &header0; + cfg.cfghdr.hdr = &header0; cfg.physAddr = cfg0_dma_addr; cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; cfg.dir = 0; @@ -4673,7 +4690,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) if (!firstPass) doFallback = 1; } else { - ddvprintk((MYIOC_s_NOTE_FMT + ddvprintk((MYIOC_s_NOTE_FMT "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id)); hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE; mptscsih_initTarget(hd, @@ -4689,8 +4706,8 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) } else if (rc == MPT_SCANDV_ISSUE_SENSE) doFallback = 1; /* set fallback flag */ - else if ((rc == MPT_SCANDV_DID_RESET) || - (rc == MPT_SCANDV_SENSE) || + else if ((rc == MPT_SCANDV_DID_RESET) || + (rc == MPT_SCANDV_SENSE) || (rc == MPT_SCANDV_FALLBACK)) doFallback = 1; /* set fallback flag */ else @@ -4722,7 +4739,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) * 4) release * 5) update nego parms to target struct */ - cfg.hdr = &header1; + cfg.cfghdr.hdr = &header1; cfg.physAddr = cfg1_dma_addr; cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; cfg.dir = 1; @@ -4809,6 +4826,8 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) notDone = 0; if (iocmd.flags & MPT_ICFLAG_ECHO) { bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3]; + if (pbuf1[0] & 0x01) + iocmd.flags |= MPT_ICFLAG_EBOS; } else { bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3]; } @@ -4905,6 +4924,9 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) } iocmd.flags &= ~MPT_ICFLAG_DID_RESET; + if (iocmd.flags & MPT_ICFLAG_EBOS) + goto skip_Reserve; + repeat = 5; while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) { iocmd.cmd = RESERVE; @@ -4948,6 +4970,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) } } +skip_Reserve: mptscsih_fillbuf(pbuf1, sz, patt, 1); iocmd.cmd = WRITE_BUFFER; iocmd.data_dma = buf1_dma; @@ -5121,12 +5144,12 @@ target_done: /* Set if cfg1_dma_addr contents is valid */ - if ((cfg.hdr != NULL) && (retcode == 0)){ + if ((cfg.cfghdr.hdr != NULL) && (retcode == 0)){ /* If disk, not U320, disable QAS */ if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) { hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS; - ddvprintk((MYIOC_s_NOTE_FMT + ddvprintk((MYIOC_s_NOTE_FMT "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor)); } @@ -5137,7 +5160,7 @@ target_done: * skip save of the final negotiated settings to * SCSI device page 1. * - cfg.hdr = &header1; + cfg.cfghdr.hdr = &header1; cfg.physAddr = cfg1_dma_addr; cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; cfg.dir = 1; @@ -5192,11 +5215,12 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) * If not an LVD bus, the adapter minSyncFactor has been * already throttled back. */ + negoFlags = hd->ioc->spi_data.noQas; if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) { width = pTarget->maxWidth; offset = pTarget->maxOffset; factor = pTarget->minSyncFactor; - negoFlags = pTarget->negoFlags; + negoFlags |= pTarget->negoFlags; } else { if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { data = hd->ioc->spi_data.nvram[id]; @@ -5217,7 +5241,6 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) } /* Set the negotiation flags */ - negoFlags = hd->ioc->spi_data.noQas; if (!width) negoFlags |= MPT_TARGET_NO_NEGO_WIDE; @@ -5248,7 +5271,7 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) /* Update tmax values with those from Device Page 0.*/ pPage0 = (SCSIDevicePage0_t *) pPage; if (pPage0) { - val = cpu_to_le32(pPage0->NegotiatedParameters); + val = le32_to_cpu(pPage0->NegotiatedParameters); dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0; dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16; dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8; @@ -5276,12 +5299,12 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) dv->now.offset, &val, &configuration, dv->now.flags); dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n", id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration)); - pPage1->RequestedParameters = le32_to_cpu(val); + pPage1->RequestedParameters = cpu_to_le32(val); pPage1->Reserved = 0; - pPage1->Configuration = le32_to_cpu(configuration); + pPage1->Configuration = cpu_to_le32(configuration); } - ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x request=%x configuration=%x\n", + ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x configuration=%x\n", id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration)); break; @@ -5301,9 +5324,9 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) offset, &val, &configuration, negoFlags); dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n", id, width, factor, offset, negoFlags, val, configuration)); - pPage1->RequestedParameters = le32_to_cpu(val); + pPage1->RequestedParameters = cpu_to_le32(val); pPage1->Reserved = 0; - pPage1->Configuration = le32_to_cpu(configuration); + pPage1->Configuration = cpu_to_le32(configuration); } ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n", id, width, factor, offset, val, configuration, negoFlags)); @@ -5377,12 +5400,12 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) if (pPage1) { mptscsih_setDevicePage1Flags (width, factor, offset, &val, &configuration, dv->now.flags); - dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x flags=%x request=%x config=%x\n", + dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x request=%x config=%x\n", id, width, offset, factor, dv->now.flags, val, configuration)); - pPage1->RequestedParameters = le32_to_cpu(val); + pPage1->RequestedParameters = cpu_to_le32(val); pPage1->Reserved = 0; - pPage1->Configuration = le32_to_cpu(configuration); + pPage1->Configuration = cpu_to_le32(configuration); } ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n", diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 51c0255ac16e..971fda4b8b57 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -1,5 +1,5 @@ /* - * linux/drivers/message/fusion/mptscsi.h + * linux/drivers/message/fusion/mptscsih.h * High performance SCSI / Fibre Channel SCSI Host device driver. * For use with PCI chip/adapter(s): * LSIFC9xx/LSI409xx Fibre Channel @@ -53,8 +53,8 @@ * SCSI Public stuff... */ -#define MPT_SCSI_CMD_PER_DEV_HIGH 31 -#define MPT_SCSI_CMD_PER_DEV_LOW 7 +#define MPT_SCSI_CMD_PER_DEV_HIGH 64 +#define MPT_SCSI_CMD_PER_DEV_LOW 32 #define MPT_SCSI_CMD_PER_LUN 7 @@ -77,6 +77,7 @@ #define MPTSCSIH_MAX_WIDTH 1 #define MPTSCSIH_MIN_SYNC 0x08 #define MPTSCSIH_SAF_TE 0 +#define MPTSCSIH_PT_CLEAR 0 #endif diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index dfa8806b1e13..5c0e307d1d5d 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -162,15 +162,15 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) u8 *mem; int error=0; int r; - + if ((r = mpt_attach(pdev,id)) != 0) return r; - + ioc = pci_get_drvdata(pdev); ioc->DoneCtx = mptspiDoneCtx; ioc->TaskCtx = mptspiTaskCtx; ioc->InternalCtx = mptspiInternalCtx; - + /* Added sanity check on readiness of the MPT adapter. */ if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) { @@ -199,7 +199,7 @@ mptspi_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(&mptspi_driver_template, sizeof(MPT_SCSI_HOST)); |