diff --git a/Documentation/scsi/ChangeLog.megaraid b/Documentation/scsi/ChangeLog.megaraid index a056bbe67c7ea22627b044b02bf19ed3426421d9..37796fe45bd00a0a31fa9bc4a3a6a12decbe1606 100644 --- a/Documentation/scsi/ChangeLog.megaraid +++ b/Documentation/scsi/ChangeLog.megaraid @@ -1,3 +1,19 @@ +Release Date : Thu Nov 16 15:32:35 EST 2006 - + Sumant Patro +Current Version : 2.20.5.1 (scsi module), 2.20.2.6 (cmm module) +Older Version : 2.20.4.9 (scsi module), 2.20.2.6 (cmm module) + +1. Changes in Initialization to fix kdump failure. + Send SYNC command on loading. + This command clears the pending commands in the adapter + and re-initialize its internal RAID structure. + Without this change, megaraid driver either panics or fails to + initialize the adapter during kdump's second kernel boot + if there are pending commands or interrupts from other devices + sharing the same IRQ. +2. Authors email-id domain name changed from lsil.com to lsi.com. + Also modified the MODULE_AUTHOR to megaraidlinux@lsi.com + Release Date : Fri May 19 09:31:45 EST 2006 - Seokmann Ju Current Version : 2.20.4.9 (scsi module), 2.20.2.6 (cmm module) Older Version : 2.20.4.8 (scsi module), 2.20.2.6 (cmm module) diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 6ad28dfb146908ec490b1c3657e70dcca75604b8..7b2fa3d8f61c0522b0bb6ff07c2e4de6199b31c3 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -1373,8 +1373,7 @@ static bool DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T Controller->BounceBufferLimit = DAC690_V2_PciDmaMask; /* This is a temporary dma mapping, used only in the scope of this function */ - CommandMailbox = - (DAC960_V2_CommandMailbox_T *)pci_alloc_consistent( PCI_Device, + CommandMailbox = pci_alloc_consistent(PCI_Device, sizeof(DAC960_V2_CommandMailbox_T), &CommandMailboxDMA); if (CommandMailbox == NULL) return false; @@ -1879,8 +1878,8 @@ static bool DAC960_V2_ReadControllerConfiguration(DAC960_Controller_T if (NewLogicalDeviceInfo->LogicalDeviceState != DAC960_V2_LogicalDevice_Offline) Controller->LogicalDriveInitiallyAccessible[LogicalDeviceNumber] = true; - LogicalDeviceInfo = (DAC960_V2_LogicalDeviceInfo_T *) - kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T), GFP_ATOMIC); + LogicalDeviceInfo = kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T), + GFP_ATOMIC); if (LogicalDeviceInfo == NULL) return DAC960_Failure(Controller, "LOGICAL DEVICE ALLOCATION"); Controller->V2.LogicalDeviceInformation[LogicalDeviceNumber] = @@ -2113,8 +2112,8 @@ static bool DAC960_V2_ReadDeviceConfiguration(DAC960_Controller_T if (!DAC960_V2_NewPhysicalDeviceInfo(Controller, Channel, TargetID, LogicalUnit)) break; - PhysicalDeviceInfo = (DAC960_V2_PhysicalDeviceInfo_T *) - kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC); + PhysicalDeviceInfo = kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), + GFP_ATOMIC); if (PhysicalDeviceInfo == NULL) return DAC960_Failure(Controller, "PHYSICAL DEVICE ALLOCATION"); Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex] = @@ -2122,8 +2121,8 @@ static bool DAC960_V2_ReadDeviceConfiguration(DAC960_Controller_T memcpy(PhysicalDeviceInfo, NewPhysicalDeviceInfo, sizeof(DAC960_V2_PhysicalDeviceInfo_T)); - InquiryUnitSerialNumber = (DAC960_SCSI_Inquiry_UnitSerialNumber_T *) - kmalloc(sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), GFP_ATOMIC); + InquiryUnitSerialNumber = kmalloc( + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), GFP_ATOMIC); if (InquiryUnitSerialNumber == NULL) { kfree(PhysicalDeviceInfo); return DAC960_Failure(Controller, "SERIAL NUMBER ALLOCATION"); @@ -4949,8 +4948,8 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command) PhysicalDevice.LogicalUnit = NewLogicalDeviceInfo->LogicalUnit; Controller->V2.LogicalDriveToVirtualDevice[LogicalDeviceNumber] = PhysicalDevice; - LogicalDeviceInfo = (DAC960_V2_LogicalDeviceInfo_T *) - kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T), GFP_ATOMIC); + LogicalDeviceInfo = kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T), + GFP_ATOMIC); Controller->V2.LogicalDeviceInformation[LogicalDeviceNumber] = LogicalDeviceInfo; DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) " @@ -5709,14 +5708,14 @@ static bool DAC960_CheckStatusBuffer(DAC960_Controller_T *Controller, unsigned int NewStatusBufferLength = DAC960_InitialStatusBufferSize; while (NewStatusBufferLength < ByteCount) NewStatusBufferLength *= 2; - Controller->CombinedStatusBuffer = - (unsigned char *) kmalloc(NewStatusBufferLength, GFP_ATOMIC); + Controller->CombinedStatusBuffer = kmalloc(NewStatusBufferLength, + GFP_ATOMIC); if (Controller->CombinedStatusBuffer == NULL) return false; Controller->CombinedStatusBufferLength = NewStatusBufferLength; return true; } - NewStatusBuffer = (unsigned char *) - kmalloc(2 * Controller->CombinedStatusBufferLength, GFP_ATOMIC); + NewStatusBuffer = kmalloc(2 * Controller->CombinedStatusBufferLength, + GFP_ATOMIC); if (NewStatusBuffer == NULL) { DAC960_Warning("Unable to expand Combined Status Buffer - Truncating\n", diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index ea31d84705107ca361d7cc0d59992a0aca3e97a3..71037f91c222611e8d9933d441fb29a4337f4096 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig @@ -66,7 +66,7 @@ config FUSION_MAX_SGE config FUSION_CTL tristate "Fusion MPT misc device (ioctl) driver" - depends on FUSION_SPI || FUSION_FC + depends on FUSION_SPI || FUSION_FC || FUSION_SAS ---help--- The Fusion MPT misc device driver provides specialized control of MPT adapters via system ioctl calls. Use of ioctl calls to diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile index 341691390e86370bec5ccfd37b73b8aa9266c92d..6003b46c8438163367695238695171c3d59cb8e7 100644 --- a/drivers/message/fusion/Makefile +++ b/drivers/message/fusion/Makefile @@ -8,6 +8,9 @@ #EXTRA_CFLAGS += -DMPT_DEBUG_INIT #EXTRA_CFLAGS += -DMPT_DEBUG_EXIT #EXTRA_CFLAGS += -DMPT_DEBUG_FAIL +#EXTRA_CFLAGS += -DMPT_DEBUG_DV +#EXTRA_CFLAGS += -DMPT_DEBUG_TM +#EXTRA_CFLAGS += -DMPT_DEBUG_REPLY # # driver/module specifics... @@ -20,11 +23,7 @@ #CFLAGS_mptbase.o += -DMPT_DEBUG_RESET # # For mptscsih: -#CFLAGS_mptscsih.o += -DMPT_DEBUG_DV -#CFLAGS_mptscsih.o += -DMPT_DEBUG_NEGO -#CFLAGS_mptscsih.o += -DMPT_DEBUG_TM #CFLAGS_mptscsih.o += -DMPT_DEBUG_SCSI -#CFLAGS_mptscsih.o += -DMPT_DEBUG_REPLY # # For mptctl: #CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h index 81ad77622dacee63e3b0aa23054d12eadd087812..75223bf24ae86fa8449e19976d09518ba51f7deb 100644 --- a/drivers/message/fusion/lsi/mpi.h +++ b/drivers/message/fusion/lsi/mpi.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2005 LSI Logic Corporation. + * Copyright (c) 2000-2006 LSI Logic Corporation. * * * Name: mpi.h * Title: MPI Message independent structures and definitions * Creation Date: July 27, 2000 * - * mpi.h Version: 01.05.11 + * mpi.h Version: 01.05.12 * * Version History * --------------- @@ -77,6 +77,7 @@ * 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT. * 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target. * 03-27-06 01.05.11 Bumped MPI_HEADER_VERSION_UNIT. + * 10-11-06 01.05.12 Bumped MPI_HEADER_VERSION_UNIT. * -------------------------------------------------------------------------- */ @@ -107,7 +108,7 @@ /* Note: The major versions of 0xe0 through 0xff are reserved */ /* versioning for this MPI header set */ -#define MPI_HEADER_VERSION_UNIT (0x0D) +#define MPI_HEADER_VERSION_UNIT (0x0E) #define MPI_HEADER_VERSION_DEV (0x00) #define MPI_HEADER_VERSION_UNIT_MASK (0xFF00) #define MPI_HEADER_VERSION_UNIT_SHIFT (8) diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h index 47e13e360c10aea30975a44c18e4f9ca36319288..0e4c8e77a81dc7efcc8dbf39f1cd4bf0282a57a1 100644 --- a/drivers/message/fusion/lsi/mpi_cnfg.h +++ b/drivers/message/fusion/lsi/mpi_cnfg.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2005 LSI Logic Corporation. + * Copyright (c) 2000-2006 LSI Logic Corporation. * * * Name: mpi_cnfg.h * Title: MPI Config message, structures, and Pages * Creation Date: July 27, 2000 * - * mpi_cnfg.h Version: 01.05.12 + * mpi_cnfg.h Version: 01.05.13 * * Version History * --------------- @@ -276,6 +276,23 @@ * Added AdditionalControlFlags, MaxTargetPortConnectTime, * ReportDeviceMissingDelay, and IODeviceMissingDelay * fields to SAS IO Unit Page 1. + * 10-11-06 01.05.13 Added NumForceWWID field and ForceWWID array to + * Manufacturing Page 5. + * Added Manufacturing pages 8 through 10. + * Added defines for supported metadata size bits in + * CapabilitiesFlags field of IOC Page 6. + * Added defines for metadata size bits in VolumeSettings + * field of RAID Volume Page 0. + * Added SATA Link Reset settings, Enable SATA Asynchronous + * Notification bit, and HideNonZeroAttachedPhyIdentifiers + * bit to AdditionalControlFlags field of SAS IO Unit + * Page 1. + * Added defines for Enclosure Devices Unmapped and + * Device Limit Exceeded bits in Status field of SAS IO + * Unit Page 2. + * Added more AccessStatus values for SAS Device Page 0. + * Added bit for SATA Asynchronous Notification Support in + * Flags field of SAS Device Page 0. * -------------------------------------------------------------------------- */ @@ -654,17 +671,24 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4 #define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA (0x01) +#ifndef MPI_MANPAGE5_NUM_FORCEWWID +#define MPI_MANPAGE5_NUM_FORCEWWID (1) +#endif + typedef struct _CONFIG_PAGE_MANUFACTURING_5 { CONFIG_PAGE_HEADER Header; /* 00h */ U64 BaseWWID; /* 04h */ U8 Flags; /* 0Ch */ - U8 Reserved1; /* 0Dh */ + U8 NumForceWWID; /* 0Dh */ U16 Reserved2; /* 0Eh */ + U32 Reserved3; /* 10h */ + U32 Reserved4; /* 14h */ + U64 ForceWWID[MPI_MANPAGE5_NUM_FORCEWWID]; /* 18h */ } CONFIG_PAGE_MANUFACTURING_5, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_5, ManufacturingPage5_t, MPI_POINTER pManufacturingPage5_t; -#define MPI_MANUFACTURING5_PAGEVERSION (0x01) +#define MPI_MANUFACTURING5_PAGEVERSION (0x02) /* defines for the Flags field */ #define MPI_MANPAGE5_TWO_WWID_PER_PHY (0x01) @@ -740,6 +764,36 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_7 #define MPI_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001) +typedef struct _CONFIG_PAGE_MANUFACTURING_8 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 ProductSpecificInfo;/* 04h */ +} CONFIG_PAGE_MANUFACTURING_8, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_8, + ManufacturingPage8_t, MPI_POINTER pManufacturingPage8_t; + +#define MPI_MANUFACTURING8_PAGEVERSION (0x00) + + +typedef struct _CONFIG_PAGE_MANUFACTURING_9 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 ProductSpecificInfo;/* 04h */ +} CONFIG_PAGE_MANUFACTURING_9, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_9, + ManufacturingPage9_t, MPI_POINTER pManufacturingPage9_t; + +#define MPI_MANUFACTURING6_PAGEVERSION (0x00) + + +typedef struct _CONFIG_PAGE_MANUFACTURING_10 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 ProductSpecificInfo;/* 04h */ +} CONFIG_PAGE_MANUFACTURING_10, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_10, + ManufacturingPage10_t, MPI_POINTER pManufacturingPage10_t; + +#define MPI_MANUFACTURING10_PAGEVERSION (0x00) + + /**************************************************************************** * IO Unit Config Pages ****************************************************************************/ @@ -1080,10 +1134,14 @@ typedef struct _CONFIG_PAGE_IOC_6 } CONFIG_PAGE_IOC_6, MPI_POINTER PTR_CONFIG_PAGE_IOC_6, IOCPage6_t, MPI_POINTER pIOCPage6_t; -#define MPI_IOCPAGE6_PAGEVERSION (0x00) +#define MPI_IOCPAGE6_PAGEVERSION (0x01) /* IOC Page 6 Capabilities Flags */ +#define MPI_IOCPAGE6_CAP_FLAGS_MASK_METADATA_SIZE (0x00000006) +#define MPI_IOCPAGE6_CAP_FLAGS_64MB_METADATA_SIZE (0x00000000) +#define MPI_IOCPAGE6_CAP_FLAGS_512MB_METADATA_SIZE (0x00000002) + #define MPI_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE (0x00000001) @@ -2160,6 +2218,11 @@ typedef struct _RAID_VOL0_SETTINGS #define MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE (0x0004) #define MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC (0x0008) #define MPI_RAIDVOL0_SETTING_FAST_DATA_SCRUBBING_0102 (0x0020) /* obsolete */ + +#define MPI_RAIDVOL0_SETTING_MASK_METADATA_SIZE (0x00C0) +#define MPI_RAIDVOL0_SETTING_64MB_METADATA_SIZE (0x0000) +#define MPI_RAIDVOL0_SETTING_512MB_METADATA_SIZE (0x0040) + #define MPI_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX (0x0010) #define MPI_RAIDVOL0_SETTING_USE_DEFAULTS (0x8000) @@ -2203,7 +2266,7 @@ typedef struct _CONFIG_PAGE_RAID_VOL_0 } CONFIG_PAGE_RAID_VOL_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_0, RaidVolumePage0_t, MPI_POINTER pRaidVolumePage0_t; -#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x06) +#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x07) /* values for RAID Volume Page 0 InactiveStatus field */ #define MPI_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00) @@ -2518,7 +2581,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1 } CONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1, SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t; -#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x06) +#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x07) /* values for SAS IO Unit Page 1 ControlFlags */ #define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000) @@ -2544,7 +2607,13 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1 #define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001) /* values for SAS IO Unit Page 1 AdditionalControlFlags */ -#define MPI_SAS_IOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001) +#define MPI_SAS_IOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION (0x0040) +#define MPI_SAS_IOUNIT1_ACONTROL_HIDE_NONZERO_ATTACHED_PHY_IDENT (0x0020) +#define MPI_SAS_IOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET (0x0010) +#define MPI_SAS_IOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET (0x0008) +#define MPI_SAS_IOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET (0x0004) +#define MPI_SAS_IOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET (0x0002) +#define MPI_SAS_IOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001) /* defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */ #define MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK (0x7F) @@ -2585,9 +2654,11 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2 } CONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2, SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t; -#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x05) +#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x06) /* values for SAS IO Unit Page 2 Status field */ +#define MPI_SAS_IOUNIT2_STATUS_DEVICE_LIMIT_EXCEEDED (0x08) +#define MPI_SAS_IOUNIT2_STATUS_ENCLOSURE_DEVICES_UNMAPPED (0x04) #define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02) #define MPI_SAS_IOUNIT2_STATUS_FULL_PERSISTENT_MAPPINGS (0x01) @@ -2739,24 +2810,38 @@ typedef struct _CONFIG_PAGE_SAS_DEVICE_0 } CONFIG_PAGE_SAS_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_0, SasDevicePage0_t, MPI_POINTER pSasDevicePage0_t; -#define MPI_SASDEVICE0_PAGEVERSION (0x04) +#define MPI_SASDEVICE0_PAGEVERSION (0x05) /* values for SAS Device Page 0 AccessStatus field */ -#define MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00) -#define MPI_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01) -#define MPI_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02) +#define MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00) +#define MPI_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01) +#define MPI_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02) +#define MPI_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT (0x03) +/* specific values for SATA Init failures */ +#define MPI_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN (0x10) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT (0x11) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_DIAG (0x12) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION (0x13) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER (0x14) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_PIO_SN (0x15) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN (0x16) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN (0x17) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION (0x18) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE (0x19) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_MAX (0x1F) /* values for SAS Device Page 0 Flags field */ -#define MPI_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE (0x0200) -#define MPI_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE (0x0100) -#define MPI_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED (0x0080) -#define MPI_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED (0x0040) -#define MPI_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020) -#define MPI_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010) -#define MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008) -#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT (0x0004) -#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED (0x0002) -#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001) +#define MPI_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY (0x0400) +#define MPI_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE (0x0200) +#define MPI_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE (0x0100) +#define MPI_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED (0x0080) +#define MPI_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED (0x0040) +#define MPI_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020) +#define MPI_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010) +#define MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008) +#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT (0x0004) +#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED (0x0002) +#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001) /* see mpi_sas.h for values for SAS Device Page 0 DeviceInfo values */ diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt index 582cfe7c2aa10a81b823aeda0d025e0bd7687431..d6b4c607453bdde0cd1179e40cab7786e52ee231 100644 --- a/drivers/message/fusion/lsi/mpi_history.txt +++ b/drivers/message/fusion/lsi/mpi_history.txt @@ -3,28 +3,28 @@ MPI Header File Change History ============================== - Copyright (c) 2000-2005 LSI Logic Corporation. + Copyright (c) 2000-2006 LSI Logic Corporation. --------------------------------------- - Header Set Release Version: 01.05.13 - Header Set Release Date: 03-27-06 + Header Set Release Version: 01.05.14 + Header Set Release Date: 10-11-06 --------------------------------------- Filename Current version Prior version ---------- --------------- ------------- - mpi.h 01.05.11 01.05.10 - mpi_ioc.h 01.05.11 01.05.10 - mpi_cnfg.h 01.05.12 01.05.11 - mpi_init.h 01.05.07 01.05.06 - mpi_targ.h 01.05.06 01.05.05 + mpi.h 01.05.12 01.05.11 + mpi_ioc.h 01.05.12 01.05.11 + mpi_cnfg.h 01.05.13 01.05.12 + mpi_init.h 01.05.08 01.05.07 + mpi_targ.h 01.05.06 01.05.06 mpi_fc.h 01.05.01 01.05.01 mpi_lan.h 01.05.01 01.05.01 mpi_raid.h 01.05.02 01.05.02 mpi_tool.h 01.05.03 01.05.03 mpi_inb.h 01.05.01 01.05.01 - mpi_sas.h 01.05.03 01.05.02 + mpi_sas.h 01.05.04 01.05.03 mpi_type.h 01.05.02 01.05.02 - mpi_history.txt 01.05.13 01.05.12 + mpi_history.txt 01.05.14 01.05.13 * Date Version Description @@ -94,6 +94,7 @@ mpi.h * 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT. * 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target. * 03-27-06 01.05.11 Bumped MPI_HEADER_VERSION_UNIT. + * 10-11-06 01.05.12 Bumped MPI_HEADER_VERSION_UNIT. * -------------------------------------------------------------------------- mpi_ioc.h @@ -182,6 +183,14 @@ mpi_ioc.h * Added MPI_EVENT_SAS_INIT_TABLE_OVERFLOW and event * data structure. * Added MPI_EXT_IMAGE_TYPE_INITIALIZATION. + * 10-11-06 01.05.12 Added MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED. + * Added MaxInitiators field to PortFacts reply. + * Added SAS Device Status Change ReasonCode for + * asynchronous notificaiton. + * Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event + * data structure. + * Added new ImageType values for FWDownload and FWUpload + * requests. * -------------------------------------------------------------------------- mpi_cnfg.h @@ -447,6 +456,23 @@ mpi_cnfg.h * Added AdditionalControlFlags, MaxTargetPortConnectTime, * ReportDeviceMissingDelay, and IODeviceMissingDelay * fields to SAS IO Unit Page 1. + * 10-11-06 01.05.13 Added NumForceWWID field and ForceWWID array to + * Manufacturing Page 5. + * Added Manufacturing pages 8 through 10. + * Added defines for supported metadata size bits in + * CapabilitiesFlags field of IOC Page 6. + * Added defines for metadata size bits in VolumeSettings + * field of RAID Volume Page 0. + * Added SATA Link Reset settings, Enable SATA Asynchronous + * Notification bit, and HideNonZeroAttachedPhyIdentifiers + * bit to AdditionalControlFlags field of SAS IO Unit + * Page 1. + * Added defines for Enclosure Devices Unmapped and + * Device Limit Exceeded bits in Status field of SAS IO + * Unit Page 2. + * Added more AccessStatus values for SAS Device Page 0. + * Added bit for SATA Asynchronous Notification Support in + * Flags field of SAS Device Page 0. * -------------------------------------------------------------------------- mpi_init.h @@ -490,6 +516,7 @@ mpi_init.h * 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them * unique in the first 32 characters. * 03-27-06 01.05.07 Added Task Management type of Clear ACA. + * 10-11-06 01.05.08 Shortened define for Task Management type of Clear ACA. * -------------------------------------------------------------------------- mpi_targ.h @@ -638,6 +665,8 @@ mpi_sas.h * and Remove Device operations to SAS IO Unit Control. * Added DevHandle field to SAS IO Unit Control request and * reply. + * 10-11-06 01.05.04 Fixed the name of a define for Operation field of SAS IO + * Unit Control request. * -------------------------------------------------------------------------- mpi_type.h @@ -653,20 +682,20 @@ mpi_type.h mpi_history.txt Parts list history -Filename 01.05.13 01.05.12 01.05.11 01.05.10 01.05.09 ----------- -------- -------- -------- -------- -------- -mpi.h 01.05.11 01.05.10 01.05.09 01.05.08 01.05.07 -mpi_ioc.h 01.05.11 01.05.10 01.05.09 01.05.09 01.05.08 -mpi_cnfg.h 01.05.12 01.05.11 01.05.10 01.05.09 01.05.08 -mpi_init.h 01.05.07 01.05.06 01.05.06 01.05.05 01.05.04 -mpi_targ.h 01.05.06 01.05.05 01.05.05 01.05.05 01.05.04 -mpi_fc.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 -mpi_lan.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 -mpi_raid.h 01.05.02 01.05.02 01.05.02 01.05.02 01.05.02 -mpi_tool.h 01.05.03 01.05.03 01.05.03 01.05.03 01.05.03 -mpi_inb.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 -mpi_sas.h 01.05.03 01.05.02 01.05.01 01.05.01 01.05.01 -mpi_type.h 01.05.02 01.05.02 01.05.01 01.05.01 01.05.01 +Filename 01.05.13 01.05.13 01.05.12 01.05.11 01.05.10 01.05.09 +---------- -------- -------- -------- -------- -------- -------- +mpi.h 01.05.12 01.05.11 01.05.10 01.05.09 01.05.08 01.05.07 +mpi_ioc.h 01.05.12 01.05.11 01.05.10 01.05.09 01.05.09 01.05.08 +mpi_cnfg.h 01.05.13 01.05.12 01.05.11 01.05.10 01.05.09 01.05.08 +mpi_init.h 01.05.08 01.05.07 01.05.06 01.05.06 01.05.05 01.05.04 +mpi_targ.h 01.05.06 01.05.06 01.05.05 01.05.05 01.05.05 01.05.04 +mpi_fc.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 +mpi_lan.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 +mpi_raid.h 01.05.02 01.05.02 01.05.02 01.05.02 01.05.02 01.05.02 +mpi_tool.h 01.05.03 01.05.03 01.05.03 01.05.03 01.05.03 01.05.03 +mpi_inb.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 +mpi_sas.h 01.05.04 01.05.03 01.05.02 01.05.01 01.05.01 01.05.01 +mpi_type.h 01.05.02 01.05.02 01.05.02 01.05.01 01.05.01 01.05.01 Filename 01.05.08 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03 ---------- -------- -------- -------- -------- -------- -------- diff --git a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h index c1c678989a2370335d548d2facd15d70970446df..ec9dff2249a7f429e12bbbedb22f45dc7f7f70d3 100644 --- a/drivers/message/fusion/lsi/mpi_init.h +++ b/drivers/message/fusion/lsi/mpi_init.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2005 LSI Logic Corporation. + * Copyright (c) 2000-2006 LSI Logic Corporation. * * * Name: mpi_init.h * Title: MPI initiator mode messages and structures * Creation Date: June 8, 2000 * - * mpi_init.h Version: 01.05.07 + * mpi_init.h Version: 01.05.08 * * Version History * --------------- @@ -53,6 +53,7 @@ * 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them * unique in the first 32 characters. * 03-27-06 01.05.07 Added Task Management type of Clear ACA. + * 10-11-06 01.05.08 Shortened define for Task Management type of Clear ACA. * -------------------------------------------------------------------------- */ @@ -428,7 +429,7 @@ typedef struct _MSG_SCSI_TASK_MGMT #define MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05) #define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06) #define MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07) -#define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_ACA (0x08) +#define MPI_SCSITASKMGMT_TASKTYPE_CLR_ACA (0x08) /* MsgFlags bits */ #define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION (0x00) diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h index 18ba407fd3998093694c58c5b2f313aba6cbe008..6c33e335337557c65c452e26abaec840449e254c 100644 --- a/drivers/message/fusion/lsi/mpi_ioc.h +++ b/drivers/message/fusion/lsi/mpi_ioc.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2005 LSI Logic Corporation. + * Copyright (c) 2000-2006 LSI Logic Corporation. * * * Name: mpi_ioc.h * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages * Creation Date: August 11, 2000 * - * mpi_ioc.h Version: 01.05.11 + * mpi_ioc.h Version: 01.05.12 * * Version History * --------------- @@ -98,6 +98,14 @@ * Added MPI_EVENT_SAS_INIT_TABLE_OVERFLOW and event * data structure. * Added MPI_EXT_IMAGE_TYPE_INITIALIZATION. + * 10-11-06 01.05.12 Added MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED. + * Added MaxInitiators field to PortFacts reply. + * Added SAS Device Status Change ReasonCode for + * asynchronous notificaiton. + * Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event + * data structure. + * Added new ImageType values for FWDownload and FWUpload + * requests. * -------------------------------------------------------------------------- */ @@ -264,6 +272,7 @@ typedef struct _MSG_IOC_FACTS_REPLY #define MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002) #define MPI_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004) #define MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL (0x0008) +#define MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED (0x0010) #define MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT (0x01) #define MPI_IOCFACTS_FLAGS_REPLY_FIFO_HOST_SIGNAL (0x02) @@ -328,7 +337,8 @@ typedef struct _MSG_PORT_FACTS_REPLY U16 MaxPostedCmdBuffers; /* 1Ch */ U16 MaxPersistentIDs; /* 1Eh */ U16 MaxLanBuckets; /* 20h */ - U16 Reserved4; /* 22h */ + U8 MaxInitiators; /* 22h */ + U8 Reserved4; /* 23h */ U32 Reserved5; /* 24h */ } MSG_PORT_FACTS_REPLY, MPI_POINTER PTR_MSG_PORT_FACTS_REPLY, PortFactsReply_t, MPI_POINTER pPortFactsReply_t; @@ -487,6 +497,7 @@ typedef struct _MSG_EVENT_ACK_REPLY #define MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x00000018) #define MPI_EVENT_SAS_INIT_TABLE_OVERFLOW (0x00000019) #define MPI_EVENT_SAS_SMP_ERROR (0x0000001A) +#define MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE (0x0000001B) #define MPI_EVENT_LOG_ENTRY_ADDED (0x00000021) /* AckRequired field values */ @@ -593,6 +604,7 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE #define MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A) #define MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B) #define MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C) +#define MPI_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION (0x0D) /* SCSI Event data for Queue Full event */ @@ -895,6 +907,54 @@ typedef struct _EVENT_DATA_SAS_INIT_TABLE_OVERFLOW MpiEventDataSasInitTableOverflow_t, MPI_POINTER pMpiEventDataSasInitTableOverflow_t; +/* SAS Expander Status Change Event data */ + +typedef struct _EVENT_DATA_SAS_EXPANDER_STATUS_CHANGE +{ + U8 ReasonCode; /* 00h */ + U8 Reserved1; /* 01h */ + U16 Reserved2; /* 02h */ + U8 PhysicalPort; /* 04h */ + U8 Reserved3; /* 05h */ + U16 EnclosureHandle; /* 06h */ + U64 SASAddress; /* 08h */ + U32 DiscoveryStatus; /* 10h */ + U16 DevHandle; /* 14h */ + U16 ParentDevHandle; /* 16h */ + U16 ExpanderChangeCount; /* 18h */ + U16 ExpanderRouteIndexes; /* 1Ah */ + U8 NumPhys; /* 1Ch */ + U8 SASLevel; /* 1Dh */ + U8 Flags; /* 1Eh */ + U8 Reserved4; /* 1Fh */ +} EVENT_DATA_SAS_EXPANDER_STATUS_CHANGE, + MPI_POINTER PTR_EVENT_DATA_SAS_EXPANDER_STATUS_CHANGE, + MpiEventDataSasExpanderStatusChange_t, + MPI_POINTER pMpiEventDataSasExpanderStatusChange_t; + +/* values for ReasonCode field of SAS Expander Status Change Event data */ +#define MPI_EVENT_SAS_EXP_RC_ADDED (0x00) +#define MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING (0x01) + +/* values for DiscoveryStatus field of SAS Expander Status Change Event data */ +#define MPI_EVENT_SAS_EXP_DS_LOOP_DETECTED (0x00000001) +#define MPI_EVENT_SAS_EXP_DS_UNADDRESSABLE_DEVICE (0x00000002) +#define MPI_EVENT_SAS_EXP_DS_MULTIPLE_PORTS (0x00000004) +#define MPI_EVENT_SAS_EXP_DS_EXPANDER_ERR (0x00000008) +#define MPI_EVENT_SAS_EXP_DS_SMP_TIMEOUT (0x00000010) +#define MPI_EVENT_SAS_EXP_DS_OUT_ROUTE_ENTRIES (0x00000020) +#define MPI_EVENT_SAS_EXP_DS_INDEX_NOT_EXIST (0x00000040) +#define MPI_EVENT_SAS_EXP_DS_SMP_FUNCTION_FAILED (0x00000080) +#define MPI_EVENT_SAS_EXP_DS_SMP_CRC_ERROR (0x00000100) +#define MPI_EVENT_SAS_EXP_DS_SUBTRACTIVE_LINK (0x00000200) +#define MPI_EVENT_SAS_EXP_DS_TABLE_LINK (0x00000400) +#define MPI_EVENT_SAS_EXP_DS_UNSUPPORTED_DEVICE (0x00000800) + +/* values for Flags field of SAS Expander Status Change Event data */ +#define MPI_EVENT_SAS_EXP_FLAGS_ROUTE_TABLE_CONFIG (0x02) +#define MPI_EVENT_SAS_EXP_FLAGS_CONFIG_IN_PROGRESS (0x01) + + /***************************************************************************** * @@ -926,6 +986,10 @@ typedef struct _MSG_FW_DOWNLOAD #define MPI_FW_DOWNLOAD_ITYPE_BIOS (0x02) #define MPI_FW_DOWNLOAD_ITYPE_NVDATA (0x03) #define MPI_FW_DOWNLOAD_ITYPE_BOOTLOADER (0x04) +#define MPI_FW_DOWNLOAD_ITYPE_MANUFACTURING (0x06) +#define MPI_FW_DOWNLOAD_ITYPE_CONFIG_1 (0x07) +#define MPI_FW_DOWNLOAD_ITYPE_CONFIG_2 (0x08) +#define MPI_FW_DOWNLOAD_ITYPE_MEGARAID (0x09) typedef struct _FWDownloadTCSGE @@ -980,6 +1044,11 @@ typedef struct _MSG_FW_UPLOAD #define MPI_FW_UPLOAD_ITYPE_NVDATA (0x03) #define MPI_FW_UPLOAD_ITYPE_BOOTLOADER (0x04) #define MPI_FW_UPLOAD_ITYPE_FW_BACKUP (0x05) +#define MPI_FW_UPLOAD_ITYPE_MANUFACTURING (0x06) +#define MPI_FW_UPLOAD_ITYPE_CONFIG_1 (0x07) +#define MPI_FW_UPLOAD_ITYPE_CONFIG_2 (0x08) +#define MPI_FW_UPLOAD_ITYPE_MEGARAID (0x09) +#define MPI_FW_UPLOAD_ITYPE_COMPLETE (0x0A) typedef struct _FWUploadTCSGE { diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h index 871ebc08b706133de56ea0ef96f5b248dda12aff..635bbe04513e44ac04893c5b0a3609fdd63d3e9c 100644 --- a/drivers/message/fusion/lsi/mpi_log_sas.h +++ b/drivers/message/fusion/lsi/mpi_log_sas.h @@ -1,4 +1,3 @@ - /*************************************************************************** * * * Copyright 2003 LSI Logic Corporation. All rights reserved. * @@ -14,7 +13,7 @@ #define IOPI_IOCLOGINFO_H_INCLUDED #define SAS_LOGINFO_NEXUS_LOSS 0x31170000 -#define SAS_LOGINFO_MASK 0xFFFF0000 +#define SAS_LOGINFO_MASK 0xFFFF0000 /****************************************************************************/ /* IOC LOGINFO defines, 0x00000000 - 0x0FFFFFFF */ @@ -43,129 +42,172 @@ /****************************************************************************/ /* IOP LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IOP */ /****************************************************************************/ -#define IOP_LOGINFO_CODE_INVALID_SAS_ADDRESS (0x00010000) -#define IOP_LOGINFO_CODE_UNUSED2 (0x00020000) -#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x00030000) -#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_RT (0x00030100) /* Route Table Entry not found */ -#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PN (0x00030200) /* Invalid Page Number */ -#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x00030300) /* Invalid FORM */ -#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x00030400) /* Invalid Page Type */ -#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM (0x00030500) /* Device Not Mapped */ -#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST (0x00030600) /* Persistent Page not found */ -#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */ - -#define IOP_LOGINFO_CODE_DIAG_MSG_ERROR (0x00040000) /* Error handling diag msg - or'd with diag status */ - -#define IOP_LOGINFO_CODE_TASK_TERMINATED (0x00050000) - -#define IOP_LOGINFO_CODE_ENCL_MGMT_READ_ACTION_ERR0R (0x00060001) /* Read Action not supported for SEP msg */ -#define IOP_LOGINFO_CODE_ENCL_MGMT_INVALID_BUS_ID_ERR0R (0x00060002) /* Invalid Bus/ID in SEP msg */ - -#define IOP_LOGINFO_CODE_TARGET_ASSIST_TERMINATED (0x00070001) -#define IOP_LOGINFO_CODE_TARGET_STATUS_SEND_TERMINATED (0x00070002) -#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_ALL_IO (0x00070003) -#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO (0x00070004) -#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO_REQ (0x00070005) +#define IOP_LOGINFO_CODE_INVALID_SAS_ADDRESS (0x00010000) +#define IOP_LOGINFO_CODE_UNUSED2 (0x00020000) +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x00030000) +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_RT (0x00030100) /* Route Table Entry not found */ +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PN (0x00030200) /* Invalid Page Number */ +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x00030300) /* Invalid FORM */ +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x00030400) /* Invalid Page Type */ +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM (0x00030500) /* Device Not Mapped */ +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST (0x00030600) /* Persistent Page not found */ +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */ + +#define IOP_LOGINFO_CODE_FWUPLOAD_NO_FLASH_AVAILABLE (0x0003E000) /* Tried to upload from flash, but there is none */ +#define IOP_LOGINFO_CODE_FWUPLOAD_UNKNOWN_IMAGE_TYPE (0x0003E001) /* ImageType field contents were invalid */ +#define IOP_LOGINFO_CODE_FWUPLOAD_WRONG_IMAGE_SIZE (0x0003E002) /* ImageSize field in TCSGE was bad/offset in MfgPg 4 was wrong */ +#define IOP_LOGINFO_CODE_FWUPLOAD_ENTIRE_FLASH_UPLOAD_FAILED (0x0003E003) /* Error occured while attempting to upload the entire flash */ +#define IOP_LOGINFO_CODE_FWUPLOAD_REGION_UPLOAD_FAILED (0x0003E004) /* Error occured while attempting to upload single flash region */ +#define IOP_LOGINFO_CODE_FWUPLOAD_DMA_FAILURE (0x0003E005) /* Problem occured while DMAing FW to host memory */ + +#define IOP_LOGINFO_CODE_DIAG_MSG_ERROR (0x00040000) /* Error handling diag msg - or'd with diag status */ + +#define IOP_LOGINFO_CODE_TASK_TERMINATED (0x00050000) + +#define IOP_LOGINFO_CODE_ENCL_MGMT_READ_ACTION_ERR0R (0x00060001) /* Read Action not supported for SEP msg */ +#define IOP_LOGINFO_CODE_ENCL_MGMT_INVALID_BUS_ID_ERR0R (0x00060002) /* Invalid Bus/ID in SEP msg */ + +#define IOP_LOGINFO_CODE_TARGET_ASSIST_TERMINATED (0x00070001) +#define IOP_LOGINFO_CODE_TARGET_STATUS_SEND_TERMINATED (0x00070002) +#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_ALL_IO (0x00070003) +#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO (0x00070004) +#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO_REQ (0x00070005) /****************************************************************************/ /* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL */ /****************************************************************************/ -#define PL_LOGINFO_CODE_OPEN_FAILURE (0x00010000) -#define PL_LOG_INFO_CODE_OPEN_FAILURE_NO_DEST_TIME_OUT (0x00010001) -#define PL_LOGINFO_CODE_OPEN_FAILURE_BAD_DESTINATION (0x00010011) -#define PL_LOGINFO_CODE_OPEN_FAILURE_PROTOCOL_NOT_SUPPORTED (0x00010013) -#define PL_LOGINFO_CODE_OPEN_FAILURE_STP_RESOURCES_BSY (0x00010018) -#define PL_LOGINFO_CODE_OPEN_FAILURE_WRONG_DESTINATION (0x00010019) -#define PL_LOGINFO_CODE_OPEN_FAILURE_ORR_TIMEOUT (0X0001001A) -#define PL_LOGINFO_CODE_OPEN_FAILURE_PATHWAY_BLOCKED (0x0001001B) -#define PL_LOGINFO_CODE_OPEN_FAILURE_AWT_MAXED (0x0001001C) -#define PL_LOGINFO_CODE_INVALID_SGL (0x00020000) -#define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00030000) -#define PL_LOGINFO_CODE_FRAME_XFER_ERROR (0x00040000) -#define PL_LOGINFO_CODE_TX_FM_CONNECTED_LOW (0x00050000) -#define PL_LOGINFO_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00060000) -#define PL_LOGINFO_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00070000) -#define PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00080000) -#define PL_LOGINFO_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00090000) -#define PL_LOGINFO_CODE_RX_FM_INVALID_MESSAGE (0x000A0000) -#define PL_LOGINFO_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x000B0000) -#define PL_LOGINFO_CODE_RX_FM_CURRENT_FRAME_ERROR (0x000C0000) -#define PL_LOGINFO_CODE_SATA_LINK_DOWN (0x000D0000) -#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS (0x000E0000) -#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x000F0000) -#define PL_LOGINFO_CODE_CONFIG_PL_NOT_INITIALIZED (0x000F0001) /* PL not yet initialized, can't do config page req. */ -#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x000F0100) /* Invalid Page Type */ -#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS (0x000F0200) /* Invalid Number of Phys */ -#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP (0x000F0300) /* Case Not Handled */ -#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_DEV (0x000F0400) /* No Device Found */ -#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x000F0500) /* Invalid FORM */ -#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY (0x000F0600) /* Invalid Phy */ -#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER (0x000F0700) /* No Owner Found */ -#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00100000) -#define PL_LOGINFO_CODE_RESET (0x00110000) /* See Sub-Codes below */ -#define PL_LOGINFO_CODE_ABORT (0x00120000) /* See Sub-Codes below */ -#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000) -#define PL_LOGINFO_CODE_IO_EXECUTED (0x00140000) -#define PL_LOGINFO_CODE_PERS_RESV_OUT_NOT_AFFIL_OWNER (0x00150000) -#define PL_LOGINFO_CODE_OPEN_TXDMA_ABORT (0x00160000) -#define PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY (0x00170000) -#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE (0x00000100) -#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_NO_DEST_TIMEOUT (0x00000101) -#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ORR_TIMEOUT (0x0000011A) /* Open Reject (Retry) Timeout */ -#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_PATHWAY_BLOCKED (0x0000011B) -#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_AWT_MAXED (0x0000011C) /* Arbitration Wait Timer Maxed */ - -#define PL_LOGINFO_SUB_CODE_TARGET_BUS_RESET (0x00000120) -#define PL_LOGINFO_SUB_CODE_TRANSPORT_LAYER (0x00000130) /* Leave lower nibble (1-f) reserved. */ -#define PL_LOGINFO_SUB_CODE_PORT_LAYER (0x00000140) /* Leave lower nibble (1-f) reserved. */ - - -#define PL_LOGINFO_SUB_CODE_INVALID_SGL (0x00000200) -#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300) -#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400) -#define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW (0x00000500) -#define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00000600) -#define PL_LOGINFO_SUB_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00000700) -#define PL_LOGINFO_SUB_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00000800) -#define PL_LOGINFO_SUB_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00000900) -#define PL_LOGINFO_SUB_CODE_RX_FM_INVALID_MESSAGE (0x00000A00) -#define PL_LOGINFO_SUB_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x00000B00) -#define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR (0x00000C00) -#define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN (0x00000D00) -#define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS (0x00000E00) -#define PL_LOGINFO_SUB_CODE_DISCOVERY_REMOTE_SEP_RESET (0x00000E01) -#define PL_LOGINFO_SUB_CODE_SECOND_OPEN (0x00000F00) -#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00001000) - - -#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200010) /* Error occured on SMP Read */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200020) /* Error occured on SMP Write */ -#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200040) /* Encl Mgmt services not available for this WWID */ -#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200050) /* Address Mode not suppored */ -#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200060) /* Invalid Slot Number in SEP Msg */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200070) /* SGPIO not present/enabled */ -#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_NOT_CONFIGURED (0x00200080) /* GPIO not configured */ -#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_FRAME_ERROR (0x00200090) /* GPIO can't allocate a frame */ -#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_CONFIG_PAGE_ERROR (0x002000A0) /* GPIO failed config page request */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SES_FRAME_ALLOC_ERROR (0x002000B0) /* Can't get frame for SES command */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SES_IO_ERROR (0x002000C0) /* I/O execution error */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SES_RETRIES_EXHAUSTED (0x002000D0) /* SEP I/O retries exhausted */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_ALLOC_ERROR (0x002000E0) /* Can't get frame for SMP command */ - -#define PL_LOGINFO_DA_SEP_NOT_PRESENT (0x00200100) /* SEP not present when msg received */ -#define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR (0x00200101) /* Can only accept 1 msg at a time */ -#define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE (0x00200102) /* ISTWI interrupt recvd. while IDLE */ -#define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE (0x00200103) /* SEP NACK'd, it is busy */ -#define PL_LOGINFO_DA_SEP_DID_NOT_RECEIVE_ACK (0x00200104) /* SEP didn't rcv. ACK (Last Rcvd Bit = 1) */ -#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200105) /* SEP stopped or sent bad chksum in Hdr */ -#define PL_LOGINFO_DA_SEP_STOP_ON_DATA (0x00200106) /* SEP stopped while transfering data */ -#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA (0x00200107) /* SEP stopped while transfering sense data */ -#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200108) /* SEP returned unknown scsi status */ -#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200109) /* SEP returned unknown scsi status */ -#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x0020010A) /* SEP returned bad chksum after STOP */ -#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x0020010B) /* SEP returned bad chksum after STOP while gettin data*/ -#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND (0x0020010C) /* SEP doesn't support CDB opcode */ +#define PL_LOGINFO_CODE_OPEN_FAILURE (0x00010000) /* see SUB_CODE_OPEN_FAIL_ below */ + +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_NO_DEST_TIME_OUT (0x00000001) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_PATHWAY_BLOCKED (0x00000002) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_CONTINUE0 (0x00000003) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_CONTINUE1 (0x00000004) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_INITIALIZE0 (0x00000005) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_INITIALIZE1 (0x00000006) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_STOP0 (0x00000007) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_STOP1 (0x00000008) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RETRY (0x00000009) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_BREAK (0x0000000A) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_UNUSED_0B (0x0000000B) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_OPEN_TIMEOUT_EXP (0x0000000C) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_UNUSED_0D (0x0000000D) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_DVTBLE_ACCSS_FAIL (0x0000000E) +#define PL_LOGINFO_SUB CODE_OPEN_FAIL_BAD_DEST (0x00000011) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RATE_NOT_SUPP (0x00000012) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_PROT_NOT_SUPP (0x00000013) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON0 (0x00000014) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON1 (0x00000015) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON2 (0x00000016) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON3 (0x00000017) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_STP_RESOURCES_BSY (0x00000018) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_WRONG_DESTINATION (0x00000019) + +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_PATH_BLOCKED (0x0000001B) /* Retry Timeout */ +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_AWT_MAXED (0x0000001C) /* Retry Timeout */ + + + +#define PL_LOGINFO_CODE_INVALID_SGL (0x00020000) +#define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00030000) +#define PL_LOGINFO_CODE_FRAME_XFER_ERROR (0x00040000) +#define PL_LOGINFO_CODE_TX_FM_CONNECTED_LOW (0x00050000) +#define PL_LOGINFO_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00060000) +#define PL_LOGINFO_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00070000) +#define PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00080000) +#define PL_LOGINFO_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00090000) +#define PL_LOGINFO_CODE_RX_FM_INVALID_MESSAGE (0x000A0000) +#define PL_LOGINFO_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x000B0000) +#define PL_LOGINFO_CODE_RX_FM_CURRENT_FRAME_ERROR (0x000C0000) +#define PL_LOGINFO_CODE_SATA_LINK_DOWN (0x000D0000) +#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS (0x000E0000) +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x000F0000) +#define PL_LOGINFO_CODE_CONFIG_PL_NOT_INITIALIZED (0x000F0001) /* PL not yet initialized, can't do config page req. */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x000F0100) /* Invalid Page Type */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS (0x000F0200) /* Invalid Number of Phys */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP (0x000F0300) /* Case Not Handled */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_DEV (0x000F0400) /* No Device Found */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x000F0500) /* Invalid FORM */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY (0x000F0600) /* Invalid Phy */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER (0x000F0700) /* No Owner Found */ +#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00100000) +#define PL_LOGINFO_CODE_RESET (0x00110000) /* See Sub-Codes below (PL_LOGINFO_SUB_CODE) */ +#define PL_LOGINFO_CODE_ABORT (0x00120000) /* See Sub-Codes below (PL_LOGINFO_SUB_CODE)*/ +#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000) +#define PL_LOGINFO_CODE_IO_EXECUTED (0x00140000) +#define PL_LOGINFO_CODE_PERS_RESV_OUT_NOT_AFFIL_OWNER (0x00150000) +#define PL_LOGINFO_CODE_OPEN_TXDMA_ABORT (0x00160000) +#define PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY (0x00170000) +#define PL_LOGINFO_CODE_IO_CANCELLED_DUE_TO_R_ERR (0x00180000) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE (0x00000100) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_NO_DEST_TIMEOUT (0x00000101) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_SATA_NEG_RATE_2HI (0x00000102) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_RATE_NOT_SUPPORTED (0x00000103) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_BREAK (0x00000104) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ZONE_VIOLATION (0x00000114) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON0 (0x00000114) /* Open Reject (Zone Violation) - available on SAS-2 devices */ +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON1 (0x00000115) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON2 (0x00000116) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON3 (0x00000117) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ORR_TIMEOUT (0x0000011A) /* Open Reject (Retry) Timeout */ +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_PATH_BLOCKED (0x0000011B) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_AWT_MAXED (0x0000011C) /* Arbitration Wait Timer Maxed */ + +#define PL_LOGINFO_SUB_CODE_TARGET_BUS_RESET (0x00000120) +#define PL_LOGINFO_SUB_CODE_TRANSPORT_LAYER (0x00000130) /* Leave lower nibble (1-f) reserved. */ +#define PL_LOGINFO_SUB_CODE_PORT_LAYER (0x00000140) /* Leave lower nibble (1-f) reserved. */ + + +#define PL_LOGINFO_SUB_CODE_INVALID_SGL (0x00000200) +#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300) +#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400) /* Bits 0-3 encode Transport Status Register (offset 0x08) */ + /* Bit 0 is Status Bit 0: FrameXferErr */ + /* Bit 1 & 2 are Status Bits 16 and 17: FrameXmitErrStatus */ + /* Bit 3 is Status Bit 18 WriteDataLenghtGTDataLengthErr */ + +#define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW (0x00000500) +#define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00000600) +#define PL_LOGINFO_SUB_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00000700) +#define PL_LOGINFO_SUB_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00000800) +#define PL_LOGINFO_SUB_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00000900) +#define PL_LOGINFO_SUB_CODE_RX_FM_INVALID_MESSAGE (0x00000A00) +#define PL_LOGINFO_SUB_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x00000B00) +#define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR (0x00000C00) +#define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN (0x00000D00) +#define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS (0x00000E00) +#define PL_LOGINFO_SUB_CODE_DISCOVERY_REMOTE_SEP_RESET (0x00000E01) +#define PL_LOGINFO_SUB_CODE_SECOND_OPEN (0x00000F00) +#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00001000) + +#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200010) /* Error occured on SMP Read */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200020) /* Error occured on SMP Write */ +#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200040) /* Encl Mgmt services not available for this WWID */ +#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200050) /* Address Mode not suppored */ +#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200060) /* Invalid Slot Number in SEP Msg */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200070) /* SGPIO not present/enabled */ +#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_NOT_CONFIGURED (0x00200080) /* GPIO not configured */ +#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_FRAME_ERROR (0x00200090) /* GPIO can't allocate a frame */ +#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_CONFIG_PAGE_ERROR (0x002000A0) /* GPIO failed config page request */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SES_FRAME_ALLOC_ERROR (0x002000B0) /* Can't get frame for SES command */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SES_IO_ERROR (0x002000C0) /* I/O execution error */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SES_RETRIES_EXHAUSTED (0x002000D0) /* SEP I/O retries exhausted */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_ALLOC_ERROR (0x002000E0) /* Can't get frame for SMP command */ + +#define PL_LOGINFO_DA_SEP_NOT_PRESENT (0x00200100) /* SEP not present when msg received */ +#define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR (0x00200101) /* Can only accept 1 msg at a time */ +#define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE (0x00200102) /* ISTWI interrupt recvd. while IDLE */ +#define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE (0x00200103) /* SEP NACK'd, it is busy */ +#define PL_LOGINFO_DA_SEP_DID_NOT_RECEIVE_ACK (0x00200104) /* SEP didn't rcv. ACK (Last Rcvd Bit = 1) */ +#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200105) /* SEP stopped or sent bad chksum in Hdr */ +#define PL_LOGINFO_DA_SEP_STOP_ON_DATA (0x00200106) /* SEP stopped while transfering data */ +#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA (0x00200107) /* SEP stopped while transfering sense data */ +#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200108) /* SEP returned unknown scsi status */ +#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200109) /* SEP returned unknown scsi status */ +#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x0020010A) /* SEP returned bad chksum after STOP */ +#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x0020010B) /* SEP returned bad chksum after STOP while gettin data*/ +#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND (0x0020010C) /* SEP doesn't support CDB opcode f/w location 1 */ +#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND_2 (0x0020010D) /* SEP doesn't support CDB opcode f/w location 2 */ +#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND_3 (0x0020010E) /* SEP doesn't support CDB opcode f/w location 3 */ /****************************************************************************/ diff --git a/drivers/message/fusion/lsi/mpi_sas.h b/drivers/message/fusion/lsi/mpi_sas.h index 50b8f0a8f4560d5e222209cb43c2d856e8fa56c2..8e990a0fa7a214287e17eef7ad60adc79739cadd 100644 --- a/drivers/message/fusion/lsi/mpi_sas.h +++ b/drivers/message/fusion/lsi/mpi_sas.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2004 LSI Logic Corporation. + * Copyright (c) 2004-2006 LSI Logic Corporation. * * * Name: mpi_sas.h * Title: MPI Serial Attached SCSI structures and definitions * Creation Date: August 19, 2004 * - * mpi_sas.h Version: 01.05.03 + * mpi_sas.h Version: 01.05.04 * * Version History * --------------- @@ -21,6 +21,8 @@ * and Remove Device operations to SAS IO Unit Control. * Added DevHandle field to SAS IO Unit Control request and * reply. + * 10-11-06 01.05.04 Fixed the name of a define for Operation field of SAS IO + * Unit Control request. * -------------------------------------------------------------------------- */ @@ -237,7 +239,8 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST #define MPI_SAS_OP_SEND_PRIMITIVE (0x0A) #define MPI_SAS_OP_FORCE_FULL_DISCOVERY (0x0B) #define MPI_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C) -#define MPI_SAS_OP_TRANSMIT_REMOVE_DEVICE (0x0D) +#define MPI_SAS_OP_TRANSMIT_REMOVE_DEVICE (0x0D) /* obsolete name */ +#define MPI_SAS_OP_REMOVE_DEVICE (0x0D) /* values for the PrimFlags field */ #define MPI_SAS_PRIMFLAGS_SINGLE (0x08) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index b3f28a03b6a99f247648c9f12dc19f348d26213f..083acfd91d8bff0dad61188a8195c7b8aa1893e2 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -6,7 +6,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2007 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -82,6 +82,10 @@ static int mpt_msi_enable; module_param(mpt_msi_enable, int, 0); MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)"); +static int mpt_channel_mapping; +module_param(mpt_channel_mapping, int, 0); +MODULE_PARM_DESC(mpt_channel_mapping, " Mapping id's to channels (default=0)"); + #ifdef MFCNT static int mfcounter = 0; #define PRINT_MF_COUNT 20000 @@ -173,11 +177,14 @@ static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc); //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag); static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers); -static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); +#ifdef MPT_DEBUG_REPLY +static void mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); +#endif static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); +static void mpt_inactive_raid_list_free(MPT_ADAPTER *ioc); /* module entry point */ static int __init fusion_init (void); @@ -319,13 +326,11 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa) else if (ioc->bus_type == SAS) mpt_sas_log_info(ioc, log_info); } - if (ioc_stat & MPI_IOCSTATUS_MASK) { - if (ioc->bus_type == SPI && - cb_idx != mpt_stm_index && - cb_idx != mpt_lan_index) - mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf); - } +#ifdef MPT_DEBUG_REPLY + if (ioc_stat & MPI_IOCSTATUS_MASK) + mpt_iocstatus_info(ioc, (u32)ioc_stat, mf); +#endif /* Check for (valid) IO callback! */ if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS || @@ -911,7 +916,7 @@ mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr) int mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag) { - int r = 0; + int r = 0; u8 *req_as_bytes; int ii; @@ -1811,6 +1816,13 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) * and we try GetLanConfigPages again... */ if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { + + /* + * Initalize link list for inactive raid volumes. + */ + init_MUTEX(&ioc->raid_data.inactive_list_mutex); + INIT_LIST_HEAD(&ioc->raid_data.inactive_list); + if (ioc->bus_type == SAS) { /* clear persistency table */ @@ -2017,6 +2029,8 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) } kfree(ioc->spi_data.nvram); + mpt_inactive_raid_list_free(ioc); + kfree(ioc->raid_data.pIocPg2); kfree(ioc->raid_data.pIocPg3); ioc->spi_data.nvram = NULL; ioc->raid_data.pIocPg3 = NULL; @@ -2413,6 +2427,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word); facts->ProductID = le16_to_cpu(facts->ProductID); + if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) + > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) + ioc->ir_firmware = 1; facts->CurrentHostMfaHighAddr = le32_to_cpu(facts->CurrentHostMfaHighAddr); facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits); @@ -2505,6 +2522,7 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag) int ii; int req_sz; int reply_sz; + int max_id; /* IOC *must* NOT be in RESET state! */ if (ioc->last_state == MPI_IOC_STATE_RESET) { @@ -2552,6 +2570,21 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag) pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs); pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets); + max_id = (ioc->bus_type == SAS) ? pfacts->PortSCSIID : + pfacts->MaxDevices; + ioc->devices_per_bus = (max_id > 255) ? 256 : max_id; + ioc->number_of_buses = (ioc->devices_per_bus < 256) ? 1 : max_id/256; + + /* + * Place all the devices on channels + * + * (for debuging) + */ + if (mpt_channel_mapping) { + ioc->devices_per_bus = 1; + ioc->number_of_buses = (max_id > 255) ? 255 : max_id; + } + return 0; } @@ -2592,13 +2625,8 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n", ioc->name, ioc->upload_fw, ioc->facts.Flags)); - if(ioc->bus_type == SAS) - ioc_init.MaxDevices = ioc->facts.MaxDevices; - else if(ioc->bus_type == FC) - ioc_init.MaxDevices = MPT_MAX_FC_DEVICES; - else - ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES; - ioc_init.MaxBuses = MPT_MAX_BUS; + ioc_init.MaxDevices = (U8)ioc->devices_per_bus; + ioc_init.MaxBuses = (U8)ioc->number_of_buses; dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n", ioc->name, ioc->facts.MsgVersion)); if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) { @@ -2720,9 +2748,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) /* RAID FW may take a long time to enable */ - if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) - > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) || - (ioc->bus_type == SAS)) { + if (ioc->ir_firmware || ioc->bus_type == SAS) { rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag); @@ -3193,6 +3219,9 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) u32 diag1val = 0; #endif + /* Clear any existing interrupts */ + CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); + if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) { drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset " "address=%p\n", ioc->name, __FUNCTION__, @@ -3212,7 +3241,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) " count=%d\n", ioc->name, doorbell, count)); if (doorbell == MPI_IOC_STATE_READY) { - return 0; + return 1; } /* wait 1 sec */ @@ -3224,9 +3253,6 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) return -1; } - /* Clear any existing interrupts */ - CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - /* Use "Diagnostic reset" method! (only thing available!) */ diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); @@ -3942,7 +3968,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag) } } else { while (--cntdn) { - mdelay (1); + udelay (1000); intstat = CHIPREG_READ32(&ioc->chip->IntStatus); if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS)) break; @@ -3994,7 +4020,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag) intstat = CHIPREG_READ32(&ioc->chip->IntStatus); if (intstat & MPI_HIS_DOORBELL_INTERRUPT) break; - mdelay(1); + udelay (1000); count++; } } @@ -4310,8 +4336,8 @@ mptbase_raid_process_event_data(MPT_ADAPTER *ioc, if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED && reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) || (reason == MPI_EVENT_RAID_RC_SMART_DATA)) { - printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n", - ioc->name, disk); + printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d id=%d\n", + ioc->name, disk, volume); } else { printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n", ioc->name, volume); @@ -4712,7 +4738,187 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) return 0; } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** + * mpt_inactive_raid_list_free + * + * This clears this link list. + * + * @ioc - pointer to per adapter structure + * + **/ +static void +mpt_inactive_raid_list_free(MPT_ADAPTER *ioc) +{ + struct inactive_raid_component_info *component_info, *pNext; + + if (list_empty(&ioc->raid_data.inactive_list)) + return; + + down(&ioc->raid_data.inactive_list_mutex); + list_for_each_entry_safe(component_info, pNext, + &ioc->raid_data.inactive_list, list) { + list_del(&component_info->list); + kfree(component_info); + } + up(&ioc->raid_data.inactive_list_mutex); +} + +/** + * mpt_inactive_raid_volumes + * + * This sets up link list of phy_disk_nums for devices belonging in an inactive volume + * + * @ioc - pointer to per adapter structure + * @channel - volume channel + * @id - volume target id + * + * + **/ +static void +mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id) +{ + CONFIGPARMS cfg; + ConfigPageHeader_t hdr; + dma_addr_t dma_handle; + pRaidVolumePage0_t buffer = NULL; + int i; + RaidPhysDiskPage0_t phys_disk; + struct inactive_raid_component_info *component_info; + int handle_inactive_volumes; + + memset(&cfg, 0 , sizeof(CONFIGPARMS)); + memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); + hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME; + cfg.pageAddr = (channel << 8) + id; + cfg.cfghdr.hdr = &hdr; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + + if (mpt_config(ioc, &cfg) != 0) + goto out; + + if (!hdr.PageLength) + goto out; + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, + &dma_handle); + + if (!buffer) + goto out; + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + if (mpt_config(ioc, &cfg) != 0) + goto out; + + if (!buffer->NumPhysDisks) + goto out; + + handle_inactive_volumes = + (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE || + (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) == 0 || + buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_FAILED || + buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_MISSING) ? 1 : 0; + + if (!handle_inactive_volumes) + goto out; + + down(&ioc->raid_data.inactive_list_mutex); + for (i = 0; i < buffer->NumPhysDisks; i++) { + if(mpt_raid_phys_disk_pg0(ioc, + buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0) + continue; + + if ((component_info = kmalloc(sizeof (*component_info), + GFP_KERNEL)) == NULL) + continue; + + component_info->volumeID = id; + component_info->volumeBus = channel; + component_info->d.PhysDiskNum = phys_disk.PhysDiskNum; + component_info->d.PhysDiskBus = phys_disk.PhysDiskBus; + component_info->d.PhysDiskID = phys_disk.PhysDiskID; + component_info->d.PhysDiskIOC = phys_disk.PhysDiskIOC; + + list_add_tail(&component_info->list, + &ioc->raid_data.inactive_list); + } + up(&ioc->raid_data.inactive_list_mutex); + + out: + if (buffer) + pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, + dma_handle); +} + +/** + * mpt_raid_phys_disk_pg0 - returns phys disk page zero + * @ioc: Pointer to a Adapter Structure + * @phys_disk_num: io unit unique phys disk num generated by the ioc + * @phys_disk: requested payload data returned + * + * Return: + * 0 on success + * -EFAULT if read of config page header fails or data pointer not NULL + * -ENOMEM if pci_alloc failed + **/ +int +mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk) +{ + CONFIGPARMS cfg; + ConfigPageHeader_t hdr; + dma_addr_t dma_handle; + pRaidPhysDiskPage0_t buffer = NULL; + int rc; + + memset(&cfg, 0 , sizeof(CONFIGPARMS)); + memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); + + hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; + cfg.cfghdr.hdr = &hdr; + cfg.physAddr = -1; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + + if (mpt_config(ioc, &cfg) != 0) { + rc = -EFAULT; + goto out; + } + + if (!hdr.PageLength) { + rc = -EFAULT; + goto out; + } + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, + &dma_handle); + + if (!buffer) { + rc = -ENOMEM; + goto out; + } + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + cfg.pageAddr = phys_disk_num; + + if (mpt_config(ioc, &cfg) != 0) { + rc = -EFAULT; + goto out; + } + + rc = 0; + memcpy(phys_disk, buffer, sizeof(*buffer)); + phys_disk->MaxLBA = le32_to_cpu(buffer->MaxLBA); + + out: + + if (buffer) + pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, + dma_handle); + + return rc; +} + /** * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes * @ioc: Pointer to a Adapter Strucutre @@ -4722,21 +4928,27 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) * 0 on success * -EFAULT if read of config page header fails or data pointer not NULL * -ENOMEM if pci_alloc failed - */ + **/ int mpt_findImVolumes(MPT_ADAPTER *ioc) { IOCPage2_t *pIoc2; u8 *mem; - ConfigPageIoc2RaidVol_t *pIocRv; dma_addr_t ioc2_dma; CONFIGPARMS cfg; ConfigPageHeader_t header; - int jj; int rc = 0; int iocpage2sz; - u8 nVols, nPhys; - u8 vid, vbus, vioc; + int i; + + if (!ioc->ir_firmware) + return 0; + + /* Free the old page + */ + kfree(ioc->raid_data.pIocPg2); + ioc->raid_data.pIocPg2 = NULL; + mpt_inactive_raid_list_free(ioc); /* Read IOCP2 header then the page. */ @@ -4764,55 +4976,23 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; cfg.physAddr = ioc2_dma; if (mpt_config(ioc, &cfg) != 0) - goto done_and_free; + goto out; + + mem = kmalloc(iocpage2sz, GFP_KERNEL); + if (!mem) + goto out; - if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) { - mem = kmalloc(iocpage2sz, GFP_ATOMIC); - if (mem) { - ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem; - } else { - goto done_and_free; - } - } memcpy(mem, (u8 *)pIoc2, iocpage2sz); + ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem; - /* Identify RAID Volume Id's */ - nVols = pIoc2->NumActiveVolumes; - if ( nVols == 0) { - /* No RAID Volume. - */ - goto done_and_free; - } else { - /* At least 1 RAID Volume - */ - pIocRv = pIoc2->RaidVolume; - ioc->raid_data.isRaid = 0; - for (jj = 0; jj < nVols; jj++, pIocRv++) { - vid = pIocRv->VolumeID; - vbus = pIocRv->VolumeBus; - vioc = pIocRv->VolumeIOC; - - /* find the match - */ - if (vbus == 0) { - ioc->raid_data.isRaid |= (1 << vid); - } else { - /* Error! Always bus 0 - */ - } - } - } + mpt_read_ioc_pg_3(ioc); - /* Identify Hidden Physical Disk Id's */ - nPhys = pIoc2->NumActivePhysDisks; - if (nPhys == 0) { - /* No physical disks. - */ - } else { - mpt_read_ioc_pg_3(ioc); - } + for (i = 0; i < pIoc2->NumActiveVolumes ; i++) + mpt_inactive_raid_volumes(ioc, + pIoc2->RaidVolume[i].VolumeBus, + pIoc2->RaidVolume[i].VolumeID); -done_and_free: + out: pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma); return rc; @@ -4865,7 +5045,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) cfg.physAddr = ioc3_dma; cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; if (mpt_config(ioc, &cfg) == 0) { - mem = kmalloc(iocpage3sz, GFP_ATOMIC); + mem = kmalloc(iocpage3sz, GFP_KERNEL); if (mem) { memcpy(mem, (u8 *)pIoc3, iocpage3sz); ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem; @@ -5679,8 +5859,6 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) return rc; } -# define EVENT_DESCR_STR_SZ 100 - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ static void EventDescriptionStr(u8 event, u32 evData0, char *evStr) @@ -5708,9 +5886,6 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) break; case MPI_EVENT_RESCAN: ds = "Bus Rescan Event"; - /* Ok, do we need to do anything here? As far as - I can tell, this is when a new device gets added - to the loop. */ break; case MPI_EVENT_LINK_STATUS_CHANGE: if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE) @@ -5787,48 +5962,63 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: { u8 id = (u8)(evData0); + u8 channel = (u8)(evData0 >> 8); u8 ReasonCode = (u8)(evData0 >> 16); switch (ReasonCode) { case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: Added: id=%d", id); + "SAS Device Status Change: Added: " + "id=%d channel=%d", id, channel); break; case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: Deleted: id=%d", id); + "SAS Device Status Change: Deleted: " + "id=%d channel=%d", id, channel); break; case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: SMART Data: id=%d", - id); + "SAS Device Status Change: SMART Data: " + "id=%d channel=%d", id, channel); break; case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: No Persistancy: id=%d", id); + "SAS Device Status Change: No Persistancy: " + "id=%d channel=%d", id, channel); + break; + case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS Device Status Change: Unsupported Device " + "Discovered : id=%d channel=%d", id, channel); break; case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: Internal Device Reset : id=%d", id); + "SAS Device Status Change: Internal Device " + "Reset : id=%d channel=%d", id, channel); break; case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: Internal Task Abort : id=%d", id); + "SAS Device Status Change: Internal Task " + "Abort : id=%d channel=%d", id, channel); break; case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: Internal Abort Task Set : id=%d", id); + "SAS Device Status Change: Internal Abort " + "Task Set : id=%d channel=%d", id, channel); break; case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: Internal Clear Task Set : id=%d", id); + "SAS Device Status Change: Internal Clear " + "Task Set : id=%d channel=%d", id, channel); break; case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: Internal Query Task : id=%d", id); + "SAS Device Status Change: Internal Query " + "Task : id=%d channel=%d", id, channel); break; default: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: Unknown: id=%d", id); + "SAS Device Status Change: Unknown: " + "id=%d channel=%d", id, channel); break; } break; @@ -5837,8 +6027,16 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) ds = "Bus Timer Expired"; break; case MPI_EVENT_QUEUE_FULL: - ds = "Queue Full"; + { + u16 curr_depth = (u16)(evData0 >> 16); + u8 channel = (u8)(evData0 >> 8); + u8 id = (u8)(evData0); + + snprintf(evStr, EVENT_DESCR_STR_SZ, + "Queue Full: channel=%d id=%d depth=%d", + channel, id, curr_depth); break; + } case MPI_EVENT_SAS_SES: ds = "SAS SES Event"; break; @@ -5942,6 +6140,76 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) ds = "SAS Log Entry Added"; break; + case MPI_EVENT_SAS_BROADCAST_PRIMITIVE: + { + u8 phy_num = (u8)(evData0); + u8 port_num = (u8)(evData0 >> 8); + u8 port_width = (u8)(evData0 >> 16); + u8 primative = (u8)(evData0 >> 24); + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS Broadcase Primative: phy=%d port=%d " + "width=%d primative=0x%02x", + phy_num, port_num, port_width, primative); + break; + } + + case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE: + { + u8 reason = (u8)(evData0); + u8 port_num = (u8)(evData0 >> 8); + u16 handle = le16_to_cpu(evData0 >> 16); + + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS Initiator Device Status Change: reason=0x%02x " + "port=%d handle=0x%04x", + reason, port_num, handle); + break; + } + + case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW: + { + u8 max_init = (u8)(evData0); + u8 current_init = (u8)(evData0 >> 8); + + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS Initiator Device Table Overflow: max initiators=%02d " + "current initators=%02d", + max_init, current_init); + break; + } + case MPI_EVENT_SAS_SMP_ERROR: + { + u8 status = (u8)(evData0); + u8 port_num = (u8)(evData0 >> 8); + u8 result = (u8)(evData0 >> 16); + + if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID) + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS SMP Error: port=%d result=0x%02x", + port_num, result); + else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR) + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS SMP Error: port=%d : CRC Error", + port_num); + else if (status == MPI_EVENT_SAS_SMP_TIMEOUT) + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS SMP Error: port=%d : Timeout", + port_num); + else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION) + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS SMP Error: port=%d : No Destination", + port_num); + else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION) + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS SMP Error: port=%d : Bad Destination", + port_num); + else + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS SMP Error: port=%d : status=0x%02x", + port_num, status); + break; + } + /* * MPT base "custom" events may be added here... */ @@ -6205,10 +6473,11 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) "Abort", /* 12h */ "IO Not Yet Executed", /* 13h */ "IO Executed", /* 14h */ - "Persistent Reservation Out Not Affiliation Owner", /* 15h */ + "Persistent Reservation Out Not Affiliation " + "Owner", /* 15h */ "Open Transmit DMA Abort", /* 16h */ "IO Device Missing Delay Retry", /* 17h */ - NULL, /* 18h */ + "IO Cancelled Due to Recieve Error", /* 18h */ NULL, /* 19h */ NULL, /* 1Ah */ NULL, /* 1Bh */ @@ -6218,6 +6487,96 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) NULL, /* 1Fh */ "Enclosure Management" /* 20h */ }; + static char *ir_code_str[] = { + "Raid Action Error", /* 00h */ + NULL, /* 00h */ + NULL, /* 01h */ + NULL, /* 02h */ + NULL, /* 03h */ + NULL, /* 04h */ + NULL, /* 05h */ + NULL, /* 06h */ + NULL /* 07h */ + }; + static char *raid_sub_code_str[] = { + NULL, /* 00h */ + "Volume Creation Failed: Data Passed too " + "Large", /* 01h */ + "Volume Creation Failed: Duplicate Volumes " + "Attempted", /* 02h */ + "Volume Creation Failed: Max Number " + "Supported Volumes Exceeded", /* 03h */ + "Volume Creation Failed: DMA Error", /* 04h */ + "Volume Creation Failed: Invalid Volume Type", /* 05h */ + "Volume Creation Failed: Error Reading " + "MFG Page 4", /* 06h */ + "Volume Creation Failed: Creating Internal " + "Structures", /* 07h */ + NULL, /* 08h */ + NULL, /* 09h */ + NULL, /* 0Ah */ + NULL, /* 0Bh */ + NULL, /* 0Ch */ + NULL, /* 0Dh */ + NULL, /* 0Eh */ + NULL, /* 0Fh */ + "Activation failed: Already Active Volume", /* 10h */ + "Activation failed: Unsupported Volume Type", /* 11h */ + "Activation failed: Too Many Active Volumes", /* 12h */ + "Activation failed: Volume ID in Use", /* 13h */ + "Activation failed: Reported Failure", /* 14h */ + "Activation failed: Importing a Volume", /* 15h */ + NULL, /* 16h */ + NULL, /* 17h */ + NULL, /* 18h */ + NULL, /* 19h */ + NULL, /* 1Ah */ + NULL, /* 1Bh */ + NULL, /* 1Ch */ + NULL, /* 1Dh */ + NULL, /* 1Eh */ + NULL, /* 1Fh */ + "Phys Disk failed: Too Many Phys Disks", /* 20h */ + "Phys Disk failed: Data Passed too Large", /* 21h */ + "Phys Disk failed: DMA Error", /* 22h */ + "Phys Disk failed: Invalid ", /* 23h */ + "Phys Disk failed: Creating Phys Disk Config " + "Page", /* 24h */ + NULL, /* 25h */ + NULL, /* 26h */ + NULL, /* 27h */ + NULL, /* 28h */ + NULL, /* 29h */ + NULL, /* 2Ah */ + NULL, /* 2Bh */ + NULL, /* 2Ch */ + NULL, /* 2Dh */ + NULL, /* 2Eh */ + NULL, /* 2Fh */ + "Compatibility Error: IR Disabled", /* 30h */ + "Compatibility Error: Inquiry Comand Failed", /* 31h */ + "Compatibility Error: Device not Direct Access " + "Device ", /* 32h */ + "Compatibility Error: Removable Device Found", /* 33h */ + "Compatibility Error: Device SCSI Version not " + "2 or Higher", /* 34h */ + "Compatibility Error: SATA Device, 48 BIT LBA " + "not Supported", /* 35h */ + "Compatibility Error: Device doesn't have " + "512 Byte Block Sizes", /* 36h */ + "Compatibility Error: Volume Type Check Failed", /* 37h */ + "Compatibility Error: Volume Type is " + "Unsupported by FW", /* 38h */ + "Compatibility Error: Disk Drive too Small for " + "use in Volume", /* 39h */ + "Compatibility Error: Phys Disk for Create " + "Volume not Found", /* 3Ah */ + "Compatibility Error: Too Many or too Few " + "Disks for Volume Type", /* 3Bh */ + "Compatibility Error: Disk stripe Sizes " + "Must be 64KB", /* 3Ch */ + "Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */ + }; /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** @@ -6226,7 +6585,7 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) * @log_info: U32 LogInfo reply word from the IOC * * Refer to lsi/mpi_log_sas.h. - */ + **/ static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info) { @@ -6240,56 +6599,165 @@ union loginfo_type { }dw; }; union loginfo_type sas_loginfo; + char *originator_desc = NULL; char *code_desc = NULL; + char *sub_code_desc = NULL; sas_loginfo.loginfo = log_info; if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) && (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*))) return; - if ((sas_loginfo.dw.originator == 0 /*IOP*/) && - (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) { - code_desc = iop_code_str[sas_loginfo.dw.code]; - }else if ((sas_loginfo.dw.originator == 1 /*PL*/) && - (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) { - code_desc = pl_code_str[sas_loginfo.dw.code]; + + originator_desc = originator_str[sas_loginfo.dw.originator]; + + switch (sas_loginfo.dw.originator) { + + case 0: /* IOP */ + if (sas_loginfo.dw.code < + sizeof(iop_code_str)/sizeof(char*)) + code_desc = iop_code_str[sas_loginfo.dw.code]; + break; + case 1: /* PL */ + if (sas_loginfo.dw.code < + sizeof(pl_code_str)/sizeof(char*)) + code_desc = pl_code_str[sas_loginfo.dw.code]; + break; + case 2: /* IR */ + if (sas_loginfo.dw.code >= + sizeof(ir_code_str)/sizeof(char*)) + break; + code_desc = ir_code_str[sas_loginfo.dw.code]; + if (sas_loginfo.dw.subcode >= + sizeof(raid_sub_code_str)/sizeof(char*)) + break; + if (sas_loginfo.dw.code == 0) + sub_code_desc = + raid_sub_code_str[sas_loginfo.dw.subcode]; + break; + default: + return; } - if (code_desc != NULL) + if (sub_code_desc != NULL) + printk(MYIOC_s_INFO_FMT + "LogInfo(0x%08x): Originator={%s}, Code={%s}," + " SubCode={%s}\n", + ioc->name, log_info, originator_desc, code_desc, + sub_code_desc); + else if (code_desc != NULL) printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): Originator={%s}, Code={%s}," " SubCode(0x%04x)\n", - ioc->name, - log_info, - originator_str[sas_loginfo.dw.originator], - code_desc, + ioc->name, log_info, originator_desc, code_desc, sas_loginfo.dw.subcode); else printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x)," " SubCode(0x%04x)\n", - ioc->name, - log_info, - originator_str[sas_loginfo.dw.originator], - sas_loginfo.dw.code, - sas_loginfo.dw.subcode); + ioc->name, log_info, originator_desc, + sas_loginfo.dw.code, sas_loginfo.dw.subcode); } +#ifdef MPT_DEBUG_REPLY /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** - * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC. + * mpt_iocstatus_info_config - IOCSTATUS information for config pages + * @ioc: Pointer to MPT_ADAPTER structure + * ioc_status: U32 IOCStatus word from IOC + * @mf: Pointer to MPT request frame + * + * Refer to lsi/mpi.h. + **/ +static void +mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) +{ + Config_t *pReq = (Config_t *)mf; + char extend_desc[EVENT_DESCR_STR_SZ]; + char *desc = NULL; + u32 form; + u8 page_type; + + if (pReq->Header.PageType == MPI_CONFIG_PAGETYPE_EXTENDED) + page_type = pReq->ExtPageType; + else + page_type = pReq->Header.PageType; + + /* + * ignore invalid page messages for GET_NEXT_HANDLE + */ + form = le32_to_cpu(pReq->PageAddress); + if (ioc_status == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) { + if (page_type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE || + page_type == MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER || + page_type == MPI_CONFIG_EXTPAGETYPE_ENCLOSURE) { + if ((form >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT) == + MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE) + return; + } + if (page_type == MPI_CONFIG_PAGETYPE_FC_DEVICE) + if ((form & MPI_FC_DEVICE_PGAD_FORM_MASK) == + MPI_FC_DEVICE_PGAD_FORM_NEXT_DID) + return; + } + + snprintf(extend_desc, EVENT_DESCR_STR_SZ, + "type=%02Xh, page=%02Xh, action=%02Xh, form=%08Xh", + page_type, pReq->Header.PageNumber, pReq->Action, form); + + switch (ioc_status) { + + case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */ + desc = "Config Page Invalid Action"; + break; + + case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */ + desc = "Config Page Invalid Type"; + break; + + case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */ + desc = "Config Page Invalid Page"; + break; + + case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */ + desc = "Config Page Invalid Data"; + break; + + case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */ + desc = "Config Page No Defaults"; + break; + + case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */ + desc = "Config Page Can't Commit"; + break; + } + + if (!desc) + return; + + printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n", + ioc->name, ioc_status, desc, extend_desc); +} + +/** + * mpt_iocstatus_info - IOCSTATUS information returned from IOC. * @ioc: Pointer to MPT_ADAPTER structure * @ioc_status: U32 IOCStatus word from IOC * @mf: Pointer to MPT request frame * * Refer to lsi/mpi.h. - */ + **/ static void -mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) +mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) { u32 status = ioc_status & MPI_IOCSTATUS_MASK; char *desc = NULL; switch (status) { + +/****************************************************************************/ +/* Common IOCStatus values for all replies */ +/****************************************************************************/ + case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */ desc = "Invalid Function"; break; @@ -6322,84 +6790,180 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) desc = "Invalid State"; break; +/****************************************************************************/ +/* Config IOCStatus values */ +/****************************************************************************/ + case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */ case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */ case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */ case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */ case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */ case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */ - /* No message for Config IOCStatus values */ + mpt_iocstatus_info_config(ioc, status, mf); break; +/****************************************************************************/ +/* SCSIIO Reply (SPI, FCP, SAS) initiator values */ +/* */ +/* Look at mptscsih_iocstatus_info_scsiio in mptscsih.c */ +/* */ +/****************************************************************************/ + case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ - /* No message for recovered error - desc = "SCSI Recovered Error"; - */ + case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ + case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */ + case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */ + case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ + case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ + case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ + case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ + case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ + case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ + case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */ + case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ + case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ break; - case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */ - desc = "SCSI Invalid Bus"; +/****************************************************************************/ +/* SCSI Target values */ +/****************************************************************************/ + + case MPI_IOCSTATUS_TARGET_PRIORITY_IO: /* 0x0060 */ + desc = "Target: Priority IO"; break; - case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */ - desc = "SCSI Invalid TargetID"; + case MPI_IOCSTATUS_TARGET_INVALID_PORT: /* 0x0061 */ + desc = "Target: Invalid Port"; break; - case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ - { - SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf; - U8 cdb = pScsiReq->CDB[0]; - if (cdb != 0x12) { /* Inquiry is issued for device scanning */ - desc = "SCSI Device Not There"; - } + case MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX: /* 0x0062 */ + desc = "Target Invalid IO Index:"; break; - } - case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ - desc = "SCSI Data Overrun"; + case MPI_IOCSTATUS_TARGET_ABORTED: /* 0x0063 */ + desc = "Target: Aborted"; break; - case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ - /* This error is checked in scsi_io_done(). Skip. - desc = "SCSI Data Underrun"; - */ + case MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: /* 0x0064 */ + desc = "Target: No Conn Retryable"; break; - case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ - desc = "SCSI I/O Data Error"; + case MPI_IOCSTATUS_TARGET_NO_CONNECTION: /* 0x0065 */ + desc = "Target: No Connection"; break; - case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ - desc = "SCSI Protocol Error"; + case MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: /* 0x006A */ + desc = "Target: Transfer Count Mismatch"; break; - case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ - desc = "SCSI Task Terminated"; + case MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT: /* 0x006B */ + desc = "Target: STS Data not Sent"; break; - case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ - desc = "SCSI Residual Mismatch"; + case MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: /* 0x006D */ + desc = "Target: Data Offset Error"; break; - case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */ - desc = "SCSI Task Management Failed"; + case MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: /* 0x006E */ + desc = "Target: Too Much Write Data"; break; - case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ - desc = "SCSI IOC Terminated"; + case MPI_IOCSTATUS_TARGET_IU_TOO_SHORT: /* 0x006F */ + desc = "Target: IU Too Short"; break; - case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ - desc = "SCSI Ext Terminated"; + case MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: /* 0x0070 */ + desc = "Target: ACK NAK Timeout"; + break; + + case MPI_IOCSTATUS_TARGET_NAK_RECEIVED: /* 0x0071 */ + desc = "Target: Nak Received"; + break; + +/****************************************************************************/ +/* Fibre Channel Direct Access values */ +/****************************************************************************/ + + case MPI_IOCSTATUS_FC_ABORTED: /* 0x0066 */ + desc = "FC: Aborted"; + break; + + case MPI_IOCSTATUS_FC_RX_ID_INVALID: /* 0x0067 */ + desc = "FC: RX ID Invalid"; + break; + + case MPI_IOCSTATUS_FC_DID_INVALID: /* 0x0068 */ + desc = "FC: DID Invalid"; + break; + + case MPI_IOCSTATUS_FC_NODE_LOGGED_OUT: /* 0x0069 */ + desc = "FC: Node Logged Out"; + break; + + case MPI_IOCSTATUS_FC_EXCHANGE_CANCELED: /* 0x006C */ + desc = "FC: Exchange Canceled"; + break; + +/****************************************************************************/ +/* LAN values */ +/****************************************************************************/ + + case MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND: /* 0x0080 */ + desc = "LAN: Device not Found"; + break; + + case MPI_IOCSTATUS_LAN_DEVICE_FAILURE: /* 0x0081 */ + desc = "LAN: Device Failure"; + break; + + case MPI_IOCSTATUS_LAN_TRANSMIT_ERROR: /* 0x0082 */ + desc = "LAN: Transmit Error"; + break; + + case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED: /* 0x0083 */ + desc = "LAN: Transmit Aborted"; + break; + + case MPI_IOCSTATUS_LAN_RECEIVE_ERROR: /* 0x0084 */ + desc = "LAN: Receive Error"; + break; + + case MPI_IOCSTATUS_LAN_RECEIVE_ABORTED: /* 0x0085 */ + desc = "LAN: Receive Aborted"; + break; + + case MPI_IOCSTATUS_LAN_PARTIAL_PACKET: /* 0x0086 */ + desc = "LAN: Partial Packet"; + break; + + case MPI_IOCSTATUS_LAN_CANCELED: /* 0x0087 */ + desc = "LAN: Canceled"; + break; + +/****************************************************************************/ +/* Serial Attached SCSI values */ +/****************************************************************************/ + + case MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED: /* 0x0090 */ + desc = "SAS: SMP Request Failed"; + break; + + case MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN: /* 0x0090 */ + desc = "SAS: SMP Data Overrun"; break; default: desc = "Others"; break; } - if (desc != NULL) - printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc); + + if (!desc) + return; + + printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s\n", ioc->name, status, desc); } +#endif /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ EXPORT_SYMBOL(mpt_attach); @@ -6434,6 +6998,7 @@ EXPORT_SYMBOL(mpt_findImVolumes); EXPORT_SYMBOL(mpt_alloc_fw_memory); EXPORT_SYMBOL(mpt_free_fw_memory); EXPORT_SYMBOL(mptbase_sas_persist_operation); +EXPORT_SYMBOL(mpt_raid_phys_disk_pg0); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index e316708f76bd90e8777df1cda033ecb060834353..e3a39272aad6e2f5a059dce85ab9e87b3f5e620b 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -6,7 +6,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2007 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -75,8 +75,8 @@ #define COPYRIGHT "Copyright (c) 1999-2007 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.04.03" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.03" +#define MPT_LINUX_VERSION_COMMON "3.04.04" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.04" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ @@ -172,6 +172,9 @@ #define MPT_SCSI_SG_DEPTH 40 #endif +/* debug print string length used for events and iocstatus */ +# define EVENT_DESCR_STR_SZ 100 + #ifdef __KERNEL__ /* { */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -334,8 +337,8 @@ typedef struct _VirtTarget { struct scsi_target *starget; u8 tflags; u8 ioc_id; - u8 target_id; - u8 bus_id; + u8 id; + u8 channel; u8 minSyncFactor; /* 0xFF is async */ u8 maxOffset; /* 0 if async */ u8 maxWidth; /* 0 if narrow, 1 if wide */ @@ -344,13 +347,12 @@ typedef struct _VirtTarget { u8 type; /* byte 0 of Inquiry data */ u8 deleted; /* target in process of being removed */ u32 num_luns; - u32 luns[8]; /* Max LUNs is 256 */ } VirtTarget; typedef struct _VirtDevice { VirtTarget *vtarget; u8 configured_lun; - u32 lun; + int lun; } VirtDevice; /* @@ -412,7 +414,7 @@ typedef struct _MPT_IOCTL { u8 rsvd; u8 status; /* current command status */ u8 reset; /* 1 if bus reset allowed */ - u8 target; /* target for reset */ + u8 id; /* target for reset */ struct mutex ioctl_mutex; } MPT_IOCTL; @@ -483,10 +485,24 @@ typedef struct _SasCfgData { */ }SasCfgData; +/* + * Inactive volume link list of raid component data + * @inactive_list + */ +struct inactive_raid_component_info { + struct list_head list; + u8 volumeID; /* volume target id */ + u8 volumeBus; /* volume channel */ + IOC_3_PHYS_DISK d; /* phys disk info */ +}; + typedef struct _RaidCfgData { IOCPage2_t *pIocPg2; /* table of Raid Volumes */ IOCPage3_t *pIocPg3; /* table of physical disks */ - int isRaid; /* bit field, 1 if RAID */ + struct semaphore inactive_list_mutex; + struct list_head inactive_list; /* link list for physical + disk that belong in + inactive volumes */ }RaidCfgData; typedef struct _FcCfgData { @@ -528,6 +544,8 @@ typedef struct _MPT_ADAPTER u32 mem_phys; /* == f4020000 (mmap) */ u32 pio_mem_phys; /* Programmed IO (downloadboot) */ int mem_size; /* mmap memory size */ + int number_of_buses; + int devices_per_bus; int alloc_total; u32 last_state; int active; @@ -607,6 +625,8 @@ typedef struct _MPT_ADAPTER u8 persist_reply_frame[MPT_DEFAULT_FRAME_SIZE]; /* persist reply */ LANPage0_t lan_cnfg_page0; LANPage1_t lan_cnfg_page1; + + u8 ir_firmware; /* =1 if IR firmware detected */ /* * Description: errata_flag_1064 * If a PCIX read occurs within 1 or 2 cycles after the chip receives @@ -790,12 +810,6 @@ typedef struct _mpt_sge { #define ddvprintk(x) #endif -#ifdef MPT_DEBUG_NEGO -#define dnegoprintk(x) printk x -#else -#define dnegoprintk(x) -#endif - #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) #define ddvtprintk(x) printk x #else @@ -957,7 +971,6 @@ typedef struct _MPT_SCSI_HOST { int port; u32 pad0; struct scsi_cmnd **ScsiLookup; - VirtTarget **Targets; MPT_LOCAL_REPLY *pLocal; /* used for internal commands */ struct timer_list timer; /* Pool of memory for holding SCpnts before doing @@ -981,6 +994,7 @@ typedef struct _MPT_SCSI_HOST { int scandv_wait_done; long last_queue_full; u16 tm_iocstatus; + struct list_head target_reset_list; } MPT_SCSI_HOST; /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1046,6 +1060,7 @@ extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size); extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); extern int mpt_findImVolumes(MPT_ADAPTER *ioc); extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); +extern int mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk); /* * Public data decl's... diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 504632da43470fdbbca038e9d7dc46e3f91fdde2..b0b80428d1107bdc082894106660225ea11a6260 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -5,7 +5,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2007 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -313,7 +313,7 @@ static void mptctl_timeout_expired (MPT_IOCTL *ioctl) */ dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", ioctl->ioc->name)); - mpt_HardResetHandler(ioctl->ioc, NO_SLEEP); + mpt_HardResetHandler(ioctl->ioc, CAN_SLEEP); } return; @@ -361,7 +361,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl) ioctl->ioc->name, mf)); pScsiTm = (SCSITaskMgmt_t *) mf; - pScsiTm->TargetID = ioctl->target; + pScsiTm->TargetID = ioctl->id; pScsiTm->Bus = hd->port; /* 0 */ pScsiTm->ChainOffset = 0; pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; @@ -1159,15 +1159,12 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) struct mpt_ioctl_iocinfo *karg; MPT_ADAPTER *ioc; struct pci_dev *pdev; - struct Scsi_Host *sh; - MPT_SCSI_HOST *hd; int iocnum; - int numDevices = 0; - unsigned int max_id; - int ii; unsigned int port; int cim_rev; u8 revision; + struct scsi_device *sdev; + VirtDevice *vdev; dctlprintk((": mptctl_getiocinfo called.\n")); /* Add of PCI INFO results in unaligned access for @@ -1257,23 +1254,16 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) /* Get number of devices */ - if ((sh = ioc->sh) != NULL) { - /* sh->max_id = maximum target ID + 1 - */ - max_id = sh->max_id - 1; - hd = (MPT_SCSI_HOST *) sh->hostdata; - - /* Check all of the target structures and - * keep a counter. - */ - if (hd && hd->Targets) { - for (ii = 0; ii <= max_id; ii++) { - if (hd->Targets[ii]) - numDevices++; - } + karg->numDevices = 0; + if (ioc->sh) { + shost_for_each_device(sdev, ioc->sh) { + vdev = sdev->hostdata; + if (vdev->vtarget->tflags & + MPT_TARGET_FLAGS_RAID_COMPONENT) + continue; + karg->numDevices++; } } - karg->numDevices = numDevices; /* Set the BIOS and FW Version */ @@ -1319,21 +1309,16 @@ mptctl_gettargetinfo (unsigned long arg) struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg; struct mpt_ioctl_targetinfo karg; MPT_ADAPTER *ioc; - struct Scsi_Host *sh; - MPT_SCSI_HOST *hd; - VirtTarget *vdev; + VirtDevice *vdev; char *pmem; int *pdata; - IOCPage2_t *pIoc2; - IOCPage3_t *pIoc3; int iocnum; int numDevices = 0; - unsigned int max_id; - int id, jj, indexed_lun, lun_index; - u32 lun; + int lun; int maxWordsLeft; int numBytes; - u8 port, devType, bus_id; + u8 port; + struct scsi_device *sdev; dctlprintk(("mptctl_gettargetinfo called.\n")); if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) { @@ -1389,74 +1374,22 @@ mptctl_gettargetinfo (unsigned long arg) /* Get number of devices */ - if ((sh = ioc->sh) != NULL) { - - max_id = sh->max_id - 1; - hd = (MPT_SCSI_HOST *) sh->hostdata; - - /* Check all of the target structures. - * Save the Id and increment the counter, - * if ptr non-null. - * sh->max_id = maximum target ID + 1 - */ - if (hd && hd->Targets) { - mpt_findImVolumes(ioc); - pIoc2 = ioc->raid_data.pIocPg2; - for ( id = 0; id <= max_id; ) { - if ( pIoc2 && pIoc2->NumActiveVolumes ) { - if ( id == pIoc2->RaidVolume[0].VolumeID ) { - if (maxWordsLeft <= 0) { - printk(KERN_ERR "mptctl_gettargetinfo - " - "buffer is full but volume is available on ioc %d\n, numDevices=%d", iocnum, numDevices); - goto data_space_full; - } - if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 ) - devType = 0x80; - else - devType = 0xC0; - bus_id = pIoc2->RaidVolume[0].VolumeBus; - numDevices++; - *pdata = ( (devType << 24) | (bus_id << 8) | id ); - dctlprintk((KERN_ERR "mptctl_gettargetinfo - " - "volume ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata)); - pdata++; - --maxWordsLeft; - goto next_id; - } else { - pIoc3 = ioc->raid_data.pIocPg3; - for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) { - if ( pIoc3->PhysDisk[jj].PhysDiskID == id ) - goto next_id; - } - } - } - if ( (vdev = hd->Targets[id]) ) { - for (jj = 0; jj <= MPT_LAST_LUN; jj++) { - lun_index = (jj >> 5); - indexed_lun = (jj % 32); - lun = (1 << indexed_lun); - if (vdev->luns[lun_index] & lun) { - if (maxWordsLeft <= 0) { - printk(KERN_ERR "mptctl_gettargetinfo - " - "buffer is full but more targets are available on ioc %d numDevices=%d\n", iocnum, numDevices); - goto data_space_full; - } - bus_id = vdev->bus_id; - numDevices++; - *pdata = ( (jj << 16) | (bus_id << 8) | id ); - dctlprintk((KERN_ERR "mptctl_gettargetinfo - " - "target ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata)); - pdata++; - --maxWordsLeft; - } - } - } -next_id: - id++; - } + if (ioc->sh){ + shost_for_each_device(sdev, ioc->sh) { + if (!maxWordsLeft) + continue; + vdev = sdev->hostdata; + if (vdev->vtarget->tflags & + MPT_TARGET_FLAGS_RAID_COMPONENT) + continue; + lun = (vdev->vtarget->raidVolume) ? 0x80 : vdev->lun; + *pdata = (((u8)lun << 16) + (vdev->vtarget->channel << 8) + + (vdev->vtarget->id )); + pdata++; + numDevices++; + --maxWordsLeft; } } -data_space_full: karg.numDevices = numDevices; /* Copy part of the data from kernel memory to user memory @@ -1821,6 +1754,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) int msgContext; u16 req_idx; ulong timeout; + struct scsi_device *sdev; dctlprintk(("mptctl_do_mpt_command called.\n")); bufIn.kptr = bufOut.kptr = NULL; @@ -1902,14 +1836,13 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) case MPI_FUNCTION_SCSI_IO_REQUEST: if (ioc->sh) { SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf; - VirtTarget *pTarget = NULL; - MPT_SCSI_HOST *hd = NULL; int qtag = MPI_SCSIIO_CONTROL_UNTAGGED; int scsidir = 0; - int target = (int) pScsiReq->TargetID; int dataSize; + u32 id; - if ((target < 0) || (target >= ioc->sh->max_id)) { + id = (ioc->devices_per_bus == 0) ? 256 : ioc->devices_per_bus; + if (pScsiReq->TargetID > id) { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Target ID out of bounds. \n", __FILE__, __LINE__); @@ -1917,6 +1850,14 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) goto done_free_mem; } + if (pScsiReq->Bus >= ioc->number_of_buses) { + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "Target Bus out of bounds. \n", + __FILE__, __LINE__); + rc = -ENODEV; + goto done_free_mem; + } + pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH; pScsiReq->MsgFlags |= mpt_msg_flags(); @@ -1936,13 +1877,15 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) cpu_to_le32(ioc->sense_buf_low_dma + (req_idx * MPT_SENSE_BUFFER_ALLOC)); - if ((hd = (MPT_SCSI_HOST *) ioc->sh->hostdata)) { - if (hd->Targets) - pTarget = hd->Targets[target]; - } + shost_for_each_device(sdev, ioc->sh) { + struct scsi_target *starget = scsi_target(sdev); + VirtTarget *vtarget = starget->hostdata; - if (pTarget &&(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) - qtag = MPI_SCSIIO_CONTROL_SIMPLEQ; + if ((pScsiReq->TargetID == vtarget->id) && + (pScsiReq->Bus == vtarget->channel) && + (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)) + qtag = MPI_SCSIIO_CONTROL_SIMPLEQ; + } /* Have the IOCTL driver set the direction based * on the dataOutSize (ordering issue with Sparc). @@ -1959,7 +1902,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) pScsiReq->DataLength = cpu_to_le32(dataSize); ioc->ioctl->reset = MPTCTL_RESET_OK; - ioc->ioctl->target = target; + ioc->ioctl->id = pScsiReq->TargetID; } else { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " @@ -2038,7 +1981,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) pScsiReq->DataLength = cpu_to_le32(dataSize); ioc->ioctl->reset = MPTCTL_RESET_OK; - ioc->ioctl->target = pScsiReq->TargetID; + ioc->ioctl->id = pScsiReq->TargetID; } else { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "SCSI driver is not loaded. \n", diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h index e65a1cf5eb0b776f26b265641c729aaa80948563..f7e72c5e47de28bbff0263ae1ecb8930bef1aa58 100644 --- a/drivers/message/fusion/mptctl.h +++ b/drivers/message/fusion/mptctl.h @@ -6,7 +6,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2007 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index c819c23b55b1aeb3ca477fd6c689c9cbc0134ff3..b7d4c7265ec66ec226b04e5b6120b6b1c48e316c 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -4,7 +4,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2007 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -86,6 +86,12 @@ MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the " " return following a device loss event." " Default=60."); +/* scsi-mid layer global parmeter is max_report_luns, which is 511 */ +#define MPTFC_MAX_LUN (16895) +static int max_lun = MPTFC_MAX_LUN; +module_param(max_lun, int, 0); +MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); + static int mptfcDoneCtx = -1; static int mptfcTaskCtx = -1; static int mptfcInternalCtx = -1; /* Used only for internal commands */ @@ -292,10 +298,9 @@ mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port, U32 port_id = 0xffffff; int num_targ = 0; int max_bus = ioc->facts.MaxBuses; - int max_targ = ioc->facts.MaxDevices; + int max_targ; - if (max_bus == 0 || max_targ == 0) - goto out; + max_targ = (ioc->facts.MaxDevices == 0) ? 256 : ioc->facts.MaxDevices; data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ; p_p0 = p0_array = kzalloc(data_sz, GFP_KERNEL); @@ -467,8 +472,8 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) if (ri->starget) { vtarget = ri->starget->hostdata; if (vtarget) { - vtarget->target_id = pg0->CurrentTargetID; - vtarget->bus_id = pg0->CurrentBus; + vtarget->id = pg0->CurrentTargetID; + vtarget->channel = pg0->CurrentBus; } } *((struct mptfc_rport_info **)rport->dd_data) = ri; @@ -540,8 +545,8 @@ mptfc_target_alloc(struct scsi_target *starget) if (rport) { ri = *((struct mptfc_rport_info **)rport->dd_data); if (ri) { /* better be! */ - vtarget->target_id = ri->pg0.CurrentTargetID; - vtarget->bus_id = ri->pg0.CurrentBus; + vtarget->id = ri->pg0.CurrentTargetID; + vtarget->channel = ri->pg0.CurrentBus; ri->starget = starget; rc = 0; } @@ -592,7 +597,6 @@ mptfc_slave_alloc(struct scsi_device *sdev) if (vtarget->num_luns == 0) { vtarget->ioc_id = hd->ioc->id; vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; - hd->Targets[sdev->id] = vtarget; } vdev->vtarget = vtarget; @@ -630,16 +634,17 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) struct mptfc_rport_info *ri; struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device)); int err; + VirtDevice *vdev = SCpnt->device->hostdata; - err = fc_remote_port_chkready(rport); - if (unlikely(err)) { - SCpnt->result = err; + if (!vdev || !vdev->vtarget) { + SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); return 0; } - if (!SCpnt->device->hostdata) { /* vdev */ - SCpnt->result = DID_NO_CONNECT << 16; + err = fc_remote_port_chkready(rport); + if (unlikely(err)) { + SCpnt->result = err; done(SCpnt); return 0; } @@ -1143,7 +1148,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) printk(MYIOC_s_WARN_FMT "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", ioc->name, ioc); - return -ENODEV; + return 0; } sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST)); @@ -1173,10 +1178,9 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* set 16 byte cdb's */ sh->max_cmd_len = 16; - sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255; + sh->max_id = ioc->pfacts->MaxDevices; + sh->max_lun = max_lun; - sh->max_lun = MPT_LAST_LUN + 1; - sh->max_channel = 0; sh->this_id = ioc->pfacts[0].PortSCSIID; /* Required entry. @@ -1230,19 +1234,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", ioc->name, hd->ScsiLookup)); - /* Allocate memory for the device structures. - * A non-Null pointer at an offset - * indicates a device exists. - * max_id = 1 + maximum id (hosts.h) - */ - hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC); - if (!hd->Targets) { - error = -ENOMEM; - goto out_mptfc_probe; - } - - dprintk((KERN_INFO " vdev @ %p\n", hd->Targets)); - /* Clear the TM flags */ hd->tmPending = 0; diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 2936204d8ad629f367cbdc00af8156ffd14bf5a5..b691292ff59969fcafc3607ad7f426cc289d1ec9 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -5,6 +5,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 2000-2007 LSI Logic Corporation + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h index 70ab75e7c263174a3a45020d7c503d21d3c1aa89..fe438bf119f61204b86bc17dc577e86991acfbb7 100644 --- a/drivers/message/fusion/mptlan.h +++ b/drivers/message/fusion/mptlan.h @@ -5,6 +5,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 2000-2007 LSI Logic Corporation + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 09e9a9d96410942dcfe21bb2d0484ee8f0956693..84b8b485e95bd8b57b6a11685a2cf64cd317d704 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -4,7 +4,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2007 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * (mailto:mpt_linux_developer@lsi.com) * Copyright (c) 2005-2007 Dell */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -83,17 +83,31 @@ MODULE_PARM_DESC(mpt_pt_clear, " Clear persistency table: enable=1 " "(default=MPTSCSIH_PT_CLEAR=0)"); +/* scsi-mid layer global parmeter is max_report_luns, which is 511 */ +#define MPTSAS_MAX_LUN (16895) +static int max_lun = MPTSAS_MAX_LUN; +module_param(max_lun, int, 0); +MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); + static int mptsasDoneCtx = -1; static int mptsasTaskCtx = -1; static int mptsasInternalCtx = -1; /* Used only for internal commands */ static int mptsasMgmtCtx = -1; +static void mptsas_hotplug_work(struct work_struct *work); + +struct mptsas_target_reset_event { + struct list_head list; + EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data; + u8 target_reset_issued; +}; enum mptsas_hotplug_action { MPTSAS_ADD_DEVICE, MPTSAS_DEL_DEVICE, MPTSAS_ADD_RAID, MPTSAS_DEL_RAID, + MPTSAS_ADD_INACTIVE_VOLUME, MPTSAS_IGNORE_EVENT, }; @@ -102,14 +116,15 @@ struct mptsas_hotplug_event { MPT_ADAPTER *ioc; enum mptsas_hotplug_action event_type; u64 sas_address; - u32 channel; - u32 id; + u8 channel; + u8 id; u32 device_info; u16 handle; u16 parent_handle; u8 phy_id; - u8 phys_disk_num; - u8 phys_disk_num_valid; + u8 phys_disk_num_valid; /* hrc (hidden raid component) */ + u8 phys_disk_num; /* hrc - unique index*/ + u8 hidden_raid_component; /* hrc - don't expose*/ }; struct mptsas_discovery_event { @@ -134,6 +149,7 @@ struct mptsas_devinfo { u8 port_id; /* sas physical port this device is assoc'd with */ u8 id; /* logical target id of this device */ + u32 phys_disk_num; /* phys disk id, for csmi-ioctls */ u8 channel; /* logical bus number of this device */ u64 sas_address; /* WWN of this device, SATA is assigned by HBA,expander */ @@ -153,6 +169,7 @@ struct mptsas_portinfo_details{ }; struct mptsas_phyinfo { + u16 handle; /* unique id to address this */ u8 phy_id; /* phy index */ u8 port_id; /* firmware port identifier */ u8 negotiated_link_rate; /* nego'd link rate for this phy */ @@ -168,7 +185,6 @@ struct mptsas_phyinfo { struct mptsas_portinfo { struct list_head list; - u16 handle; /* unique id to address this */ u16 num_phys; /* number of phys */ struct mptsas_phyinfo *phy_info; }; @@ -561,22 +577,273 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) mutex_unlock(&ioc->sas_topology_mutex); } +/** + * csmisas_find_vtarget + * + * @ioc + * @volume_id + * @volume_bus + * + **/ +static VirtTarget * +mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id) +{ + struct scsi_device *sdev; + VirtDevice *vdev; + VirtTarget *vtarget = NULL; + + shost_for_each_device(sdev, ioc->sh) { + if ((vdev = sdev->hostdata) == NULL) + continue; + if (vdev->vtarget->id == id && + vdev->vtarget->channel == channel) + vtarget = vdev->vtarget; + } + return vtarget; +} + +/** + * mptsas_target_reset + * + * Issues TARGET_RESET to end device using handshaking method + * + * @ioc + * @channel + * @id + * + * Returns (1) success + * (0) failure + * + **/ +static int +mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id) +{ + MPT_FRAME_HDR *mf; + SCSITaskMgmt_t *pScsiTm; + + if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) { + dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n", + ioc->name,__FUNCTION__, __LINE__)); + return 0; + } + + /* Format the Request + */ + pScsiTm = (SCSITaskMgmt_t *) mf; + memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t)); + pScsiTm->TargetID = id; + pScsiTm->Bus = channel; + pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; + pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET; + pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION; + + DBG_DUMP_TM_REQUEST_FRAME(mf); + + if (mpt_send_handshake_request(ioc->TaskCtx, ioc, + sizeof(SCSITaskMgmt_t), (u32 *)mf, NO_SLEEP)) { + mpt_free_msg_frame(ioc, mf); + dfailprintk((MYIOC_s_WARN_FMT "%s, tm handshake failed @%d!!\n", + ioc->name,__FUNCTION__, __LINE__)); + return 0; + } + + return 1; +} + +/** + * mptsas_target_reset_queue + * + * Receive request for TARGET_RESET after recieving an firmware + * event NOT_RESPONDING_EVENT, then put command in link list + * and queue if task_queue already in use. + * + * @ioc + * @sas_event_data + * + **/ static void -mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget) +mptsas_target_reset_queue(MPT_ADAPTER *ioc, + EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data) { - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + VirtTarget *vtarget = NULL; + struct mptsas_target_reset_event *target_reset_list; + u8 id, channel; - if (mptscsih_TMHandler(hd, - MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, - vtarget->bus_id, vtarget->target_id, 0, 0, 5) < 0) { - hd->tmPending = 0; - hd->tmState = TM_STATE_NONE; - printk(MYIOC_s_WARN_FMT - "Error processing TaskMgmt id=%d TARGET_RESET\n", - ioc->name, vtarget->target_id); + id = sas_event_data->TargetID; + channel = sas_event_data->Bus; + + if (!(vtarget = mptsas_find_vtarget(ioc, channel, id))) + return; + + vtarget->deleted = 1; /* block IO */ + + target_reset_list = kzalloc(sizeof(*target_reset_list), + GFP_ATOMIC); + if (!target_reset_list) { + dfailprintk((MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n", + ioc->name,__FUNCTION__, __LINE__)); + return; + } + + memcpy(&target_reset_list->sas_event_data, sas_event_data, + sizeof(*sas_event_data)); + list_add_tail(&target_reset_list->list, &hd->target_reset_list); + + if (hd->resetPending) + return; + + if (mptsas_target_reset(ioc, channel, id)) { + target_reset_list->target_reset_issued = 1; + hd->resetPending = 1; } } +/** + * mptsas_dev_reset_complete + * + * Completion for TARGET_RESET after NOT_RESPONDING_EVENT, + * enable work queue to finish off removing device from upper layers. + * then send next TARGET_RESET in the queue. + * + * @ioc + * + **/ +static void +mptsas_dev_reset_complete(MPT_ADAPTER *ioc) +{ + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + struct list_head *head = &hd->target_reset_list; + struct mptsas_target_reset_event *target_reset_list; + struct mptsas_hotplug_event *ev; + EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data; + u8 id, channel; + __le64 sas_address; + + if (list_empty(head)) + return; + + target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, list); + + sas_event_data = &target_reset_list->sas_event_data; + id = sas_event_data->TargetID; + channel = sas_event_data->Bus; + hd->resetPending = 0; + + /* + * retry target reset + */ + if (!target_reset_list->target_reset_issued) { + if (mptsas_target_reset(ioc, channel, id)) { + target_reset_list->target_reset_issued = 1; + hd->resetPending = 1; + } + return; + } + + /* + * enable work queue to remove device from upper layers + */ + list_del(&target_reset_list->list); + + ev = kzalloc(sizeof(*ev), GFP_ATOMIC); + if (!ev) { + dfailprintk((MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n", + ioc->name,__FUNCTION__, __LINE__)); + return; + } + + INIT_WORK(&ev->work, mptsas_hotplug_work); + ev->ioc = ioc; + ev->handle = le16_to_cpu(sas_event_data->DevHandle); + ev->parent_handle = + le16_to_cpu(sas_event_data->ParentDevHandle); + ev->channel = channel; + ev->id =id; + ev->phy_id = sas_event_data->PhyNum; + memcpy(&sas_address, &sas_event_data->SASAddress, + sizeof(__le64)); + ev->sas_address = le64_to_cpu(sas_address); + ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo); + ev->event_type = MPTSAS_DEL_DEVICE; + schedule_work(&ev->work); + kfree(target_reset_list); + + /* + * issue target reset to next device in the queue + */ + + head = &hd->target_reset_list; + if (list_empty(head)) + return; + + target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, + list); + + sas_event_data = &target_reset_list->sas_event_data; + id = sas_event_data->TargetID; + channel = sas_event_data->Bus; + + if (mptsas_target_reset(ioc, channel, id)) { + target_reset_list->target_reset_issued = 1; + hd->resetPending = 1; + } +} + +/** + * mptsas_taskmgmt_complete + * + * @ioc + * @mf + * @mr + * + **/ +static int +mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) +{ + mptsas_dev_reset_complete(ioc); + return mptscsih_taskmgmt_complete(ioc, mf, mr); +} + +/** + * mptscsih_ioc_reset + * + * @ioc + * @reset_phase + * + **/ +static int +mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) +{ + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + struct mptsas_target_reset_event *target_reset_list, *n; + int rc; + + rc = mptscsih_ioc_reset(ioc, reset_phase); + + if (ioc->bus_type != SAS) + goto out; + + if (reset_phase != MPT_IOC_POST_RESET) + goto out; + + if (!hd || !hd->ioc) + goto out; + + if (list_empty(&hd->target_reset_list)) + goto out; + + /* flush the target_reset_list */ + list_for_each_entry_safe(target_reset_list, n, + &hd->target_reset_list, list) { + list_del(&target_reset_list->list); + kfree(target_reset_list); + } + + out: + return rc; +} + static int mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, u32 form, u32 form_specific) @@ -661,8 +928,7 @@ mptsas_target_alloc(struct scsi_target *starget) struct Scsi_Host *host = dev_to_shost(&starget->dev); MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; VirtTarget *vtarget; - u32 target_id; - u32 channel; + u8 id, channel; struct sas_rphy *rphy; struct mptsas_portinfo *p; int i; @@ -673,15 +939,19 @@ mptsas_target_alloc(struct scsi_target *starget) vtarget->starget = starget; vtarget->ioc_id = hd->ioc->id; - vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY; - - target_id = starget->id; + vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; + id = starget->id; channel = 0; - hd->Targets[target_id] = vtarget; - - if (starget->channel == MPTSAS_RAID_CHANNEL) + /* + * RAID volumes placed beyond the last expected port. + */ + if (starget->channel == MPTSAS_RAID_CHANNEL) { + for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++) + if (id == hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) + channel = hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus; goto out; + } rphy = dev_to_rphy(starget->dev.parent); mutex_lock(&hd->ioc->sas_topology_mutex); @@ -690,18 +960,19 @@ mptsas_target_alloc(struct scsi_target *starget) if (p->phy_info[i].attached.sas_address != rphy->identify.sas_address) continue; - target_id = p->phy_info[i].attached.id; + id = p->phy_info[i].attached.id; channel = p->phy_info[i].attached.channel; mptsas_set_starget(&p->phy_info[i], starget); /* * Exposing hidden raid components */ - if (mptscsih_is_phys_disk(hd->ioc, target_id)) { - target_id = mptscsih_raid_id_to_num(hd, - target_id); + if (mptscsih_is_phys_disk(hd->ioc, channel, id)) { + id = mptscsih_raid_id_to_num(hd->ioc, + channel, id); vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; + p->phy_info[i].attached.phys_disk_num = id; } mutex_unlock(&hd->ioc->sas_topology_mutex); goto out; @@ -713,8 +984,8 @@ mptsas_target_alloc(struct scsi_target *starget) return -ENXIO; out: - vtarget->target_id = target_id; - vtarget->bus_id = channel; + vtarget->id = id; + vtarget->channel = channel; starget->hostdata = vtarget; return 0; } @@ -786,7 +1057,8 @@ mptsas_slave_alloc(struct scsi_device *sdev) * Exposing hidden raid components */ if (mptscsih_is_phys_disk(hd->ioc, - p->phy_info[i].attached.id)) + p->phy_info[i].attached.channel, + p->phy_info[i].attached.id)) sdev->no_uld_attach = 1; mutex_unlock(&hd->ioc->sas_topology_mutex); goto out; @@ -808,13 +1080,14 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { VirtDevice *vdev = SCpnt->device->hostdata; -// scsi_print_command(SCpnt); - if (vdev->vtarget->deleted) { + if (!vdev || !vdev->vtarget || vdev->vtarget->deleted) { SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); return 0; } +// scsi_print_command(SCpnt); + return mptscsih_qcmd(SCpnt,done); } @@ -1114,9 +1387,6 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) goto out_free_consistent; } - if (port_info->num_phys) - port_info->handle = - le16_to_cpu(buffer->PhyData[0].ControllerDevHandle); for (i = 0; i < port_info->num_phys; i++) { mptsas_print_phy_data(&buffer->PhyData[i]); port_info->phy_info[i].phy_id = i; @@ -1125,6 +1395,8 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) port_info->phy_info[i].negotiated_link_rate = buffer->PhyData[i].NegotiatedLinkRate; port_info->phy_info[i].portinfo = port_info; + port_info->phy_info[i].handle = + le16_to_cpu(buffer->PhyData[i].ControllerDevHandle); } out_free_consistent: @@ -1261,6 +1533,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, device_info->phy_id = buffer->PhyNum; device_info->port_id = buffer->PhysicalPort; device_info->id = buffer->TargetID; + device_info->phys_disk_num = ~0; device_info->channel = buffer->Bus; memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64)); device_info->sas_address = le64_to_cpu(sas_address); @@ -1325,7 +1598,6 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info, /* save config data */ port_info->num_phys = buffer->NumPhys; - port_info->handle = le16_to_cpu(buffer->DevHandle); port_info->phy_info = kcalloc(port_info->num_phys, sizeof(*port_info->phy_info),GFP_KERNEL); if (!port_info->phy_info) { @@ -1333,8 +1605,11 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info, goto out_free_consistent; } - for (i = 0; i < port_info->num_phys; i++) + for (i = 0; i < port_info->num_phys; i++) { port_info->phy_info[i].portinfo = port_info; + port_info->phy_info[i].handle = + le16_to_cpu(buffer->DevHandle); + } out_free_consistent: pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, @@ -1702,7 +1977,6 @@ static int mptsas_probe_hba_phys(MPT_ADAPTER *ioc) { struct mptsas_portinfo *port_info, *hba; - u32 handle = 0xFFFF; int error = -ENOMEM, i; hba = kzalloc(sizeof(*port_info), GFP_KERNEL); @@ -1714,34 +1988,36 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc) goto out_free_port_info; mutex_lock(&ioc->sas_topology_mutex); - ioc->handle = hba->handle; - port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle); + ioc->handle = hba->phy_info[0].handle; + port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle); if (!port_info) { port_info = hba; list_add_tail(&port_info->list, &ioc->sas_topology); } else { - port_info->handle = hba->handle; - for (i = 0; i < hba->num_phys; i++) + for (i = 0; i < hba->num_phys; i++) { port_info->phy_info[i].negotiated_link_rate = hba->phy_info[i].negotiated_link_rate; + port_info->phy_info[i].handle = + hba->phy_info[i].handle; + port_info->phy_info[i].port_id = + hba->phy_info[i].port_id; + } kfree(hba->phy_info); kfree(hba); hba = NULL; } mutex_unlock(&ioc->sas_topology_mutex); - for (i = 0; i < port_info->num_phys; i++) { mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i], (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER << MPI_SAS_PHY_PGAD_FORM_SHIFT), i); mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify, - (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE << - MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle); + (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << + MPI_SAS_DEVICE_PGAD_FORM_SHIFT), + port_info->phy_info[i].handle); port_info->phy_info[i].identify.phy_id = - port_info->phy_info[i].phy_id; - handle = port_info->phy_info[i].identify.handle; - + port_info->phy_info[i].phy_id = i; if (port_info->phy_info[i].attached.handle) mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].attached, @@ -1777,12 +2053,12 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle) goto out; error = mptsas_sas_expander_pg0(ioc, ex, - (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << - MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle); + (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << + MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle); if (error) goto out_free_port_info; - *handle = ex->handle; + *handle = ex->phy_info[0].handle; mutex_lock(&ioc->sas_topology_mutex); port_info = mptsas_find_portinfo_by_handle(ioc, *handle); @@ -1790,7 +2066,12 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle) port_info = ex; list_add_tail(&port_info->list, &ioc->sas_topology); } else { - port_info->handle = ex->handle; + for (i = 0; i < ex->num_phys; i++) { + port_info->phy_info[i].handle = + ex->phy_info[i].handle; + port_info->phy_info[i].port_id = + ex->phy_info[i].port_id; + } kfree(ex->phy_info); kfree(ex); ex = NULL; @@ -1868,8 +2149,6 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc) struct mptsas_portinfo buffer; struct mptsas_portinfo *port_info, *n, *parent; struct mptsas_phyinfo *phy_info; - struct scsi_target * starget; - VirtTarget * vtarget; struct sas_port * port; int i; u64 expander_sas_address; @@ -1884,26 +2163,8 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc) if (mptsas_sas_expander_pg0(ioc, &buffer, (MPI_SAS_EXPAND_PGAD_FORM_HANDLE << - MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) { - - /* - * Issue target reset to all child end devices - * then mark them deleted to prevent further - * IO going to them. - */ - phy_info = port_info->phy_info; - for (i = 0; i < port_info->num_phys; i++, phy_info++) { - starget = mptsas_get_starget(phy_info); - if (!starget) - continue; - vtarget = starget->hostdata; - if(vtarget->deleted) - continue; - vtarget->deleted = 1; - mptsas_target_reset(ioc, vtarget); - sas_port_delete(mptsas_get_port(phy_info)); - mptsas_port_delete(phy_info->port_details); - } + MPI_SAS_EXPAND_PGAD_FORM_SHIFT), + port_info->phy_info[0].handle)) { /* * Obtain the port_info instance to the parent port @@ -1972,11 +2233,13 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc) /* Reporting RAID volumes. */ + if (!ioc->ir_firmware) + goto out; if (!ioc->raid_data.pIocPg2) goto out; if (!ioc->raid_data.pIocPg2->NumActiveVolumes) goto out; - for (i=0; iraid_data.pIocPg2->NumActiveVolumes; i++) { + for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0); } @@ -2030,12 +2293,37 @@ mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address) mutex_lock(&ioc->sas_topology_mutex); list_for_each_entry(port_info, &ioc->sas_topology, list) { for (i = 0; i < port_info->num_phys; i++) { + if (!mptsas_is_end_device( + &port_info->phy_info[i].attached)) + continue; if (port_info->phy_info[i].attached.sas_address != sas_address) continue; + phy_info = &port_info->phy_info[i]; + break; + } + } + mutex_unlock(&ioc->sas_topology_mutex); + return phy_info; +} + +static struct mptsas_phyinfo * +mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id) +{ + struct mptsas_portinfo *port_info; + struct mptsas_phyinfo *phy_info = NULL; + int i; + + mutex_lock(&ioc->sas_topology_mutex); + list_for_each_entry(port_info, &ioc->sas_topology, list) { + for (i = 0; i < port_info->num_phys; i++) { if (!mptsas_is_end_device( &port_info->phy_info[i].attached)) continue; + if (port_info->phy_info[i].attached.id != id) + continue; + if (port_info->phy_info[i].attached.channel != channel) + continue; phy_info = &port_info->phy_info[i]; break; } @@ -2045,7 +2333,7 @@ mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address) } static struct mptsas_phyinfo * -mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) +mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id) { struct mptsas_portinfo *port_info; struct mptsas_phyinfo *phy_info = NULL; @@ -2054,11 +2342,15 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) mutex_lock(&ioc->sas_topology_mutex); list_for_each_entry(port_info, &ioc->sas_topology, list) { for (i = 0; i < port_info->num_phys; i++) { - if (port_info->phy_info[i].attached.id != id) - continue; if (!mptsas_is_end_device( &port_info->phy_info[i].attached)) continue; + if (port_info->phy_info[i].attached.phys_disk_num == ~0) + continue; + if (port_info->phy_info[i].attached.phys_disk_num != id) + continue; + if (port_info->phy_info[i].attached.channel != channel) + continue; phy_info = &port_info->phy_info[i]; break; } @@ -2094,6 +2386,76 @@ mptsas_reprobe_target(struct scsi_target *starget, int uld_attach) mptsas_reprobe_lun); } +static void +mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id) +{ + CONFIGPARMS cfg; + ConfigPageHeader_t hdr; + dma_addr_t dma_handle; + pRaidVolumePage0_t buffer = NULL; + RaidPhysDiskPage0_t phys_disk; + int i; + struct mptsas_hotplug_event *ev; + + memset(&cfg, 0 , sizeof(CONFIGPARMS)); + memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); + hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME; + cfg.pageAddr = (channel << 8) + id; + cfg.cfghdr.hdr = &hdr; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + + if (mpt_config(ioc, &cfg) != 0) + goto out; + + if (!hdr.PageLength) + goto out; + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, + &dma_handle); + + if (!buffer) + goto out; + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + if (mpt_config(ioc, &cfg) != 0) + goto out; + + if (!(buffer->VolumeStatus.Flags & + MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE)) + goto out; + + if (!buffer->NumPhysDisks) + goto out; + + for (i = 0; i < buffer->NumPhysDisks; i++) { + + if (mpt_raid_phys_disk_pg0(ioc, + buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0) + continue; + + ev = kzalloc(sizeof(*ev), GFP_ATOMIC); + if (!ev) { + printk(KERN_WARNING "mptsas: lost hotplug event\n"); + goto out; + } + + INIT_WORK(&ev->work, mptsas_hotplug_work); + ev->ioc = ioc; + ev->id = phys_disk.PhysDiskID; + ev->channel = phys_disk.PhysDiskBus; + ev->phys_disk_num_valid = 1; + ev->phys_disk_num = phys_disk.PhysDiskNum; + ev->event_type = MPTSAS_ADD_DEVICE; + schedule_work(&ev->work); + } + + out: + if (buffer) + pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, + dma_handle); +} /* * Work queue thread to handle SAS hotplug events */ @@ -2102,6 +2464,7 @@ mptsas_hotplug_work(struct work_struct *work) { struct mptsas_hotplug_event *ev = container_of(work, struct mptsas_hotplug_event, work); + MPT_ADAPTER *ioc = ev->ioc; struct mptsas_phyinfo *phy_info; struct sas_rphy *rphy; @@ -2114,17 +2477,43 @@ mptsas_hotplug_work(struct work_struct *work) VirtTarget *vtarget; VirtDevice *vdevice; - mutex_lock(&ioc->sas_discovery_mutex); switch (ev->event_type) { case MPTSAS_DEL_DEVICE: - phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id); + phy_info = NULL; + if (ev->phys_disk_num_valid) { + if (ev->hidden_raid_component){ + if (mptsas_sas_device_pg0(ioc, &sas_device, + (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << + MPI_SAS_DEVICE_PGAD_FORM_SHIFT), + (ev->channel << 8) + ev->id)) { + dfailprintk((MYIOC_s_ERR_FMT + "%s: exit at line=%d\n", ioc->name, + __FUNCTION__, __LINE__)); + break; + } + phy_info = mptsas_find_phyinfo_by_sas_address( + ioc, sas_device.sas_address); + }else + phy_info = mptsas_find_phyinfo_by_phys_disk_num( + ioc, ev->channel, ev->phys_disk_num); + } + + if (!phy_info) + phy_info = mptsas_find_phyinfo_by_target(ioc, + ev->channel, ev->id); /* * Sanity checks, for non-existing phys and remote rphys. */ - if (!phy_info || !phy_info->port_details) { + if (!phy_info){ + dfailprintk((MYIOC_s_ERR_FMT + "%s: exit at line=%d\n", ioc->name, + __FUNCTION__, __LINE__)); + break; + } + if (!phy_info->port_details) { dfailprintk((MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); @@ -2137,6 +2526,7 @@ mptsas_hotplug_work(struct work_struct *work) __FUNCTION__, __LINE__)); break; } + port = mptsas_get_port(phy_info); if (!port) { dfailprintk((MYIOC_s_ERR_FMT @@ -2159,28 +2549,35 @@ mptsas_hotplug_work(struct work_struct *work) /* * Handling RAID components */ - if (ev->phys_disk_num_valid) { - vtarget->target_id = ev->phys_disk_num; - vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; + if (ev->phys_disk_num_valid && + ev->hidden_raid_component) { + printk(MYIOC_s_INFO_FMT + "RAID Hidding: channel=%d, id=%d, " + "physdsk %d \n", ioc->name, ev->channel, + ev->id, ev->phys_disk_num); + vtarget->id = ev->phys_disk_num; + vtarget->tflags |= + MPT_TARGET_FLAGS_RAID_COMPONENT; mptsas_reprobe_target(starget, 1); - break; + phy_info->attached.phys_disk_num = + ev->phys_disk_num; + break; } - - vtarget->deleted = 1; - mptsas_target_reset(ioc, vtarget); } - if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) + if (phy_info->attached.device_info & + MPI_SAS_DEVICE_INFO_SSP_TARGET) ds = "ssp"; - if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET) + if (phy_info->attached.device_info & + MPI_SAS_DEVICE_INFO_STP_TARGET) ds = "stp"; - if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE) + if (phy_info->attached.device_info & + MPI_SAS_DEVICE_INFO_SATA_DEVICE) ds = "sata"; printk(MYIOC_s_INFO_FMT "removing %s device, channel %d, id %d, phy %d\n", ioc->name, ds, ev->channel, ev->id, phy_info->phy_id); - #ifdef MPT_DEBUG_SAS_WIDE dev_printk(KERN_DEBUG, &port->dev, "delete port (%d)\n", port->port_identifier); @@ -2198,14 +2595,14 @@ mptsas_hotplug_work(struct work_struct *work) */ if (mptsas_sas_device_pg0(ioc, &sas_device, (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << - MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) { + MPI_SAS_DEVICE_PGAD_FORM_SHIFT), + (ev->channel << 8) + ev->id)) { dfailprintk((MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); break; } - ssleep(2); __mptsas_discovery_work(ioc); phy_info = mptsas_find_phyinfo_by_sas_address(ioc, @@ -2219,7 +2616,8 @@ mptsas_hotplug_work(struct work_struct *work) } starget = mptsas_get_starget(phy_info); - if (starget) { + if (starget && (!ev->hidden_raid_component)){ + vtarget = starget->hostdata; if (!vtarget) { @@ -2232,9 +2630,15 @@ mptsas_hotplug_work(struct work_struct *work) * Handling RAID components */ if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { - vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT; - vtarget->target_id = ev->id; + printk(MYIOC_s_INFO_FMT + "RAID Exposing: channel=%d, id=%d, " + "physdsk %d \n", ioc->name, ev->channel, + ev->id, ev->phys_disk_num); + vtarget->tflags &= + ~MPT_TARGET_FLAGS_RAID_COMPONENT; + vtarget->id = ev->id; mptsas_reprobe_target(starget, 0); + phy_info->attached.phys_disk_num = ~0; } break; } @@ -2243,8 +2647,10 @@ mptsas_hotplug_work(struct work_struct *work) dfailprintk((MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); + if (ev->channel) printk("%d\n", __LINE__); break; } + port = mptsas_get_port(phy_info); if (!port) { dfailprintk((MYIOC_s_ERR_FMT @@ -2252,15 +2658,17 @@ mptsas_hotplug_work(struct work_struct *work) __FUNCTION__, __LINE__)); break; } - memcpy(&phy_info->attached, &sas_device, sizeof(struct mptsas_devinfo)); - if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) + if (phy_info->attached.device_info & + MPI_SAS_DEVICE_INFO_SSP_TARGET) ds = "ssp"; - if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET) + if (phy_info->attached.device_info & + MPI_SAS_DEVICE_INFO_STP_TARGET) ds = "stp"; - if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE) + if (phy_info->attached.device_info & + MPI_SAS_DEVICE_INFO_SATA_DEVICE) ds = "sata"; printk(MYIOC_s_INFO_FMT @@ -2301,19 +2709,21 @@ mptsas_hotplug_work(struct work_struct *work) break; case MPTSAS_DEL_RAID: sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, - ev->id, 0); + ev->id, 0); if (!sdev) break; printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, id %d\n", ioc->name, MPTSAS_RAID_CHANNEL, ev->id); vdevice = sdev->hostdata; - vdevice->vtarget->deleted = 1; - mptsas_target_reset(ioc, vdevice->vtarget); scsi_remove_device(sdev); scsi_device_put(sdev); mpt_findImVolumes(ioc); break; + case MPTSAS_ADD_INACTIVE_VOLUME: + mptsas_adding_inactive_raid_components(ioc, + ev->channel, ev->id); + break; case MPTSAS_IGNORE_EVENT: default: break; @@ -2321,7 +2731,6 @@ mptsas_hotplug_work(struct work_struct *work) mutex_unlock(&ioc->sas_discovery_mutex); kfree(ev); - } static void @@ -2339,8 +2748,12 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, return; switch (sas_event_data->ReasonCode) { - case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: + + mptsas_target_reset_queue(ioc, sas_event_data); + break; + + case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: ev = kzalloc(sizeof(*ev), GFP_ATOMIC); if (!ev) { printk(KERN_WARNING "mptsas: lost hotplug event\n"); @@ -2375,15 +2788,20 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, mptsas_persist_clear_table); schedule_work(&ioc->sas_persist_task); break; + /* + * TODO, handle other events + */ case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: - /* TODO */ + case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED: case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: - /* TODO */ + case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL: + case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL: + case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL: + case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL: default: break; } } - static void mptsas_send_raid_event(MPT_ADAPTER *ioc, EVENT_DATA_RAID *raid_event_data) @@ -2404,31 +2822,36 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc, INIT_WORK(&ev->work, mptsas_hotplug_work); ev->ioc = ioc; ev->id = raid_event_data->VolumeID; + ev->channel = raid_event_data->VolumeBus; ev->event_type = MPTSAS_IGNORE_EVENT; switch (raid_event_data->ReasonCode) { case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: + ev->phys_disk_num_valid = 1; + ev->phys_disk_num = raid_event_data->PhysDiskNum; ev->event_type = MPTSAS_ADD_DEVICE; break; case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: - ioc->raid_data.isRaid = 1; ev->phys_disk_num_valid = 1; ev->phys_disk_num = raid_event_data->PhysDiskNum; + ev->hidden_raid_component = 1; ev->event_type = MPTSAS_DEL_DEVICE; break; case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED: switch (state) { case MPI_PD_STATE_ONLINE: - ioc->raid_data.isRaid = 1; + case MPI_PD_STATE_NOT_COMPATIBLE: ev->phys_disk_num_valid = 1; ev->phys_disk_num = raid_event_data->PhysDiskNum; + ev->hidden_raid_component = 1; ev->event_type = MPTSAS_ADD_DEVICE; break; case MPI_PD_STATE_MISSING: - case MPI_PD_STATE_NOT_COMPATIBLE: case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST: case MPI_PD_STATE_FAILED_AT_HOST_REQUEST: case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON: + ev->phys_disk_num_valid = 1; + ev->phys_disk_num = raid_event_data->PhysDiskNum; ev->event_type = MPTSAS_DEL_DEVICE; break; default: @@ -2485,6 +2908,35 @@ mptsas_send_discovery_event(MPT_ADAPTER *ioc, schedule_work(&ev->work); }; +/* + * mptsas_send_ir2_event - handle exposing hidden disk when + * an inactive raid volume is added + * + * @ioc: Pointer to MPT_ADAPTER structure + * @ir2_data + * + */ +static void +mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data) +{ + struct mptsas_hotplug_event *ev; + + if (ir2_data->ReasonCode != + MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED) + return; + + ev = kzalloc(sizeof(*ev), GFP_ATOMIC); + if (!ev) + return; + + INIT_WORK(&ev->work, mptsas_hotplug_work); + ev->ioc = ioc; + ev->id = ir2_data->TargetID; + ev->channel = ir2_data->Bus; + ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME; + + schedule_work(&ev->work); +}; static int mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) @@ -2524,6 +2976,10 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) mptsas_send_discovery_event(ioc, (EVENT_DATA_SAS_DISCOVERY *)reply->Data); break; + case MPI_EVENT_IR2: + mptsas_send_ir2_event(ioc, + (PTR_MPI_EVENT_DATA_IR2)reply->Data); + break; default: rc = mptscsih_event_process(ioc, reply); break; @@ -2611,12 +3067,11 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* set 16 byte cdb's */ sh->max_cmd_len = 16; - sh->max_id = ioc->pfacts->MaxDevices + 1; + sh->max_id = ioc->pfacts[0].PortSCSIID; + sh->max_lun = max_lun; sh->transportt = mptsas_transport_template; - sh->max_lun = MPT_LAST_LUN + 1; - sh->max_channel = 0; sh->this_id = ioc->pfacts[0].PortSCSIID; /* Required entry. @@ -2659,8 +3114,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) sh->sg_tablesize = numSGE; } - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - hd = (MPT_SCSI_HOST *) sh->hostdata; hd->ioc = ioc; @@ -2676,19 +3129,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", ioc->name, hd->ScsiLookup)); - /* Allocate memory for the device structures. - * A non-Null pointer at an offset - * indicates a device exists. - * max_id = 1 + maximum id (hosts.h) - */ - hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC); - if (!hd->Targets) { - error = -ENOMEM; - goto out_mptsas_probe; - } - - dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets)); - /* Clear the TM flags */ hd->tmPending = 0; @@ -2713,15 +3153,17 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->sas_data.ptClear = mpt_pt_clear; + init_waitqueue_head(&hd->scandv_waitq); + hd->scandv_wait_done = 0; + hd->last_queue_full = 0; + INIT_LIST_HEAD(&hd->target_reset_list); + spin_unlock_irqrestore(&ioc->FreeQlock, flags); + if (ioc->sas_data.ptClear==1) { mptbase_sas_persist_operation( ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT); } - init_waitqueue_head(&hd->scandv_waitq); - hd->scandv_wait_done = 0; - hd->last_queue_full = 0; - error = scsi_add_host(sh, &ioc->pcidev->dev); if (error) { dprintk((KERN_ERR MYNAM @@ -2745,7 +3187,7 @@ static void __devexit mptsas_remove(struct pci_dev *pdev) struct mptsas_portinfo *p, *n; int i; - ioc->sas_discovery_ignore_events=1; + ioc->sas_discovery_ignore_events = 1; sas_remove_host(ioc->sh); mutex_lock(&ioc->sas_topology_mutex); @@ -2800,7 +3242,7 @@ mptsas_init(void) return -ENODEV; mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER); - mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER); + mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER); mptsasInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); @@ -2810,7 +3252,7 @@ mptsas_init(void) ": Registered for IOC event notifications\n")); } - if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) { + if (mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset) == 0) { dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n")); } diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index f0cca3ea93b20b8d4f72279480ac56e81e681b13..c417ae0b5fe61c017da74fd45d4cd593cc49cd45 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -4,7 +4,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2007 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -79,43 +79,6 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(my_VERSION); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -typedef struct _BIG_SENSE_BUF { - u8 data[MPT_SENSE_BUFFER_ALLOC]; -} BIG_SENSE_BUF; - -#define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */ -#define MPT_SCANDV_DID_RESET (0x00000001) -#define MPT_SCANDV_SENSE (0x00000002) -#define MPT_SCANDV_SOME_ERROR (0x00000004) -#define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008) -#define MPT_SCANDV_ISSUE_SENSE (0x00000010) -#define MPT_SCANDV_FALLBACK (0x00000020) - -#define MPT_SCANDV_MAX_RETRIES (10) - -#define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */ -#define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */ -#define MPT_ICFLAG_EBOS 0x04 /* ReadBuffer Echo buffer has EBOS */ -#define MPT_ICFLAG_PHYS_DISK 0x08 /* Any SCSI IO but do Phys Disk Format */ -#define MPT_ICFLAG_TAGGED_CMD 0x10 /* Do tagged IO */ -#define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */ -#define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */ - -typedef struct _internal_cmd { - char *data; /* data pointer */ - dma_addr_t data_dma; /* data dma address */ - int size; /* transfer size */ - u8 cmd; /* SCSI Op Code */ - u8 bus; /* bus number */ - u8 id; /* SCSI ID (virtual) */ - u8 lun; - u8 flags; /* Bit Field - See above */ - u8 physDiskNum; /* Phys disk number, -1 else */ - u8 rsvd2; - u8 rsvd; -} INTERNAL_CMD; - /* * Other private/forward protos... */ @@ -131,14 +94,11 @@ static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); -static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); +static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout); int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); -static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev); -static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev); -static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus); int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); @@ -517,16 +477,100 @@ mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget, SEPMsg = (SEPRequest_t *)mf; SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR; - SEPMsg->Bus = vtarget->bus_id; - SEPMsg->TargetID = vtarget->target_id; + SEPMsg->Bus = vtarget->channel; + SEPMsg->TargetID = vtarget->id; SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS; SEPMsg->SlotStatus = SlotStatus; devtverboseprintk((MYIOC_s_WARN_FMT - "Sending SEP cmd=%x id=%d bus=%d\n", - ioc->name, SlotStatus, SEPMsg->TargetID, SEPMsg->Bus)); + "Sending SEP cmd=%x channel=%d id=%d\n", + ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID)); mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); } +#ifdef MPT_DEBUG_REPLY +/** + * mptscsih_iocstatus_info_scsiio - IOCSTATUS information for SCSIIO + * @ioc: Pointer to MPT_ADAPTER structure + * @ioc_status: U32 IOCStatus word from IOC + * @scsi_status: U8 sam status from target + * @scsi_state: U8 scsi state + * @sc: original scsi cmnd pointer + * @mf: Pointer to MPT request frame + * + * Refer to lsi/mpi.h. + **/ +static void +mptscsih_iocstatus_info_scsiio(MPT_ADAPTER *ioc, u32 ioc_status, + u8 scsi_status, u8 scsi_state, struct scsi_cmnd *sc) +{ + char extend_desc[EVENT_DESCR_STR_SZ]; + char *desc = NULL; + + switch (ioc_status) { + + case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */ + desc = "SCSI Invalid Bus"; + break; + + case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */ + desc = "SCSI Invalid TargetID"; + break; + + case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ + /* + * Inquiry is issued for device scanning + */ + if (sc->cmnd[0] != 0x12) + desc = "SCSI Device Not There"; + break; + + case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ + desc = "SCSI Data Overrun"; + break; + + case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ + desc = "SCSI I/O Data Error"; + break; + + case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ + desc = "SCSI Protocol Error"; + break; + + case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ + desc = "SCSI Task Terminated"; + break; + + case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ + desc = "SCSI Residual Mismatch"; + break; + + case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */ + desc = "SCSI Task Management Failed"; + break; + + case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ + desc = "SCSI IOC Terminated"; + break; + + case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ + desc = "SCSI Ext Terminated"; + break; + } + + if (!desc) + return; + + snprintf(extend_desc, EVENT_DESCR_STR_SZ, + "[%d:%d:%d:%d] cmd=%02Xh, sam_status=%02Xh state=%02Xh", + sc->device->host->host_no, + sc->device->channel, sc->device->id, sc->device->lun, + sc->cmnd[0], scsi_status, scsi_state); + + printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n", + ioc->name, ioc_status, desc, extend_desc); +} +#endif + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mptscsih_io_done - Main SCSI IO callback routine registered to @@ -613,12 +657,14 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) u32 xfer_cnt; u16 status; u8 scsi_state, scsi_status; + u32 log_info; status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK; scsi_state = pScsiReply->SCSIState; scsi_status = pScsiReply->SCSIStatus; xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); sc->resid = sc->request_bufflen - xfer_cnt; + log_info = le32_to_cpu(pScsiReply->IOCLogInfo); /* * if we get a data underrun indication, yet no data was @@ -633,13 +679,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) status = MPI_IOCSTATUS_SUCCESS; } - dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n" - "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n" - "resid=%d bufflen=%d xfer_cnt=%d\n", - ioc->id, sc->device->id, sc->device->lun, - status, scsi_state, scsi_status, sc->resid, - sc->request_bufflen, xfer_cnt)); - if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) mptscsih_copy_sense_data(sc, hd, mf, pScsiReply); @@ -648,9 +687,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) */ if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID && pScsiReply->ResponseInfo) { - printk(KERN_NOTICE "ha=%d id=%d lun=%d: " + printk(KERN_NOTICE "[%d:%d:%d:%d] " "FCP_ResponseInfo=%08xh\n", - ioc->id, sc->device->id, sc->device->lun, + sc->device->host->host_no, sc->device->channel, + sc->device->id, sc->device->lun, le32_to_cpu(pScsiReply->ResponseInfo)); } @@ -695,9 +735,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) if ( ioc->bus_type == SAS ) { u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus); if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { - u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo); - log_info &=SAS_LOGINFO_MASK; - if (log_info == SAS_LOGINFO_NEXUS_LOSS) { + if ((log_info & SAS_LOGINFO_MASK) + == SAS_LOGINFO_NEXUS_LOSS) { sc->result = (DID_BUS_BUSY << 16); break; } @@ -735,7 +774,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) else /* Sufficient data transfer occurred */ sc->result = (DID_OK << 16) | scsi_status; dreplyprintk((KERN_NOTICE - "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id)); + "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n", + sc->result, sc->device->channel, sc->device->id)); break; case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ @@ -848,7 +888,28 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) } /* switch(status) */ - dreplyprintk((KERN_NOTICE " sc->result is %08xh\n", sc->result)); +#ifdef MPT_DEBUG_REPLY + if (sc->result) { + + mptscsih_iocstatus_info_scsiio(ioc, status, + scsi_status, scsi_state, sc); + + dreplyprintk(("%s: [%d:%d:%d:%d] cmd=0x%02x " + "result=0x%08x\n\tiocstatus=0x%04X " + "scsi_state=0x%02X scsi_status=0x%02X " + "loginfo=0x%08X\n", __FUNCTION__, + sc->device->host->host_no, sc->device->channel, sc->device->id, + sc->device->lun, sc->cmnd[0], sc->result, status, + scsi_state, scsi_status, log_info)); + + dreplyprintk(("%s: [%d:%d:%d:%d] resid=%d " + "bufflen=%d xfer_cnt=%d\n", __FUNCTION__, + sc->device->host->host_no, sc->device->channel, sc->device->id, + sc->device->lun, sc->resid, sc->request_bufflen, + xfer_cnt)); + } +#endif + } /* end of address reply case */ /* Unmap the DMA buffers, if any. */ @@ -955,9 +1016,10 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) int ii; int max = hd->ioc->req_depth; struct scsi_cmnd *sc; + struct scsi_lun lun; - dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n", - vdevice->vtarget->target_id, vdevice->lun, max)); + dsprintk((KERN_INFO MYNAM ": search_running channel %d id %d lun %d max %d\n", + vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, max)); for (ii=0; ii < max; ii++) { if ((sc = hd->ScsiLookup[ii]) != NULL) { @@ -965,10 +1027,14 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii); if (mf == NULL) continue; - dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n", - hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1])); - if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun))) + int_to_scsilun(vdevice->lun, &lun); + if ((mf->Bus != vdevice->vtarget->channel) || + (mf->TargetID != vdevice->vtarget->id) || + memcmp(lun.scsi_lun, mf->LUN, 8)) continue; + dsprintk(( "search_running: found (sc=%p, mf = %p) " + "channel %d id %d, lun %d \n", hd->ScsiLookup[ii], + mf, mf->Bus, mf->TargetID, vdevice->lun)); /* Cleanup */ @@ -1065,12 +1131,6 @@ mptscsih_remove(struct pci_dev *pdev) hd->ScsiLookup = NULL; } - /* - * Free pointer array. - */ - kfree(hd->Targets); - hd->Targets = NULL; - dprintk((MYIOC_s_INFO_FMT "Free'd ScsiLookup (%d) memory\n", hd->ioc->name, sz1)); @@ -1317,14 +1377,6 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) return SCSI_MLQUEUE_HOST_BUSY; } - if ((hd->ioc->bus_type == SPI) && - vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT && - mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) { - SCpnt->result = DID_NO_CONNECT << 16; - done(SCpnt); - return 0; - } - /* * Put together a MPT SCSI request... */ @@ -1368,8 +1420,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) /* Use the above information to set up the message frame */ - pScsiReq->TargetID = (u8) vdev->vtarget->target_id; - pScsiReq->Bus = vdev->vtarget->bus_id; + pScsiReq->TargetID = (u8) vdev->vtarget->id; + pScsiReq->Bus = vdev->vtarget->channel; pScsiReq->ChainOffset = 0; if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; @@ -1379,14 +1431,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; pScsiReq->Reserved = 0; pScsiReq->MsgFlags = mpt_msg_flags(); - pScsiReq->LUN[0] = 0; - pScsiReq->LUN[1] = lun; - pScsiReq->LUN[2] = 0; - pScsiReq->LUN[3] = 0; - pScsiReq->LUN[4] = 0; - pScsiReq->LUN[5] = 0; - pScsiReq->LUN[6] = 0; - pScsiReq->LUN[7] = 0; + int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN); pScsiReq->Control = cpu_to_le32(scsictl); /* @@ -1491,14 +1536,14 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mptscsih_TMHandler - Generic handler for SCSI Task Management. * Fall through to mpt_HardResetHandler if: not operational, too many * failed TM requests or handshake failure. * * @ioc: Pointer to MPT_ADAPTER structure * @type: Task Management type - * @target: Logical Target ID for reset (if appropriate) + * @id: Logical Target ID for reset (if appropriate) * @lun: Logical Unit for reset (if appropriate) * @ctx2abort: Context for the task to be aborted (if appropriate) * @@ -1507,28 +1552,17 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC * will be active. * - * Returns 0 for SUCCESS or -1 if FAILED. - */ + * Returns 0 for SUCCESS, or FAILED. + **/ int -mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout) +mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) { MPT_ADAPTER *ioc; int rc = -1; - int doTask = 1; u32 ioc_raw_state; unsigned long flags; - /* If FW is being reloaded currently, return success to - * the calling function. - */ - if (hd == NULL) - return 0; - ioc = hd->ioc; - if (ioc == NULL) { - printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n"); - return FAILED; - } dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name)); // SJR - CHECKME - Can we avoid this here? @@ -1541,8 +1575,10 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in spin_unlock_irqrestore(&ioc->diagLock, flags); /* Wait a fixed amount of time for the TM pending flag to be cleared. - * If we time out and not bus reset, then we return a FAILED status to the caller. - * The call to mptscsih_tm_pending_wait() will set the pending flag if we are + * If we time out and not bus reset, then we return a FAILED status + * to the caller. + * The call to mptscsih_tm_pending_wait() will set the pending flag + * if we are * successful. Otherwise, reload the FW. */ if (mptscsih_tm_pending_wait(hd) == FAILED) { @@ -1552,18 +1588,16 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in hd->ioc->name, hd->tmPending)); return FAILED; } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { - dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: " - "Timed out waiting for last TM (%d) to complete! \n", - hd->ioc->name, hd->tmPending)); + dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target " + "reset: Timed out waiting for last TM (%d) " + "to complete! \n", hd->ioc->name, + hd->tmPending)); return FAILED; } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: " "Timed out waiting for last TM (%d) to complete! \n", hd->ioc->name, hd->tmPending)); - if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)) - return FAILED; - - doTask = 0; + return FAILED; } } else { spin_lock_irqsave(&hd->ioc->FreeQlock, flags); @@ -1571,47 +1605,40 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); } - /* Is operational? - */ ioc_raw_state = mpt_GetIocState(hd->ioc, 0); -#ifdef MPT_DEBUG_RESET if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) { printk(MYIOC_s_WARN_FMT - "TM Handler: IOC Not operational(0x%x)!\n", - hd->ioc->name, ioc_raw_state); - } -#endif - - if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) - && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) { - - /* Isse the Task Mgmt request. - */ - if (hd->hard_resets < -1) - hd->hard_resets++; - rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout); - if (rc) { - printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name); - } else { - dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name)); - } + "TM Handler for type=%x: IOC Not operational (0x%x)!\n", + ioc->name, type, ioc_raw_state); + printk(KERN_WARNING " Issuing HardReset!!\n"); + if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) + printk((KERN_WARNING "TMHandler: HardReset " + "FAILED!!\n")); + return FAILED; } - /* Only fall through to the HRH if this is a bus reset - */ - if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc || - ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) { - dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", - hd->ioc->name)); - rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); + if (ioc_raw_state & MPI_DOORBELL_ACTIVE) { + printk(MYIOC_s_WARN_FMT + "TM Handler for type=%x: ioc_state: " + "DOORBELL_ACTIVE (0x%x)!\n", + ioc->name, type, ioc_raw_state); + return FAILED; } - /* - * Check IOCStatus from TM reply message + /* Isse the Task Mgmt request. */ - if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS) - rc = FAILED; + if (hd->hard_resets < -1) + hd->hard_resets++; + + rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun, + ctx2abort, timeout); + if (rc) + printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", + hd->ioc->name); + else + dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", + hd->ioc->name)); dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc)); @@ -1620,11 +1647,11 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mptscsih_IssueTaskMgmt - Generic send Task Management function. * @hd: Pointer to MPT_SCSI_HOST structure * @type: Task Management type - * @target: Logical Target ID for reset (if appropriate) + * @id: Logical Target ID for reset (if appropriate) * @lun: Logical Unit for reset (if appropriate) * @ctx2abort: Context for the task to be aborted (if appropriate) * @@ -1633,11 +1660,11 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in * * Not all fields are meaningfull for all task types. * - * Returns 0 for SUCCESS, -999 for "no msg frames", - * else other non-zero value returned. - */ + * Returns 0 for SUCCESS, or FAILED. + * + **/ static int -mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout) +mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) { MPT_FRAME_HDR *mf; SCSITaskMgmt_t *pScsiTm; @@ -1657,7 +1684,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun /* Format the Request */ pScsiTm = (SCSITaskMgmt_t *) mf; - pScsiTm->TargetID = target; + pScsiTm->TargetID = id; pScsiTm->Bus = channel; pScsiTm->ChainOffset = 0; pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; @@ -1668,42 +1695,59 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0; - for (ii= 0; ii < 8; ii++) { - pScsiTm->LUN[ii] = 0; - } - pScsiTm->LUN[1] = lun; + int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN); for (ii=0; ii < 7; ii++) pScsiTm->Reserved2[ii] = 0; pScsiTm->TaskMsgContext = ctx2abort; - dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n", - hd->ioc->name, ctx2abort, type)); + dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) " + "type=%d\n", hd->ioc->name, ctx2abort, type)); DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm); if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc, - sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, - CAN_SLEEP)) != 0) { - dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!" - " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, - hd->ioc, mf)); - mpt_free_msg_frame(hd->ioc, mf); - return retval; + sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) { + dfailprintk((MYIOC_s_ERR_FMT "send_handshake FAILED!" + " (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd, + hd->ioc, mf, retval)); + goto fail_out; } if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) { - dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!" + dfailprintk((MYIOC_s_ERR_FMT "task management request TIMED OUT!" " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf)); - mpt_free_msg_frame(hd->ioc, mf); dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", hd->ioc->name)); retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); + dtmprintk((MYIOC_s_INFO_FMT "rc=%d \n", + hd->ioc->name, retval)); + goto fail_out; } + /* + * Handle success case, see if theres a non-zero ioc_status. + */ + if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS || + hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED || + hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED) + retval = 0; + else + retval = FAILED; + return retval; + + fail_out: + + /* + * Free task managment mf, and corresponding tm flags + */ + mpt_free_msg_frame(hd->ioc, mf); + hd->tmPending = 0; + hd->tmState = TM_STATE_NONE; + return FAILED; } static int @@ -1728,7 +1772,7 @@ mptscsih_get_tm_timeout(MPT_ADAPTER *ioc) * (linux scsi_host_template.eh_abort_handler routine) * * Returns SUCCESS or FAILED. - */ + **/ int mptscsih_abort(struct scsi_cmnd * SCpnt) { @@ -1764,9 +1808,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) return SUCCESS; } - if (hd->resetPending) { + if (hd->resetPending) return FAILED; - } if (hd->timeouts < -1) hd->timeouts++; @@ -1789,13 +1832,12 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, - vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun, + vdev->vtarget->channel, vdev->vtarget->id, vdev->lun, ctx2abort, mptscsih_get_tm_timeout(hd->ioc)); if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx && - SCpnt->serial_number == sn) { + SCpnt->serial_number == sn) retval = FAILED; - } printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", hd->ioc->name, @@ -1803,12 +1845,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) if (retval == 0) return SUCCESS; - - if(retval != FAILED ) { - hd->tmPending = 0; - hd->tmState = TM_STATE_NONE; - } - return FAILED; + else + return FAILED; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1819,7 +1857,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) * (linux scsi_host_template.eh_dev_reset_handler routine) * * Returns SUCCESS or FAILED. - */ + **/ int mptscsih_dev_reset(struct scsi_cmnd * SCpnt) { @@ -1845,7 +1883,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, - vdev->vtarget->bus_id, vdev->vtarget->target_id, + vdev->vtarget->channel, vdev->vtarget->id, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n", @@ -1854,14 +1892,11 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) if (retval == 0) return SUCCESS; - - if(retval != FAILED ) { - hd->tmPending = 0; - hd->tmState = TM_STATE_NONE; - } - return FAILED; + else + return FAILED; } + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant @@ -1870,7 +1905,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) * (linux scsi_host_template.eh_bus_reset_handler routine) * * Returns SUCCESS or FAILED. - */ + **/ int mptscsih_bus_reset(struct scsi_cmnd * SCpnt) { @@ -1896,7 +1931,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - vdev->vtarget->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); + vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n", hd->ioc->name, @@ -1904,12 +1939,8 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) if (retval == 0) return SUCCESS; - - if(retval != FAILED ) { - hd->tmPending = 0; - hd->tmState = TM_STATE_NONE; - } - return FAILED; + else + return FAILED; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1992,7 +2023,6 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd) /** * mptscsih_tm_wait_for_completion - wait for completion of TM task * @hd: Pointer to MPT host structure. - * @timeout: timeout in seconds * * Returns {SUCCESS,FAILED}. */ @@ -2066,7 +2096,7 @@ mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) * load/init time via the mpt_register() API call. * * Returns 1 indicating alloc'd request frame ptr should be freed. - */ + **/ int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) { @@ -2076,78 +2106,85 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m unsigned long flags; u16 iocstatus; u8 tmType; + u32 termination_count; dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n", - ioc->name, mf, mr)); - if (ioc->sh) { - /* Depending on the thread, a timer is activated for - * the TM request. Delete this timer on completion of TM. - * Decrement count of outstanding TM requests. - */ - hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; - } else { - dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n", - ioc->name)); + ioc->name, mf, mr)); + if (!ioc->sh) { + dtmprintk((MYIOC_s_WARN_FMT + "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name)); return 1; } if (mr == NULL) { - dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n", - ioc->name, mf)); + dtmprintk((MYIOC_s_WARN_FMT + "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf)); return 1; - } else { - pScsiTmReply = (SCSITaskMgmtReply_t*)mr; - pScsiTmReq = (SCSITaskMgmt_t*)mf; - - /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */ - tmType = pScsiTmReq->TaskType; + } - if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && - pScsiTmReply->ResponseCode) - mptscsih_taskmgmt_response_code(ioc, - pScsiTmReply->ResponseCode); + hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + pScsiTmReply = (SCSITaskMgmtReply_t*)mr; + pScsiTmReq = (SCSITaskMgmt_t*)mf; + tmType = pScsiTmReq->TaskType; + iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; + termination_count = le32_to_cpu(pScsiTmReply->TerminationCount); + + if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && + pScsiTmReply->ResponseCode) + mptscsih_taskmgmt_response_code(ioc, + pScsiTmReply->ResponseCode); + DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply); + +#if defined(MPT_DEBUG_REPLY) || defined(MPT_DEBUG_TM) + printk("%s: ha=%d [%d:%d:0] task_type=0x%02X " + "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X " + "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus, + pScsiTmReply->TargetID, pScsiTmReq->TaskType, + le16_to_cpu(pScsiTmReply->IOCStatus), + le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode, + le32_to_cpu(pScsiTmReply->TerminationCount)); +#endif + if (!iocstatus) { + dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name)); + hd->abortSCpnt = NULL; + goto out; + } - dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n", - ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount))); - DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply); + /* Error? (anything non-zero?) */ - iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; - hd->tm_iocstatus = iocstatus; - dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n", - ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo))); - /* Error? (anything non-zero?) */ - if (iocstatus) { + /* clear flags and continue. + */ + switch (tmType) { - /* clear flags and continue. - */ - if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) - hd->abortSCpnt = NULL; + case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK: + if (termination_count == 1) + iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED; + hd->abortSCpnt = NULL; + break; - /* If an internal command is present - * or the TM failed - reload the FW. - * FC FW may respond FAILED to an ABORT - */ - if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { - if ((hd->cmdPtr) || - (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) { - if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) { - printk((KERN_WARNING - " Firmware Reload FAILED!!\n")); - } - } - } - } else { - dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name)); + case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS: - hd->abortSCpnt = NULL; + /* If an internal command is present + * or the TM failed - reload the FW. + * FC FW may respond FAILED to an ABORT + */ + if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED || + hd->cmdPtr) + if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) + printk((KERN_WARNING " Firmware Reload FAILED!!\n")); + break; - } + case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET: + default: + break; } + out: spin_lock_irqsave(&ioc->FreeQlock, flags); hd->tmPending = 0; - spin_unlock_irqrestore(&ioc->FreeQlock, flags); hd->tmState = TM_STATE_NONE; + hd->tm_iocstatus = iocstatus; + spin_unlock_irqrestore(&ioc->FreeQlock, flags); return 1; } @@ -2191,7 +2228,7 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, dprintk((KERN_NOTICE ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n", - sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors)); + sdev->id, sdev->lun, sdev->channel, (int)cylinders, heads, sectors)); return 0; } @@ -2200,115 +2237,78 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, * */ int -mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) +mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) { + struct inactive_raid_component_info *component_info; int i; + int rc = 0; - if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3) - return 0; + if (!ioc->raid_data.pIocPg3) + goto out; for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { - if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) - return 1; - } - return 0; -} -EXPORT_SYMBOL(mptscsih_is_phys_disk); - -int -mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid) -{ - int i; - - if (!hd->ioc->raid_data.isRaid || !hd->ioc->raid_data.pIocPg3) - return -ENXIO; - - for (i = 0; i < hd->ioc->raid_data.pIocPg3->NumPhysDisks; i++) { - if (physdiskid == - hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) - return hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum; + if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) && + (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) { + rc = 1; + goto out; + } } - return -ENXIO; -} -EXPORT_SYMBOL(mptscsih_raid_id_to_num); + /* + * Check inactive list for matching phys disks + */ + if (list_empty(&ioc->raid_data.inactive_list)) + goto out; -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * OS entry point to allow host driver to alloc memory - * for each scsi target. Called once per device the bus scan. - * Return non-zero if allocation fails. - */ -int -mptscsih_target_alloc(struct scsi_target *starget) -{ - VirtTarget *vtarget; + down(&ioc->raid_data.inactive_list_mutex); + list_for_each_entry(component_info, &ioc->raid_data.inactive_list, + list) { + if ((component_info->d.PhysDiskID == id) && + (component_info->d.PhysDiskBus == channel)) + rc = 1; + } + up(&ioc->raid_data.inactive_list_mutex); - vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL); - if (!vtarget) - return -ENOMEM; - starget->hostdata = vtarget; - vtarget->starget = starget; - return 0; + out: + return rc; } +EXPORT_SYMBOL(mptscsih_is_phys_disk); -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * OS entry point to allow host driver to alloc memory - * for each scsi device. Called once per device the bus scan. - * Return non-zero if allocation fails. - */ -int -mptscsih_slave_alloc(struct scsi_device *sdev) +u8 +mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) { - struct Scsi_Host *host = sdev->host; - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; - VirtTarget *vtarget; - VirtDevice *vdev; - struct scsi_target *starget; + struct inactive_raid_component_info *component_info; + int i; + int rc = -ENXIO; - vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); - if (!vdev) { - printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", - hd->ioc->name, sizeof(VirtDevice)); - return -ENOMEM; + if (!ioc->raid_data.pIocPg3) + goto out; + for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { + if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) && + (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) { + rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum; + goto out; + } } - vdev->lun = sdev->lun; - sdev->hostdata = vdev; - - starget = scsi_target(sdev); - vtarget = starget->hostdata; + /* + * Check inactive list for matching phys disks + */ + if (list_empty(&ioc->raid_data.inactive_list)) + goto out; - vdev->vtarget = vtarget; - - if (vtarget->num_luns == 0) { - hd->Targets[sdev->id] = vtarget; - vtarget->ioc_id = hd->ioc->id; - vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; - vtarget->target_id = sdev->id; - vtarget->bus_id = sdev->channel; - if (hd->ioc->bus_type == SPI && sdev->channel == 0 && - hd->ioc->raid_data.isRaid & (1 << sdev->id)) { - vtarget->raidVolume = 1; - ddvtprintk((KERN_INFO - "RAID Volume @ id %d\n", sdev->id)); - } + down(&ioc->raid_data.inactive_list_mutex); + list_for_each_entry(component_info, &ioc->raid_data.inactive_list, + list) { + if ((component_info->d.PhysDiskID == id) && + (component_info->d.PhysDiskBus == channel)) + rc = component_info->d.PhysDiskNum; } - vtarget->num_luns++; - return 0; -} + up(&ioc->raid_data.inactive_list_mutex); -/* - * OS entry point to allow for host driver to free allocated memory - * Called if no device present or device being unloaded - */ -void -mptscsih_target_destroy(struct scsi_target *starget) -{ - if (starget->hostdata) - kfree(starget->hostdata); - starget->hostdata = NULL; + out: + return rc; } +EXPORT_SYMBOL(mptscsih_raid_id_to_num); /* * OS entry point to allow for host driver to free allocated memory @@ -2328,11 +2328,7 @@ mptscsih_slave_destroy(struct scsi_device *sdev) vdevice = sdev->hostdata; mptscsih_search_running_cmds(hd, vdevice); - vtarget->luns[0] &= ~(1 << vdevice->lun); vtarget->num_luns--; - if (vtarget->num_luns == 0) { - hd->Targets[sdev->id] = NULL; - } mptscsih_synchronize_cache(hd, vdevice); kfree(vdevice); sdev->hostdata = NULL; @@ -2394,15 +2390,14 @@ mptscsih_slave_configure(struct scsi_device *sdev) VirtDevice *vdevice; struct scsi_target *starget; MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata; - int indexed_lun, lun_index; starget = scsi_target(sdev); vtarget = starget->hostdata; vdevice = sdev->hostdata; dsprintk((MYIOC_s_INFO_FMT - "device @ %p, id=%d, LUN=%d, channel=%d\n", - hd->ioc->name, sdev, sdev->id, sdev->lun, sdev->channel)); + "device @ %p, channel=%d, id=%d, lun=%d\n", + hd->ioc->name, sdev, sdev->channel, sdev->id, sdev->lun)); if (hd->ioc->bus_type == SPI) dsprintk((MYIOC_s_INFO_FMT "sdtr %d wdtr %d ppr %d inq length=%d\n", @@ -2415,11 +2410,7 @@ mptscsih_slave_configure(struct scsi_device *sdev) goto slave_configure_exit; } - vdevice->configured_lun=1; - lun_index = (vdevice->lun >> 5); /* 32 luns per lun_index */ - indexed_lun = (vdevice->lun % 32); - vtarget->luns[lun_index] |= (1 << indexed_lun); - mptscsih_initTarget(hd, vtarget, sdev); + vdevice->configured_lun = 1; mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); dsprintk((MYIOC_s_INFO_FMT @@ -2681,285 +2672,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) return 1; /* currently means nothing really */ } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptscsih_initTarget - Target, LUN alloc/free functionality. - * @hd: Pointer to MPT_SCSI_HOST structure - * @vtarget: per target private data - * @sdev: SCSI device - * - * NOTE: It's only SAFE to call this routine if data points to - * sane & valid STANDARD INQUIRY data! - * - * Allocate and initialize memory for this target. - * Save inquiry data. - * - */ -static void -mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, - struct scsi_device *sdev) -{ - dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n", - hd->ioc->name, vtarget->bus_id, vtarget->target_id, - sdev->lun, hd)); - - /* Is LUN supported? If so, upper 2 bits will be 0 - * in first byte of inquiry data. - */ - if (sdev->inq_periph_qual != 0) - return; - - if (vtarget == NULL) - return; - - vtarget->type = sdev->type; - - if (hd->ioc->bus_type != SPI) - return; - - if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) { - /* Treat all Processors as SAF-TE if - * command line option is set */ - vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; - mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); - }else if ((sdev->type == TYPE_PROCESSOR) && - !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) { - if (sdev->inquiry_len > 49 ) { - if (sdev->inquiry[44] == 'S' && - sdev->inquiry[45] == 'A' && - sdev->inquiry[46] == 'F' && - sdev->inquiry[47] == '-' && - sdev->inquiry[48] == 'T' && - sdev->inquiry[49] == 'E' ) { - vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; - mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); - } - } - } - mptscsih_setTargetNegoParms(hd, vtarget, sdev); -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Update the target negotiation parameters based on the - * the Inquiry data, adapter capabilities, and NVRAM settings. - * - */ -static void -mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, - struct scsi_device *sdev) -{ - SpiCfgData *pspi_data = &hd->ioc->spi_data; - int id = (int) target->target_id; - int nvram; - u8 width = MPT_NARROW; - u8 factor = MPT_ASYNC; - u8 offset = 0; - u8 nfactor; - u8 noQas = 1; - - target->negoFlags = pspi_data->noQas; - - /* noQas == 0 => device supports QAS. */ - - if (sdev->scsi_level < SCSI_2) { - width = 0; - factor = MPT_ULTRA2; - offset = pspi_data->maxSyncOffset; - target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; - } else { - if (scsi_device_wide(sdev)) { - width = 1; - } - - if (scsi_device_sync(sdev)) { - factor = pspi_data->minSyncFactor; - if (!scsi_device_dt(sdev)) - factor = MPT_ULTRA2; - else { - if (!scsi_device_ius(sdev) && - !scsi_device_qas(sdev)) - factor = MPT_ULTRA160; - else { - factor = MPT_ULTRA320; - if (scsi_device_qas(sdev)) { - ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id)); - noQas = 0; - } - if (sdev->type == TYPE_TAPE && - scsi_device_ius(sdev)) - target->negoFlags |= MPT_TAPE_NEGO_IDP; - } - } - offset = pspi_data->maxSyncOffset; - - /* If RAID, never disable QAS - * else if non RAID, do not disable - * QAS if bit 1 is set - * bit 1 QAS support, non-raid only - * bit 0 IU support - */ - if (target->raidVolume == 1) { - noQas = 0; - } - } else { - factor = MPT_ASYNC; - offset = 0; - } - } - - if (!sdev->tagged_supported) { - target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; - } - - /* Update tflags based on NVRAM settings. (SCSI only) - */ - if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { - nvram = pspi_data->nvram[id]; - nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8; - - if (width) - width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; - - if (offset > 0) { - /* Ensure factor is set to the - * maximum of: adapter, nvram, inquiry - */ - if (nfactor) { - if (nfactor < pspi_data->minSyncFactor ) - nfactor = pspi_data->minSyncFactor; - - factor = max(factor, nfactor); - if (factor == MPT_ASYNC) - offset = 0; - } else { - offset = 0; - factor = MPT_ASYNC; - } - } else { - factor = MPT_ASYNC; - } - } - - /* Make sure data is consistent - */ - if ((!width) && (factor < MPT_ULTRA2)) { - factor = MPT_ULTRA2; - } - - /* Save the data to the target structure. - */ - target->minSyncFactor = factor; - target->maxOffset = offset; - target->maxWidth = width; - - target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO; - - /* Disable unused features. - */ - if (!width) - target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE; - - if (!offset) - target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC; - - if ( factor > MPT_ULTRA320 ) - noQas = 0; - - if (noQas && (pspi_data->noQas == 0)) { - pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS; - target->negoFlags |= MPT_TARGET_NO_NEGO_QAS; - - /* Disable QAS in a mixed configuration case - */ - - ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id)); - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * SCSI Config Page functionality ... - */ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptscsih_writeIOCPage4 - write IOC Page 4 - * @hd: Pointer to a SCSI Host Structure - * @target_id: write IOC Page4 for this ID & Bus - * - * Return: -EAGAIN if unable to obtain a Message Frame - * or 0 if success. - * - * Remark: We do not wait for a return, write pages sequentially. - */ -static int -mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus) -{ - MPT_ADAPTER *ioc = hd->ioc; - Config_t *pReq; - IOCPage4_t *IOCPage4Ptr; - MPT_FRAME_HDR *mf; - dma_addr_t dataDma; - u16 req_idx; - u32 frameOffset; - u32 flagsLength; - int ii; - - /* Get a MF for this command. - */ - if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { - dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n", - ioc->name)); - return -EAGAIN; - } - - /* Set the request and the data pointers. - * Place data at end of MF. - */ - pReq = (Config_t *)mf; - - req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); - frameOffset = ioc->req_sz - sizeof(IOCPage4_t); - - /* Complete the request frame (same for all requests). - */ - pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; - pReq->Reserved = 0; - pReq->ChainOffset = 0; - pReq->Function = MPI_FUNCTION_CONFIG; - pReq->ExtPageLength = 0; - pReq->ExtPageType = 0; - pReq->MsgFlags = 0; - for (ii=0; ii < 8; ii++) { - pReq->Reserved2[ii] = 0; - } - - IOCPage4Ptr = ioc->spi_data.pIocPg4; - dataDma = ioc->spi_data.IocPg4_dma; - ii = IOCPage4Ptr->ActiveSEP++; - IOCPage4Ptr->SEP[ii].SEPTargetID = target_id; - IOCPage4Ptr->SEP[ii].SEPBus = bus; - pReq->Header = IOCPage4Ptr->Header; - pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 )); - - /* Add a SGE to the config request. - */ - flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | - (IOCPage4Ptr->Header.PageLength + ii) * 4; - - mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); - - dinitprintk((MYIOC_s_INFO_FMT - "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n", - ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus)); - - mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); - - return 0; -} - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * Bus Scan and Domain Validation functionality ... @@ -3343,7 +3055,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; } else { pScsiReq->TargetID = io->id; - pScsiReq->Bus = io->bus; + pScsiReq->Bus = io->channel; pScsiReq->ChainOffset = 0; pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; } @@ -3356,9 +3068,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) pScsiReq->MsgFlags = mpt_msg_flags(); /* MsgContext set in mpt_get_msg_fram call */ - for (ii=0; ii < 8; ii++) - pScsiReq->LUN[ii] = 0; - pScsiReq->LUN[1] = io->lun; + int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN); if (io->flags & MPT_ICFLAG_TAGGED_CMD) pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ); @@ -3379,7 +3089,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) + (my_idx * MPT_SENSE_BUFFER_ALLOC)); ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n", - hd->ioc->name, cmd, io->bus, io->id, io->lun)); + hd->ioc->name, cmd, io->channel, io->id, io->lun)); if (dir == MPI_SCSIIO_CONTROL_READ) { mpt_add_sge((char *) &pScsiReq->SGL, @@ -3462,9 +3172,9 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice) iocmd.data_dma = -1; iocmd.size = 0; iocmd.rsvd = iocmd.rsvd2 = 0; - iocmd.bus = vdevice->vtarget->bus_id; - iocmd.id = vdevice->vtarget->target_id; - iocmd.lun = (u8)vdevice->lun; + iocmd.channel = vdevice->vtarget->channel; + iocmd.id = vdevice->vtarget->id; + iocmd.lun = vdevice->lun; if ((vdevice->vtarget->type == TYPE_DISK) && (vdevice->configured_lun)) @@ -3480,9 +3190,6 @@ EXPORT_SYMBOL(mptscsih_resume); EXPORT_SYMBOL(mptscsih_proc_info); EXPORT_SYMBOL(mptscsih_info); EXPORT_SYMBOL(mptscsih_qcmd); -EXPORT_SYMBOL(mptscsih_target_alloc); -EXPORT_SYMBOL(mptscsih_slave_alloc); -EXPORT_SYMBOL(mptscsih_target_destroy); EXPORT_SYMBOL(mptscsih_slave_destroy); EXPORT_SYMBOL(mptscsih_slave_configure); EXPORT_SYMBOL(mptscsih_abort); diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 187c8af0890b3e6590b61aa9783d0b3238fd2ad9..843c01a6aa0ecc817571629e49dd7bf28ec21ce6 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -6,7 +6,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2007 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -53,6 +53,24 @@ * SCSI Public stuff... */ +#define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */ +#define MPT_SCANDV_DID_RESET (0x00000001) +#define MPT_SCANDV_SENSE (0x00000002) +#define MPT_SCANDV_SOME_ERROR (0x00000004) +#define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008) +#define MPT_SCANDV_ISSUE_SENSE (0x00000010) +#define MPT_SCANDV_FALLBACK (0x00000020) + +#define MPT_SCANDV_MAX_RETRIES (10) + +#define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */ +#define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */ +#define MPT_ICFLAG_EBOS 0x04 /* ReadBuffer Echo buffer has EBOS */ +#define MPT_ICFLAG_PHYS_DISK 0x08 /* Any SCSI IO but do Phys Disk Format */ +#define MPT_ICFLAG_TAGGED_CMD 0x10 /* Do tagged IO */ +#define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */ +#define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */ + #define MPT_SCSI_CMD_PER_DEV_HIGH 64 #define MPT_SCSI_CMD_PER_DEV_LOW 32 @@ -69,9 +87,22 @@ #define MPTSCSIH_SAF_TE 0 #define MPTSCSIH_PT_CLEAR 0 - #endif +typedef struct _internal_cmd { + char *data; /* data pointer */ + dma_addr_t data_dma; /* data dma address */ + int size; /* transfer size */ + u8 cmd; /* SCSI Op Code */ + u8 channel; /* bus number */ + u8 id; /* SCSI ID (virtual) */ + int lun; + u8 flags; /* Bit Field - See above */ + u8 physDiskNum; /* Phys disk number, -1 else */ + u8 rsvd2; + u8 rsvd; +} INTERNAL_CMD; + extern void mptscsih_remove(struct pci_dev *); extern void mptscsih_shutdown(struct pci_dev *); #ifdef CONFIG_PM @@ -81,9 +112,6 @@ extern int mptscsih_resume(struct pci_dev *pdev); extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func); extern const char * mptscsih_info(struct Scsi_Host *SChost); extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)); -extern int mptscsih_target_alloc(struct scsi_target *starget); -extern int mptscsih_slave_alloc(struct scsi_device *device); -extern void mptscsih_target_destroy(struct scsi_target *starget); extern void mptscsih_slave_destroy(struct scsi_device *device); extern int mptscsih_slave_configure(struct scsi_device *device); extern int mptscsih_abort(struct scsi_cmnd * SCpnt); @@ -98,6 +126,6 @@ extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pE extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); extern void mptscsih_timer_expired(unsigned long data); -extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); -extern int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid); -extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); +extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout); +extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id); +extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id); diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 203c661d2c79c782324b849fa57589289da95e09..c31a9e3c8a26c91bb6ca48e0db622212bc173eff 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -4,7 +4,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2007 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -65,6 +65,7 @@ #include #include #include +#include #include "mptbase.h" #include "mptscsih.h" @@ -95,25 +96,339 @@ static int mptspiDoneCtx = -1; static int mptspiTaskCtx = -1; static int mptspiInternalCtx = -1; /* Used only for internal commands */ +/** + * mptspi_setTargetNegoParms - Update the target negotiation + * parameters based on the the Inquiry data, adapter capabilities, + * and NVRAM settings + * + * @hd: Pointer to a SCSI Host Structure + * @vtarget: per target private data + * @sdev: SCSI device + * + **/ +static void +mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, + struct scsi_device *sdev) +{ + SpiCfgData *pspi_data = &hd->ioc->spi_data; + int id = (int) target->id; + int nvram; + u8 width = MPT_NARROW; + u8 factor = MPT_ASYNC; + u8 offset = 0; + u8 nfactor; + u8 noQas = 1; + + target->negoFlags = pspi_data->noQas; + + if (sdev->scsi_level < SCSI_2) { + width = 0; + factor = MPT_ULTRA2; + offset = pspi_data->maxSyncOffset; + target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; + } else { + if (scsi_device_wide(sdev)) + width = 1; + + if (scsi_device_sync(sdev)) { + factor = pspi_data->minSyncFactor; + if (!scsi_device_dt(sdev)) + factor = MPT_ULTRA2; + else { + if (!scsi_device_ius(sdev) && + !scsi_device_qas(sdev)) + factor = MPT_ULTRA160; + else { + factor = MPT_ULTRA320; + if (scsi_device_qas(sdev)) { + ddvprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id)); + noQas = 0; + } + if (sdev->type == TYPE_TAPE && + scsi_device_ius(sdev)) + target->negoFlags |= MPT_TAPE_NEGO_IDP; + } + } + offset = pspi_data->maxSyncOffset; + + /* If RAID, never disable QAS + * else if non RAID, do not disable + * QAS if bit 1 is set + * bit 1 QAS support, non-raid only + * bit 0 IU support + */ + if (target->raidVolume == 1) + noQas = 0; + } else { + factor = MPT_ASYNC; + offset = 0; + } + } + + if (!sdev->tagged_supported) + target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; + + /* Update tflags based on NVRAM settings. (SCSI only) + */ + if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { + nvram = pspi_data->nvram[id]; + nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8; + + if (width) + width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; + + if (offset > 0) { + /* Ensure factor is set to the + * maximum of: adapter, nvram, inquiry + */ + if (nfactor) { + if (nfactor < pspi_data->minSyncFactor ) + nfactor = pspi_data->minSyncFactor; + + factor = max(factor, nfactor); + if (factor == MPT_ASYNC) + offset = 0; + } else { + offset = 0; + factor = MPT_ASYNC; + } + } else { + factor = MPT_ASYNC; + } + } + + /* Make sure data is consistent + */ + if ((!width) && (factor < MPT_ULTRA2)) + factor = MPT_ULTRA2; + + /* Save the data to the target structure. + */ + target->minSyncFactor = factor; + target->maxOffset = offset; + target->maxWidth = width; + + target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO; + + /* Disable unused features. + */ + if (!width) + target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE; + + if (!offset) + target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC; + + if ( factor > MPT_ULTRA320 ) + noQas = 0; + + if (noQas && (pspi_data->noQas == 0)) { + pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS; + target->negoFlags |= MPT_TARGET_NO_NEGO_QAS; + + /* Disable QAS in a mixed configuration case + */ + + ddvprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id)); + } +} + +/** + * mptspi_writeIOCPage4 - write IOC Page 4 + * @hd: Pointer to a SCSI Host Structure + * @channel: + * @id: write IOC Page4 for this ID & Bus + * + * Return: -EAGAIN if unable to obtain a Message Frame + * or 0 if success. + * + * Remark: We do not wait for a return, write pages sequentially. + **/ +static int +mptspi_writeIOCPage4(MPT_SCSI_HOST *hd, u8 channel , u8 id) +{ + MPT_ADAPTER *ioc = hd->ioc; + Config_t *pReq; + IOCPage4_t *IOCPage4Ptr; + MPT_FRAME_HDR *mf; + dma_addr_t dataDma; + u16 req_idx; + u32 frameOffset; + u32 flagsLength; + int ii; + + /* Get a MF for this command. + */ + if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { + dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n", + ioc->name)); + return -EAGAIN; + } + + /* Set the request and the data pointers. + * Place data at end of MF. + */ + pReq = (Config_t *)mf; + + req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); + frameOffset = ioc->req_sz - sizeof(IOCPage4_t); + + /* Complete the request frame (same for all requests). + */ + pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; + pReq->Reserved = 0; + pReq->ChainOffset = 0; + pReq->Function = MPI_FUNCTION_CONFIG; + pReq->ExtPageLength = 0; + pReq->ExtPageType = 0; + pReq->MsgFlags = 0; + for (ii=0; ii < 8; ii++) { + pReq->Reserved2[ii] = 0; + } + + IOCPage4Ptr = ioc->spi_data.pIocPg4; + dataDma = ioc->spi_data.IocPg4_dma; + ii = IOCPage4Ptr->ActiveSEP++; + IOCPage4Ptr->SEP[ii].SEPTargetID = id; + IOCPage4Ptr->SEP[ii].SEPBus = channel; + pReq->Header = IOCPage4Ptr->Header; + pReq->PageAddress = cpu_to_le32(id | (channel << 8 )); + + /* Add a SGE to the config request. + */ + flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | + (IOCPage4Ptr->Header.PageLength + ii) * 4; + + mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); + + ddvprintk((MYIOC_s_INFO_FMT + "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n", + ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, channel)); + + mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); + + return 0; +} + +/** + * mptspi_initTarget - Target, LUN alloc/free functionality. + * @hd: Pointer to MPT_SCSI_HOST structure + * @vtarget: per target private data + * @sdev: SCSI device + * + * NOTE: It's only SAFE to call this routine if data points to + * sane & valid STANDARD INQUIRY data! + * + * Allocate and initialize memory for this target. + * Save inquiry data. + * + **/ +static void +mptspi_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, + struct scsi_device *sdev) +{ + + /* Is LUN supported? If so, upper 2 bits will be 0 + * in first byte of inquiry data. + */ + if (sdev->inq_periph_qual != 0) + return; + + if (vtarget == NULL) + return; + + vtarget->type = sdev->type; + + if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) { + /* Treat all Processors as SAF-TE if + * command line option is set */ + vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; + mptspi_writeIOCPage4(hd, vtarget->channel, vtarget->id); + }else if ((sdev->type == TYPE_PROCESSOR) && + !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) { + if (sdev->inquiry_len > 49 ) { + if (sdev->inquiry[44] == 'S' && + sdev->inquiry[45] == 'A' && + sdev->inquiry[46] == 'F' && + sdev->inquiry[47] == '-' && + sdev->inquiry[48] == 'T' && + sdev->inquiry[49] == 'E' ) { + vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; + mptspi_writeIOCPage4(hd, vtarget->channel, vtarget->id); + } + } + } + mptspi_setTargetNegoParms(hd, vtarget, sdev); +} + +/** + * mptspi_is_raid - Determines whether target is belonging to volume + * @hd: Pointer to a SCSI HOST structure + * @id: target device id + * + * Return: + * non-zero = true + * zero = false + * + */ +static int +mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id) +{ + int i, rc = 0; + + if (!hd->ioc->raid_data.pIocPg2) + goto out; + + if (!hd->ioc->raid_data.pIocPg2->NumActiveVolumes) + goto out; + for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { + if (hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) { + rc = 1; + goto out; + } + } + + out: + return rc; +} + static int mptspi_target_alloc(struct scsi_target *starget) { struct Scsi_Host *shost = dev_to_shost(&starget->dev); struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; - int ret; + VirtTarget *vtarget; if (hd == NULL) return -ENODEV; - ret = mptscsih_target_alloc(starget); - if (ret) - return ret; + vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL); + if (!vtarget) + return -ENOMEM; + + vtarget->ioc_id = hd->ioc->id; + vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; + vtarget->id = (u8)starget->id; + vtarget->channel = (u8)starget->channel; + vtarget->starget = starget; + starget->hostdata = vtarget; + + if (starget->channel == 1) { + if (mptscsih_is_phys_disk(hd->ioc, 0, starget->id) == 0) + return 0; + vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; + /* The real channel for this device is zero */ + vtarget->channel = 0; + /* The actual physdisknum (for RAID passthrough) */ + vtarget->id = mptscsih_raid_id_to_num(hd->ioc, 0, + starget->id); + } - /* if we're a device on virtual channel 1 and we're not part - * of an array, just return here (otherwise the setup below - * may actually affect a real physical device on channel 0 */ - if (starget->channel == 1 && - mptscsih_raid_id_to_num(hd, starget->id) < 0) - return 0; + if (starget->channel == 0 && + mptspi_is_raid(hd, starget->id)) { + vtarget->raidVolume = 1; + ddvprintk((KERN_INFO + "RAID Volume @ channel=%d id=%d\n", starget->channel, + starget->id)); + } if (hd->ioc->spi_data.nvram && hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) { @@ -132,6 +447,64 @@ static int mptspi_target_alloc(struct scsi_target *starget) return 0; } +void +mptspi_target_destroy(struct scsi_target *starget) +{ + if (starget->hostdata) + kfree(starget->hostdata); + starget->hostdata = NULL; +} + +/** + * mptspi_print_write_nego - negotiation parameters debug info that is being sent + * @hd: Pointer to a SCSI HOST structure + * @starget: SCSI target + * @ii: negotiation parameters + * + */ +static void +mptspi_print_write_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii) +{ + ddvprintk((MYIOC_s_INFO_FMT "id=%d Requested = 0x%08x" + " ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n", + hd->ioc->name, starget->id, ii, + ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "", + ((ii >> 8) & 0xFF), ((ii >> 16) & 0xFF), + ii & MPI_SCSIDEVPAGE0_NP_IU ? "IU ": "", + ii & MPI_SCSIDEVPAGE0_NP_DT ? "DT ": "", + ii & MPI_SCSIDEVPAGE0_NP_QAS ? "QAS ": "", + ii & MPI_SCSIDEVPAGE0_NP_HOLD_MCS ? "HOLDMCS ": "", + ii & MPI_SCSIDEVPAGE0_NP_WR_FLOW ? "WRFLOW ": "", + ii & MPI_SCSIDEVPAGE0_NP_RD_STRM ? "RDSTRM ": "", + ii & MPI_SCSIDEVPAGE0_NP_RTI ? "RTI ": "", + ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": "")); +} + +/** + * mptspi_print_read_nego - negotiation parameters debug info that is being read + * @hd: Pointer to a SCSI HOST structure + * @starget: SCSI target + * @ii: negotiation parameters + * + */ +static void +mptspi_print_read_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii) +{ + ddvprintk((MYIOC_s_INFO_FMT "id=%d Read = 0x%08x" + " ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n", + hd->ioc->name, starget->id, ii, + ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "", + ((ii >> 8) & 0xFF), ((ii >> 16) & 0xFF), + ii & MPI_SCSIDEVPAGE0_NP_IU ? "IU ": "", + ii & MPI_SCSIDEVPAGE0_NP_DT ? "DT ": "", + ii & MPI_SCSIDEVPAGE0_NP_QAS ? "QAS ": "", + ii & MPI_SCSIDEVPAGE0_NP_HOLD_MCS ? "HOLDMCS ": "", + ii & MPI_SCSIDEVPAGE0_NP_WR_FLOW ? "WRFLOW ": "", + ii & MPI_SCSIDEVPAGE0_NP_RD_STRM ? "RDSTRM ": "", + ii & MPI_SCSIDEVPAGE0_NP_RTI ? "RTI ": "", + ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": "")); +} + static int mptspi_read_spi_device_pg0(struct scsi_target *starget, struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0) { @@ -147,7 +520,7 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget, /* No SPI parameters for RAID devices */ if (starget->channel == 0 && - (hd->ioc->raid_data.isRaid & (1 << starget->id))) + mptspi_is_raid(hd, starget->id)) return -1; size = ioc->spi_data.sdp0length * 4; @@ -185,6 +558,8 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget, err = 0; memcpy(pass_pg0, pg0, size); + mptspi_print_read_nego(hd, starget, le32_to_cpu(pg0->NegotiatedParameters)); + out_free: dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma); return err; @@ -233,7 +608,7 @@ static void mptspi_read_parameters(struct scsi_target *starget) } static int -mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk) +mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id) { MpiRaidActionRequest_t *pReq; MPT_FRAME_HDR *mf; @@ -253,8 +628,8 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk) pReq->Reserved1 = 0; pReq->ChainOffset = 0; pReq->Function = MPI_FUNCTION_RAID_ACTION; - pReq->VolumeID = disk; - pReq->VolumeBus = 0; + pReq->VolumeID = id; + pReq->VolumeBus = channel; pReq->PhysDiskNum = 0; pReq->MsgFlags = 0; pReq->Reserved2 = 0; @@ -263,8 +638,8 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk) mpt_add_sge((char *)&pReq->ActionDataSGE, MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); - ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n", - hd->ioc->name, action, io->id)); + ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action=%x channel=%d id=%d\n", + hd->ioc->name, pReq->Action, channel, id)); hd->pLocal = NULL; hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */ @@ -292,12 +667,12 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, /* no DV on RAID devices */ if (sdev->channel == 0 && - (hd->ioc->raid_data.isRaid & (1 << sdev->id))) + mptspi_is_raid(hd, sdev->id)) return; /* If this is a piece of a RAID, then quiesce first */ if (sdev->channel == 1 && - mptscsih_quiesce_raid(hd, 1, vtarget->target_id) < 0) { + mptscsih_quiesce_raid(hd, 1, vtarget->channel, vtarget->id) < 0) { starget_printk(KERN_ERR, scsi_target(sdev), "Integrated RAID quiesce failed\n"); return; @@ -306,7 +681,7 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, spi_dv_device(sdev); if (sdev->channel == 1 && - mptscsih_quiesce_raid(hd, 0, vtarget->target_id) < 0) + mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0) starget_printk(KERN_ERR, scsi_target(sdev), "Integrated RAID resume failed\n"); @@ -317,54 +692,89 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, static int mptspi_slave_alloc(struct scsi_device *sdev) { - int ret; MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata; - /* gcc doesn't see that all uses of this variable occur within - * the if() statements, so stop it from whining */ - int physdisknum = 0; - - if (sdev->channel == 1) { - physdisknum = mptscsih_raid_id_to_num(hd, sdev->id); + VirtTarget *vtarget; + VirtDevice *vdev; + struct scsi_target *starget; - if (physdisknum < 0) - return physdisknum; + if (sdev->channel == 1 && + mptscsih_is_phys_disk(hd->ioc, 0, sdev->id) == 0) + return -ENXIO; + + vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); + if (!vdev) { + printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", + hd->ioc->name, sizeof(VirtDevice)); + return -ENOMEM; } - ret = mptscsih_slave_alloc(sdev); + vdev->lun = sdev->lun; + sdev->hostdata = vdev; - if (ret) - return ret; + starget = scsi_target(sdev); + vtarget = starget->hostdata; + vdev->vtarget = vtarget; + vtarget->num_luns++; - if (sdev->channel == 1) { - VirtDevice *vdev = sdev->hostdata; + if (sdev->channel == 1) sdev->no_uld_attach = 1; - vdev->vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; - /* The real channel for this device is zero */ - vdev->vtarget->bus_id = 0; - /* The actual physdisknum (for RAID passthrough) */ - vdev->vtarget->target_id = physdisknum; - } return 0; } static int mptspi_slave_configure(struct scsi_device *sdev) { - int ret = mptscsih_slave_configure(sdev); struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)sdev->host->hostdata; + VirtTarget *vtarget = scsi_target(sdev)->hostdata; + int ret = mptscsih_slave_configure(sdev); if (ret) return ret; + mptspi_initTarget(hd, vtarget, sdev); + + ddvprintk((MYIOC_s_INFO_FMT "id=%d min_period=0x%02x" + " max_offset=0x%02x max_width=%d\n", hd->ioc->name, + sdev->id, spi_min_period(scsi_target(sdev)), + spi_max_offset(scsi_target(sdev)), + spi_max_width(scsi_target(sdev)))); + if ((sdev->channel == 1 || - !(hd->ioc->raid_data.isRaid & (1 << sdev->id))) && + !(mptspi_is_raid(hd, sdev->id))) && !spi_initial_dv(sdev->sdev_target)) mptspi_dv_device(hd, sdev); return 0; } +static int +mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) +{ + struct _MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; + VirtDevice *vdev = SCpnt->device->hostdata; + + if (!vdev || !vdev->vtarget) { + SCpnt->result = DID_NO_CONNECT << 16; + done(SCpnt); + return 0; + } + + if (SCpnt->device->channel == 1 && + mptscsih_is_phys_disk(hd->ioc, 0, SCpnt->device->id) == 0) { + SCpnt->result = DID_NO_CONNECT << 16; + done(SCpnt); + return 0; + } + +#ifdef MPT_DEBUG_DV + if (spi_dv_pending(scsi_target(SCpnt->device))) + scsi_print_command(SCpnt); +#endif + + return mptscsih_qcmd(SCpnt,done); +} + static void mptspi_slave_destroy(struct scsi_device *sdev) { struct scsi_target *starget = scsi_target(sdev); @@ -392,11 +802,11 @@ static struct scsi_host_template mptspi_driver_template = { .proc_info = mptscsih_proc_info, .name = "MPT SPI Host", .info = mptscsih_info, - .queuecommand = mptscsih_qcmd, + .queuecommand = mptspi_qcmd, .target_alloc = mptspi_target_alloc, .slave_alloc = mptspi_slave_alloc, .slave_configure = mptspi_slave_configure, - .target_destroy = mptscsih_target_destroy, + .target_destroy = mptspi_target_destroy, .slave_destroy = mptspi_slave_destroy, .change_queue_depth = mptscsih_change_queue_depth, .eh_abort_handler = mptscsih_abort, @@ -427,7 +837,7 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget, /* don't allow updating nego parameters on RAID devices */ if (starget->channel == 0 && - (hd->ioc->raid_data.isRaid & (1 << starget->id))) + mptspi_is_raid(hd, starget->id)) return -1; size = ioc->spi_data.sdp1length * 4; @@ -460,6 +870,8 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget, pg1->Header.PageNumber = hdr.PageNumber; pg1->Header.PageType = hdr.PageType; + mptspi_print_write_nego(hd, starget, le32_to_cpu(pg1->RequestedParameters)); + if (mpt_config(ioc, &cfg)) { starget_printk(KERN_ERR, starget, "mpt_config failed\n"); goto out_free; @@ -672,9 +1084,9 @@ static void mpt_work_wrapper(struct work_struct *work) if (sdev->channel != 1) continue; - /* The target_id is the raid PhysDiskNum, even if + /* The id is the raid PhysDiskNum, even if * starget->id is the actual target address */ - if(vtarget->target_id != disk) + if(vtarget->id != disk) continue; starget_printk(KERN_INFO, vtarget->starget, @@ -727,7 +1139,7 @@ mptspi_deny_binding(struct scsi_target *starget) { struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata; - return ((hd->ioc->raid_data.isRaid & (1 << starget->id)) && + return ((mptspi_is_raid(hd, starget->id)) && starget->channel == 0) ? 1 : 0; } @@ -945,14 +1357,13 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) * max_lun = 1 + actual last lun, * see hosts.h :o( */ - sh->max_id = MPT_MAX_SCSI_DEVICES; + sh->max_id = ioc->devices_per_bus; sh->max_lun = MPT_LAST_LUN + 1; /* * If RAID Firmware Detected, setup virtual channel */ - if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) - > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) + if (ioc->ir_firmware) sh->max_channel = 1; else sh->max_channel = 0; @@ -1009,20 +1420,6 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", ioc->name, hd->ScsiLookup)); - /* Allocate memory for the device structures. - * A non-Null pointer at an offset - * indicates a device exists. - * max_id = 1 + maximum id (hosts.h) - */ - hd->Targets = kcalloc(sh->max_id * (sh->max_channel + 1), - sizeof(void *), GFP_ATOMIC); - if (!hd->Targets) { - error = -ENOMEM; - goto out_mptspi_probe; - } - - dprintk((KERN_INFO " vdev @ %p\n", hd->Targets)); - /* Clear the TM flags */ hd->tmPending = 0; diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 88642dec080c086e36023dcd6ffc877032d3e63e..421da1e7c0ead283aaf6046ef108e981017c6887 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -838,32 +838,28 @@ zfcp_erp_action_exists(struct zfcp_erp_action *erp_action) * and does appropriate preparations (dismiss fsf request, ...) * * locks: called under erp_lock (disabled interrupts) - * - * returns: 0 */ -static int +static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) { - int retval = 0; - struct zfcp_fsf_req *fsf_req = NULL; struct zfcp_adapter *adapter = erp_action->adapter; if (erp_action->fsf_req) { /* take lock to ensure that request is not deleted meanwhile */ spin_lock(&adapter->req_list_lock); - if ((!zfcp_reqlist_ismember(adapter, - erp_action->fsf_req->req_id)) && - (fsf_req->erp_action == erp_action)) { + if (zfcp_reqlist_ismember(adapter, + erp_action->fsf_req->req_id)) { /* fsf_req still exists */ debug_text_event(adapter->erp_dbf, 3, "a_ca_req"); - debug_event(adapter->erp_dbf, 3, &fsf_req, + debug_event(adapter->erp_dbf, 3, &erp_action->fsf_req, sizeof (unsigned long)); /* dismiss fsf_req of timed out/dismissed erp_action */ if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED | ZFCP_STATUS_ERP_TIMEDOUT)) { debug_text_event(adapter->erp_dbf, 3, "a_ca_disreq"); - fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; + erp_action->fsf_req->status |= + ZFCP_STATUS_FSFREQ_DISMISSED; } if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { ZFCP_LOG_NORMAL("error: erp step timed out " @@ -876,11 +872,11 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) * then keep it running asynchronously and don't mess * with the association of erp_action and fsf_req. */ - if (fsf_req->status & (ZFCP_STATUS_FSFREQ_COMPLETED | + if (erp_action->fsf_req->status & + (ZFCP_STATUS_FSFREQ_COMPLETED | ZFCP_STATUS_FSFREQ_DISMISSED)) { /* forget about association between fsf_req and erp_action */ - fsf_req->erp_action = NULL; erp_action->fsf_req = NULL; } } else { @@ -894,8 +890,6 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) spin_unlock(&adapter->req_list_lock); } else debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq"); - - return retval; } /** diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index cda0cc095ad1bb9b862d7c9049a17d76dc38807b..01386ac688a27887e32cd75dfa336a2c4611f5d9 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -89,7 +89,7 @@ extern int zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **, u32, u32, struct zfcp_sg_list *); extern void zfcp_fsf_start_timer(struct zfcp_fsf_req *, unsigned long); extern void zfcp_erp_start_timer(struct zfcp_fsf_req *); -extern int zfcp_fsf_req_dismiss_all(struct zfcp_adapter *); +extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *); extern int zfcp_fsf_status_read(struct zfcp_adapter *, int); extern int zfcp_fsf_req_create(struct zfcp_adapter *, u32, int, mempool_t *, unsigned long *, struct zfcp_fsf_req **); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 4b3ae3f22e78c448c21d28318adf3726e95c8c28..ef16f7ca4bb1cf1001010cf2c41854391edc6b09 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -176,28 +176,25 @@ static void zfcp_fsf_req_dismiss(struct zfcp_adapter *adapter, /** * zfcp_fsf_req_dismiss_all - dismiss all remaining fsf requests */ -int zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) +void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) { struct zfcp_fsf_req *request, *tmp; unsigned long flags; + LIST_HEAD(remove_queue); unsigned int i, counter; spin_lock_irqsave(&adapter->req_list_lock, flags); atomic_set(&adapter->reqs_active, 0); - for (i=0; ireq_list[i])) - continue; - - counter = 0; - list_for_each_entry_safe(request, tmp, - &adapter->req_list[i], list) { - zfcp_fsf_req_dismiss(adapter, request, counter); - counter++; - } - } + for (i=0; ireq_list[i], &remove_queue); + spin_unlock_irqrestore(&adapter->req_list_lock, flags); - return 0; + counter = 0; + list_for_each_entry_safe(request, tmp, &remove_queue, list) { + zfcp_fsf_req_dismiss(adapter, request, counter); + counter++; + } } /* diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 68103e508db7077455dd437db6eae86797d63c0c..88e061d13d0bd69355e6f060b7a8b9c5e5e331fb 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -667,12 +667,30 @@ NCR_700_chip_setup(struct Scsi_Host *host) __u8 min_xferp = (hostdata->chip710 ? NCR_710_MIN_XFERP : NCR_700_MIN_XFERP); if(hostdata->chip710) { - __u8 burst_disable = hostdata->burst_disable - ? BURST_DISABLE : 0; + __u8 burst_disable = 0; + __u8 burst_length = 0; + + switch (hostdata->burst_length) { + case 1: + burst_length = BURST_LENGTH_1; + break; + case 2: + burst_length = BURST_LENGTH_2; + break; + case 4: + burst_length = BURST_LENGTH_4; + break; + case 8: + burst_length = BURST_LENGTH_8; + break; + default: + burst_disable = BURST_DISABLE; + break; + } dcntl_extra = COMPAT_700_MODE; NCR_700_writeb(dcntl_extra, host, DCNTL_REG); - NCR_700_writeb(BURST_LENGTH_8 | hostdata->dmode_extra, + NCR_700_writeb(burst_length | hostdata->dmode_extra, host, DMODE_710_REG); NCR_700_writeb(burst_disable | (hostdata->differential ? DIFF : 0), host, CTEST7_REG); diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h index f38822db4210886f8654c33bd03a3e2dd15635b9..841e1bb27d57eb54ae0142c2c64e4009fdb1cc51 100644 --- a/drivers/scsi/53c700.h +++ b/drivers/scsi/53c700.h @@ -203,7 +203,7 @@ struct NCR_700_Host_Parameters { __u32 force_le_on_be:1; #endif __u32 chip710:1; /* set if really a 710 not 700 */ - __u32 burst_disable:1; /* set to 1 to disable 710 bursting */ + __u32 burst_length:4; /* set to 0 to disable 710 bursting */ /* NOTHING BELOW HERE NEEDS ALTERING */ __u32 fast:1; /* if we can alter the SCSI bus clock diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c index 9c37943108792af5723ff0a394dee6888ea26571..93b41f45638a92411e7719c6c368bbcc7a0d86cf 100644 --- a/drivers/scsi/53c7xx.c +++ b/drivers/scsi/53c7xx.c @@ -4399,7 +4399,7 @@ abort_connected (struct Scsi_Host *host) { * account the current synchronous offset) */ - sstat = (NCR53c8x0_read8 (SSTAT2_REG); + sstat = NCR53c8x0_read8 (SSTAT2_REG); offset = OFFSET (sstat & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT; phase = sstat & SSTAT2_PHASE_MASK; @@ -5422,7 +5422,7 @@ insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) { --buffers, offset += segment->length, ++segment) #if 0 printk("scsi%d: comparing 0x%p to 0x%p\n", - cmd->device->host->host_no, saved, page_address(segment->page+segment->offset); + cmd->device->host->host_no, saved, page_address(segment->page+segment->offset)); #else ; #endif diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 3075204915c867b532509788e18668393840dd0b..e874b8944875c77cb1d41df5004fbfa5eae08e9f 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -192,7 +192,7 @@ static void BusLogic_InitializeCCBs(struct BusLogic_HostAdapter *HostAdapter, vo BusLogic_CreateInitialCCBs allocates the initial CCBs for Host Adapter. */ -static boolean __init BusLogic_CreateInitialCCBs(struct BusLogic_HostAdapter *HostAdapter) +static bool __init BusLogic_CreateInitialCCBs(struct BusLogic_HostAdapter *HostAdapter) { int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB); void *BlockPointer; @@ -238,7 +238,7 @@ static void BusLogic_DestroyCCBs(struct BusLogic_HostAdapter *HostAdapter) multiple host adapters share the same IRQ Channel. */ -static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapter, int AdditionalCCBs, boolean SuccessMessageP) +static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapter, int AdditionalCCBs, bool SuccessMessageP) { int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB); int PreviouslyAllocated = HostAdapter->AllocatedCCBs; @@ -362,10 +362,8 @@ static int BusLogic_Command(struct BusLogic_HostAdapter *HostAdapter, enum BusLo interrupt could occur if the IRQ Channel was previously enabled by another BusLogic Host Adapter or another driver sharing the same IRQ Channel. */ - if (!HostAdapter->IRQ_ChannelAcquired) { + if (!HostAdapter->IRQ_ChannelAcquired) local_irq_save(ProcessorFlags); - local_irq_disable(); - } /* Wait for the Host Adapter Ready bit to be set and the Command/Parameter Register Busy bit to be reset in the Status Register. @@ -639,9 +637,9 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd struct BusLogic_ProbeInfo *PrimaryProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount]; int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount + 1; int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0; - boolean ForceBusDeviceScanningOrder = false; - boolean ForceBusDeviceScanningOrderChecked = false; - boolean StandardAddressSeen[6]; + bool ForceBusDeviceScanningOrder = false; + bool ForceBusDeviceScanningOrderChecked = false; + bool StandardAddressSeen[6]; struct pci_dev *PCI_Device = NULL; int i; if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) @@ -1011,7 +1009,7 @@ static void __init BusLogic_InitializeProbeInfoList(struct BusLogic_HostAdapter BusLogic_Failure prints a standardized error message, and then returns false. */ -static boolean BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter, char *ErrorMessage) +static bool BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter, char *ErrorMessage) { BusLogic_AnnounceDriver(HostAdapter); if (HostAdapter->HostAdapterBusType == BusLogic_PCI_Bus) { @@ -1030,7 +1028,7 @@ static boolean BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter, char * BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter. */ -static boolean __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *HostAdapter) +static bool __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *HostAdapter) { union BusLogic_StatusRegister StatusRegister; union BusLogic_InterruptRegister InterruptRegister; @@ -1101,8 +1099,8 @@ static boolean __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *Hos SCSI Bus Reset. */ -static boolean BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter - *HostAdapter, boolean HardReset) +static bool BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter + *HostAdapter, bool HardReset) { union BusLogic_StatusRegister StatusRegister; int TimeoutCounter; @@ -1205,11 +1203,11 @@ static boolean BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter Host Adapter. */ -static boolean __init BusLogic_CheckHostAdapter(struct BusLogic_HostAdapter *HostAdapter) +static bool __init BusLogic_CheckHostAdapter(struct BusLogic_HostAdapter *HostAdapter) { struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation; unsigned char RequestedReplyLength; - boolean Result = true; + bool Result = true; /* FlashPoint Host Adapters do not require this protection. */ @@ -1239,7 +1237,7 @@ static boolean __init BusLogic_CheckHostAdapter(struct BusLogic_HostAdapter *Hos from Host Adapter and initializes the Host Adapter structure. */ -static boolean __init BusLogic_ReadHostAdapterConfiguration(struct BusLogic_HostAdapter +static bool __init BusLogic_ReadHostAdapterConfiguration(struct BusLogic_HostAdapter *HostAdapter) { struct BusLogic_BoardID BoardID; @@ -1686,14 +1684,14 @@ static boolean __init BusLogic_ReadHostAdapterConfiguration(struct BusLogic_Host Host Adapter. */ -static boolean __init BusLogic_ReportHostAdapterConfiguration(struct BusLogic_HostAdapter +static bool __init BusLogic_ReportHostAdapterConfiguration(struct BusLogic_HostAdapter *HostAdapter) { unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1; unsigned short SynchronousPermitted, FastPermitted; unsigned short UltraPermitted, WidePermitted; unsigned short DisconnectPermitted, TaggedQueuingPermitted; - boolean CommonSynchronousNegotiation, CommonTaggedQueueDepth; + bool CommonSynchronousNegotiation, CommonTaggedQueueDepth; char SynchronousString[BusLogic_MaxTargetDevices + 1]; char WideString[BusLogic_MaxTargetDevices + 1]; char DisconnectString[BusLogic_MaxTargetDevices + 1]; @@ -1835,7 +1833,7 @@ static boolean __init BusLogic_ReportHostAdapterConfiguration(struct BusLogic_Ho Host Adapter. */ -static boolean __init BusLogic_AcquireResources(struct BusLogic_HostAdapter *HostAdapter) +static bool __init BusLogic_AcquireResources(struct BusLogic_HostAdapter *HostAdapter) { if (HostAdapter->IRQ_Channel == 0) { BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n", HostAdapter); @@ -1903,7 +1901,7 @@ static void BusLogic_ReleaseResources(struct BusLogic_HostAdapter *HostAdapter) of the Host Adapter from its initial power on or hard reset state. */ -static boolean BusLogic_InitializeHostAdapter(struct BusLogic_HostAdapter +static bool BusLogic_InitializeHostAdapter(struct BusLogic_HostAdapter *HostAdapter) { struct BusLogic_ExtendedMailboxRequest ExtendedMailboxRequest; @@ -2002,7 +2000,7 @@ static boolean BusLogic_InitializeHostAdapter(struct BusLogic_HostAdapter through Host Adapter. */ -static boolean __init BusLogic_TargetDeviceInquiry(struct BusLogic_HostAdapter +static bool __init BusLogic_TargetDeviceInquiry(struct BusLogic_HostAdapter *HostAdapter) { u16 InstalledDevices; @@ -2739,7 +2737,7 @@ static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel, void *DeviceIdenti already have been acquired by the caller. */ -static boolean BusLogic_WriteOutgoingMailbox(struct BusLogic_HostAdapter +static bool BusLogic_WriteOutgoingMailbox(struct BusLogic_HostAdapter *HostAdapter, enum BusLogic_ActionCode ActionCode, struct BusLogic_CCB *CCB) { struct BusLogic_OutgoingMailbox *NextOutgoingMailbox; @@ -3058,7 +3056,7 @@ static int BusLogic_AbortCommand(struct scsi_cmnd *Command) currently executing SCSI Commands as having been Reset. */ -static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, boolean HardReset) +static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, bool HardReset) { struct BusLogic_CCB *CCB; int TargetID; @@ -3309,7 +3307,7 @@ Target Requested Completed Requested Completed Requested Completed\n\ static void BusLogic_Message(enum BusLogic_MessageLevel MessageLevel, char *Format, struct BusLogic_HostAdapter *HostAdapter, ...) { static char Buffer[BusLogic_LineBufferSize]; - static boolean BeginningOfLine = true; + static bool BeginningOfLine = true; va_list Arguments; int Length = 0; va_start(Arguments, HostAdapter); @@ -3347,7 +3345,7 @@ static void BusLogic_Message(enum BusLogic_MessageLevel MessageLevel, char *Form and updates the pointer if the keyword is recognized and false otherwise. */ -static boolean __init BusLogic_ParseKeyword(char **StringPointer, char *Keyword) +static bool __init BusLogic_ParseKeyword(char **StringPointer, char *Keyword) { char *Pointer = *StringPointer; while (*Keyword != '\0') { diff --git a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h index cca6d45eee4da90a13e6b8dba1210f4fcf38accc..bfbfb5c3a8f65281a42db90626925ce94da92f4f 100644 --- a/drivers/scsi/BusLogic.h +++ b/drivers/scsi/BusLogic.h @@ -233,12 +233,6 @@ enum BusLogic_BIOS_DiskGeometryTranslation { } PACKED; -/* - Define a Boolean data type. -*/ - -typedef bool boolean; - /* Define a 10^18 Statistics Byte Counter data type. */ @@ -269,19 +263,19 @@ struct BusLogic_ProbeInfo { */ struct BusLogic_ProbeOptions { - boolean NoProbe:1; /* Bit 0 */ - boolean NoProbeISA:1; /* Bit 1 */ - boolean NoProbePCI:1; /* Bit 2 */ - boolean NoSortPCI:1; /* Bit 3 */ - boolean MultiMasterFirst:1; /* Bit 4 */ - boolean FlashPointFirst:1; /* Bit 5 */ - boolean LimitedProbeISA:1; /* Bit 6 */ - boolean Probe330:1; /* Bit 7 */ - boolean Probe334:1; /* Bit 8 */ - boolean Probe230:1; /* Bit 9 */ - boolean Probe234:1; /* Bit 10 */ - boolean Probe130:1; /* Bit 11 */ - boolean Probe134:1; /* Bit 12 */ + bool NoProbe:1; /* Bit 0 */ + bool NoProbeISA:1; /* Bit 1 */ + bool NoProbePCI:1; /* Bit 2 */ + bool NoSortPCI:1; /* Bit 3 */ + bool MultiMasterFirst:1;/* Bit 4 */ + bool FlashPointFirst:1; /* Bit 5 */ + bool LimitedProbeISA:1; /* Bit 6 */ + bool Probe330:1; /* Bit 7 */ + bool Probe334:1; /* Bit 8 */ + bool Probe230:1; /* Bit 9 */ + bool Probe234:1; /* Bit 10 */ + bool Probe130:1; /* Bit 11 */ + bool Probe134:1; /* Bit 12 */ }; /* @@ -289,10 +283,10 @@ struct BusLogic_ProbeOptions { */ struct BusLogic_GlobalOptions { - boolean TraceProbe:1; /* Bit 0 */ - boolean TraceHardwareReset:1; /* Bit 1 */ - boolean TraceConfiguration:1; /* Bit 2 */ - boolean TraceErrors:1; /* Bit 3 */ + bool TraceProbe:1; /* Bit 0 */ + bool TraceHardwareReset:1; /* Bit 1 */ + bool TraceConfiguration:1; /* Bit 2 */ + bool TraceErrors:1; /* Bit 3 */ }; /* @@ -300,7 +294,7 @@ struct BusLogic_GlobalOptions { */ struct BusLogic_LocalOptions { - boolean InhibitTargetInquiry:1; /* Bit 0 */ + bool InhibitTargetInquiry:1; /* Bit 0 */ }; /* @@ -322,10 +316,10 @@ union BusLogic_ControlRegister { unsigned char All; struct { unsigned char:4; /* Bits 0-3 */ - boolean SCSIBusReset:1; /* Bit 4 */ - boolean InterruptReset:1; /* Bit 5 */ - boolean SoftReset:1; /* Bit 6 */ - boolean HardReset:1; /* Bit 7 */ + bool SCSIBusReset:1; /* Bit 4 */ + bool InterruptReset:1; /* Bit 5 */ + bool SoftReset:1; /* Bit 6 */ + bool HardReset:1; /* Bit 7 */ } cr; }; @@ -336,14 +330,14 @@ union BusLogic_ControlRegister { union BusLogic_StatusRegister { unsigned char All; struct { - boolean CommandInvalid:1; /* Bit 0 */ - boolean Reserved:1; /* Bit 1 */ - boolean DataInRegisterReady:1; /* Bit 2 */ - boolean CommandParameterRegisterBusy:1; /* Bit 3 */ - boolean HostAdapterReady:1; /* Bit 4 */ - boolean InitializationRequired:1; /* Bit 5 */ - boolean DiagnosticFailure:1; /* Bit 6 */ - boolean DiagnosticActive:1; /* Bit 7 */ + bool CommandInvalid:1; /* Bit 0 */ + bool Reserved:1; /* Bit 1 */ + bool DataInRegisterReady:1; /* Bit 2 */ + bool CommandParameterRegisterBusy:1; /* Bit 3 */ + bool HostAdapterReady:1; /* Bit 4 */ + bool InitializationRequired:1; /* Bit 5 */ + bool DiagnosticFailure:1; /* Bit 6 */ + bool DiagnosticActive:1; /* Bit 7 */ } sr; }; @@ -354,12 +348,12 @@ union BusLogic_StatusRegister { union BusLogic_InterruptRegister { unsigned char All; struct { - boolean IncomingMailboxLoaded:1; /* Bit 0 */ - boolean OutgoingMailboxAvailable:1; /* Bit 1 */ - boolean CommandComplete:1; /* Bit 2 */ - boolean ExternalBusReset:1; /* Bit 3 */ + bool IncomingMailboxLoaded:1; /* Bit 0 */ + bool OutgoingMailboxAvailable:1;/* Bit 1 */ + bool CommandComplete:1; /* Bit 2 */ + bool ExternalBusReset:1; /* Bit 3 */ unsigned char Reserved:3; /* Bits 4-6 */ - boolean InterruptValid:1; /* Bit 7 */ + bool InterruptValid:1; /* Bit 7 */ } ir; }; @@ -373,7 +367,7 @@ union BusLogic_GeometryRegister { enum BusLogic_BIOS_DiskGeometryTranslation Drive0Geometry:2; /* Bits 0-1 */ enum BusLogic_BIOS_DiskGeometryTranslation Drive1Geometry:2; /* Bits 2-3 */ unsigned char:3; /* Bits 4-6 */ - boolean ExtendedTranslationEnabled:1; /* Bit 7 */ + bool ExtendedTranslationEnabled:1; /* Bit 7 */ } gr; }; @@ -445,16 +439,16 @@ struct BusLogic_BoardID { struct BusLogic_Configuration { unsigned char:5; /* Byte 0 Bits 0-4 */ - boolean DMA_Channel5:1; /* Byte 0 Bit 5 */ - boolean DMA_Channel6:1; /* Byte 0 Bit 6 */ - boolean DMA_Channel7:1; /* Byte 0 Bit 7 */ - boolean IRQ_Channel9:1; /* Byte 1 Bit 0 */ - boolean IRQ_Channel10:1; /* Byte 1 Bit 1 */ - boolean IRQ_Channel11:1; /* Byte 1 Bit 2 */ - boolean IRQ_Channel12:1; /* Byte 1 Bit 3 */ + bool DMA_Channel5:1; /* Byte 0 Bit 5 */ + bool DMA_Channel6:1; /* Byte 0 Bit 6 */ + bool DMA_Channel7:1; /* Byte 0 Bit 7 */ + bool IRQ_Channel9:1; /* Byte 1 Bit 0 */ + bool IRQ_Channel10:1; /* Byte 1 Bit 1 */ + bool IRQ_Channel11:1; /* Byte 1 Bit 2 */ + bool IRQ_Channel12:1; /* Byte 1 Bit 3 */ unsigned char:1; /* Byte 1 Bit 4 */ - boolean IRQ_Channel14:1; /* Byte 1 Bit 5 */ - boolean IRQ_Channel15:1; /* Byte 1 Bit 6 */ + bool IRQ_Channel14:1; /* Byte 1 Bit 5 */ + bool IRQ_Channel15:1; /* Byte 1 Bit 6 */ unsigned char:1; /* Byte 1 Bit 7 */ unsigned char HostAdapterID:4; /* Byte 2 Bits 0-3 */ unsigned char:4; /* Byte 2 Bits 4-7 */ @@ -467,12 +461,12 @@ struct BusLogic_Configuration { struct BusLogic_SynchronousValue { unsigned char Offset:4; /* Bits 0-3 */ unsigned char TransferPeriod:3; /* Bits 4-6 */ - boolean Synchronous:1; /* Bit 7 */ + bool Synchronous:1; /* Bit 7 */ }; struct BusLogic_SetupInformation { - boolean SynchronousInitiationEnabled:1; /* Byte 0 Bit 0 */ - boolean ParityCheckingEnabled:1; /* Byte 0 Bit 1 */ + bool SynchronousInitiationEnabled:1; /* Byte 0 Bit 0 */ + bool ParityCheckingEnabled:1; /* Byte 0 Bit 1 */ unsigned char:6; /* Byte 0 Bits 2-7 */ unsigned char BusTransferRate; /* Byte 1 */ unsigned char PreemptTimeOnBus; /* Byte 2 */ @@ -523,13 +517,13 @@ enum BusLogic_ISACompatibleIOPort { struct BusLogic_PCIHostAdapterInformation { enum BusLogic_ISACompatibleIOPort ISACompatibleIOPort; /* Byte 0 */ unsigned char PCIAssignedIRQChannel; /* Byte 1 */ - boolean LowByteTerminated:1; /* Byte 2 Bit 0 */ - boolean HighByteTerminated:1; /* Byte 2 Bit 1 */ + bool LowByteTerminated:1; /* Byte 2 Bit 0 */ + bool HighByteTerminated:1; /* Byte 2 Bit 1 */ unsigned char:2; /* Byte 2 Bits 2-3 */ - boolean JP1:1; /* Byte 2 Bit 4 */ - boolean JP2:1; /* Byte 2 Bit 5 */ - boolean JP3:1; /* Byte 2 Bit 6 */ - boolean GenericInfoValid:1; /* Byte 2 Bit 7 */ + bool JP1:1; /* Byte 2 Bit 4 */ + bool JP2:1; /* Byte 2 Bit 5 */ + bool JP3:1; /* Byte 2 Bit 6 */ + bool GenericInfoValid:1;/* Byte 2 Bit 7 */ unsigned char:8; /* Byte 3 */ }; @@ -545,17 +539,17 @@ struct BusLogic_ExtendedSetupInformation { u32 BaseMailboxAddress; /* Bytes 5-8 */ struct { unsigned char:2; /* Byte 9 Bits 0-1 */ - boolean FastOnEISA:1; /* Byte 9 Bit 2 */ + bool FastOnEISA:1; /* Byte 9 Bit 2 */ unsigned char:3; /* Byte 9 Bits 3-5 */ - boolean LevelSensitiveInterrupt:1; /* Byte 9 Bit 6 */ + bool LevelSensitiveInterrupt:1; /* Byte 9 Bit 6 */ unsigned char:1; /* Byte 9 Bit 7 */ } Misc; unsigned char FirmwareRevision[3]; /* Bytes 10-12 */ - boolean HostWideSCSI:1; /* Byte 13 Bit 0 */ - boolean HostDifferentialSCSI:1; /* Byte 13 Bit 1 */ - boolean HostSupportsSCAM:1; /* Byte 13 Bit 2 */ - boolean HostUltraSCSI:1; /* Byte 13 Bit 3 */ - boolean HostSmartTermination:1; /* Byte 13 Bit 4 */ + bool HostWideSCSI:1; /* Byte 13 Bit 0 */ + bool HostDifferentialSCSI:1; /* Byte 13 Bit 1 */ + bool HostSupportsSCAM:1; /* Byte 13 Bit 2 */ + bool HostUltraSCSI:1; /* Byte 13 Bit 3 */ + bool HostSmartTermination:1; /* Byte 13 Bit 4 */ unsigned char:3; /* Byte 13 Bits 5-7 */ } PACKED; @@ -590,35 +584,35 @@ struct BusLogic_AutoSCSIData { unsigned char InformationByteCount; /* Byte 2 */ unsigned char HostAdapterType[6]; /* Bytes 3-8 */ unsigned char:8; /* Byte 9 */ - boolean FloppyEnabled:1; /* Byte 10 Bit 0 */ - boolean FloppySecondary:1; /* Byte 10 Bit 1 */ - boolean LevelSensitiveInterrupt:1; /* Byte 10 Bit 2 */ + bool FloppyEnabled:1; /* Byte 10 Bit 0 */ + bool FloppySecondary:1; /* Byte 10 Bit 1 */ + bool LevelSensitiveInterrupt:1; /* Byte 10 Bit 2 */ unsigned char:2; /* Byte 10 Bits 3-4 */ unsigned char SystemRAMAreaForBIOS:3; /* Byte 10 Bits 5-7 */ unsigned char DMA_Channel:7; /* Byte 11 Bits 0-6 */ - boolean DMA_AutoConfiguration:1; /* Byte 11 Bit 7 */ + bool DMA_AutoConfiguration:1; /* Byte 11 Bit 7 */ unsigned char IRQ_Channel:7; /* Byte 12 Bits 0-6 */ - boolean IRQ_AutoConfiguration:1; /* Byte 12 Bit 7 */ + bool IRQ_AutoConfiguration:1; /* Byte 12 Bit 7 */ unsigned char DMA_TransferRate; /* Byte 13 */ unsigned char SCSI_ID; /* Byte 14 */ - boolean LowByteTerminated:1; /* Byte 15 Bit 0 */ - boolean ParityCheckingEnabled:1; /* Byte 15 Bit 1 */ - boolean HighByteTerminated:1; /* Byte 15 Bit 2 */ - boolean NoisyCablingEnvironment:1; /* Byte 15 Bit 3 */ - boolean FastSynchronousNegotiation:1; /* Byte 15 Bit 4 */ - boolean BusResetEnabled:1; /* Byte 15 Bit 5 */ - boolean:1; /* Byte 15 Bit 6 */ - boolean ActiveNegationEnabled:1; /* Byte 15 Bit 7 */ + bool LowByteTerminated:1; /* Byte 15 Bit 0 */ + bool ParityCheckingEnabled:1; /* Byte 15 Bit 1 */ + bool HighByteTerminated:1; /* Byte 15 Bit 2 */ + bool NoisyCablingEnvironment:1; /* Byte 15 Bit 3 */ + bool FastSynchronousNegotiation:1; /* Byte 15 Bit 4 */ + bool BusResetEnabled:1; /* Byte 15 Bit 5 */ + bool:1; /* Byte 15 Bit 6 */ + bool ActiveNegationEnabled:1; /* Byte 15 Bit 7 */ unsigned char BusOnDelay; /* Byte 16 */ unsigned char BusOffDelay; /* Byte 17 */ - boolean HostAdapterBIOSEnabled:1; /* Byte 18 Bit 0 */ - boolean BIOSRedirectionOfINT19Enabled:1; /* Byte 18 Bit 1 */ - boolean ExtendedTranslationEnabled:1; /* Byte 18 Bit 2 */ - boolean MapRemovableAsFixedEnabled:1; /* Byte 18 Bit 3 */ - boolean:1; /* Byte 18 Bit 4 */ - boolean BIOSSupportsMoreThan2DrivesEnabled:1; /* Byte 18 Bit 5 */ - boolean BIOSInterruptModeEnabled:1; /* Byte 18 Bit 6 */ - boolean FlopticalSupportEnabled:1; /* Byte 19 Bit 7 */ + bool HostAdapterBIOSEnabled:1; /* Byte 18 Bit 0 */ + bool BIOSRedirectionOfINT19Enabled:1; /* Byte 18 Bit 1 */ + bool ExtendedTranslationEnabled:1; /* Byte 18 Bit 2 */ + bool MapRemovableAsFixedEnabled:1; /* Byte 18 Bit 3 */ + bool:1; /* Byte 18 Bit 4 */ + bool BIOSSupportsMoreThan2DrivesEnabled:1; /* Byte 18 Bit 5 */ + bool BIOSInterruptModeEnabled:1; /* Byte 18 Bit 6 */ + bool FlopticalSupportEnabled:1; /* Byte 19 Bit 7 */ unsigned short DeviceEnabled; /* Bytes 19-20 */ unsigned short WidePermitted; /* Bytes 21-22 */ unsigned short FastPermitted; /* Bytes 23-24 */ @@ -628,22 +622,22 @@ struct BusLogic_AutoSCSIData { unsigned short IgnoreInBIOSScan; /* Bytes 31-32 */ unsigned char PCIInterruptPin:2; /* Byte 33 Bits 0-1 */ unsigned char HostAdapterIOPortAddress:2; /* Byte 33 Bits 2-3 */ - boolean StrictRoundRobinModeEnabled:1; /* Byte 33 Bit 4 */ - boolean VESABusSpeedGreaterThan33MHz:1; /* Byte 33 Bit 5 */ - boolean VESABurstWriteEnabled:1; /* Byte 33 Bit 6 */ - boolean VESABurstReadEnabled:1; /* Byte 33 Bit 7 */ + bool StrictRoundRobinModeEnabled:1; /* Byte 33 Bit 4 */ + bool VESABusSpeedGreaterThan33MHz:1; /* Byte 33 Bit 5 */ + bool VESABurstWriteEnabled:1; /* Byte 33 Bit 6 */ + bool VESABurstReadEnabled:1; /* Byte 33 Bit 7 */ unsigned short UltraPermitted; /* Bytes 34-35 */ unsigned int:32; /* Bytes 36-39 */ unsigned char:8; /* Byte 40 */ unsigned char AutoSCSIMaximumLUN; /* Byte 41 */ - boolean:1; /* Byte 42 Bit 0 */ - boolean SCAM_Dominant:1; /* Byte 42 Bit 1 */ - boolean SCAM_Enabled:1; /* Byte 42 Bit 2 */ - boolean SCAM_Level2:1; /* Byte 42 Bit 3 */ + bool:1; /* Byte 42 Bit 0 */ + bool SCAM_Dominant:1; /* Byte 42 Bit 1 */ + bool SCAM_Enabled:1; /* Byte 42 Bit 2 */ + bool SCAM_Level2:1; /* Byte 42 Bit 3 */ unsigned char:4; /* Byte 42 Bits 4-7 */ - boolean INT13ExtensionEnabled:1; /* Byte 43 Bit 0 */ - boolean:1; /* Byte 43 Bit 1 */ - boolean CDROMBootEnabled:1; /* Byte 43 Bit 2 */ + bool INT13ExtensionEnabled:1; /* Byte 43 Bit 0 */ + bool:1; /* Byte 43 Bit 1 */ + bool CDROMBootEnabled:1; /* Byte 43 Bit 2 */ unsigned char:5; /* Byte 43 Bits 3-7 */ unsigned char BootTargetID:4; /* Byte 44 Bits 0-3 */ unsigned char BootChannel:4; /* Byte 44 Bits 4-7 */ @@ -852,7 +846,7 @@ struct BusLogic_CCB { enum BusLogic_CCB_Opcode Opcode; /* Byte 0 */ unsigned char:3; /* Byte 1 Bits 0-2 */ enum BusLogic_DataDirection DataDirection:2; /* Byte 1 Bits 3-4 */ - boolean TagEnable:1; /* Byte 1 Bit 5 */ + bool TagEnable:1; /* Byte 1 Bit 5 */ enum BusLogic_QueueTag QueueTag:2; /* Byte 1 Bits 6-7 */ unsigned char CDB_Length; /* Byte 2 */ unsigned char SenseDataLength; /* Byte 3 */ @@ -864,7 +858,7 @@ struct BusLogic_CCB { enum BusLogic_TargetDeviceStatus TargetDeviceStatus; /* Byte 15 */ unsigned char TargetID; /* Byte 16 */ unsigned char LogicalUnit:5; /* Byte 17 Bits 0-4 */ - boolean LegacyTagEnable:1; /* Byte 17 Bit 5 */ + bool LegacyTagEnable:1; /* Byte 17 Bit 5 */ enum BusLogic_QueueTag LegacyQueueTag:2; /* Byte 17 Bits 6-7 */ SCSI_CDB_T CDB; /* Bytes 18-29 */ unsigned char:8; /* Byte 30 */ @@ -939,13 +933,13 @@ struct BusLogic_DriverOptions { */ struct BusLogic_TargetFlags { - boolean TargetExists:1; - boolean TaggedQueuingSupported:1; - boolean WideTransfersSupported:1; - boolean TaggedQueuingActive:1; - boolean WideTransfersActive:1; - boolean CommandSuccessfulFlag:1; - boolean TargetInfoReported:1; + bool TargetExists:1; + bool TaggedQueuingSupported:1; + bool WideTransfersSupported:1; + bool TaggedQueuingActive:1; + bool WideTransfersActive:1; + bool CommandSuccessfulFlag:1; + bool TargetInfoReported:1; }; /* @@ -992,7 +986,7 @@ typedef unsigned int FlashPoint_CardHandle_T; struct FlashPoint_Info { u32 BaseAddress; /* Bytes 0-3 */ - boolean Present; /* Byte 4 */ + bool Present; /* Byte 4 */ unsigned char IRQ_Channel; /* Byte 5 */ unsigned char SCSI_ID; /* Byte 6 */ unsigned char SCSI_LUN; /* Byte 7 */ @@ -1002,15 +996,15 @@ struct FlashPoint_Info { unsigned short UltraPermitted; /* Bytes 14-15 */ unsigned short DisconnectPermitted; /* Bytes 16-17 */ unsigned short WidePermitted; /* Bytes 18-19 */ - boolean ParityCheckingEnabled:1; /* Byte 20 Bit 0 */ - boolean HostWideSCSI:1; /* Byte 20 Bit 1 */ - boolean HostSoftReset:1; /* Byte 20 Bit 2 */ - boolean ExtendedTranslationEnabled:1; /* Byte 20 Bit 3 */ - boolean LowByteTerminated:1; /* Byte 20 Bit 4 */ - boolean HighByteTerminated:1; /* Byte 20 Bit 5 */ - boolean ReportDataUnderrun:1; /* Byte 20 Bit 6 */ - boolean SCAM_Enabled:1; /* Byte 20 Bit 7 */ - boolean SCAM_Level2:1; /* Byte 21 Bit 0 */ + bool ParityCheckingEnabled:1; /* Byte 20 Bit 0 */ + bool HostWideSCSI:1; /* Byte 20 Bit 1 */ + bool HostSoftReset:1; /* Byte 20 Bit 2 */ + bool ExtendedTranslationEnabled:1; /* Byte 20 Bit 3 */ + bool LowByteTerminated:1; /* Byte 20 Bit 4 */ + bool HighByteTerminated:1; /* Byte 20 Bit 5 */ + bool ReportDataUnderrun:1; /* Byte 20 Bit 6 */ + bool SCAM_Enabled:1; /* Byte 20 Bit 7 */ + bool SCAM_Level2:1; /* Byte 21 Bit 0 */ unsigned char:7; /* Byte 21 Bits 1-7 */ unsigned char Family; /* Byte 22 */ unsigned char BusType; /* Byte 23 */ @@ -1044,29 +1038,29 @@ struct BusLogic_HostAdapter { unsigned char IRQ_Channel; unsigned char DMA_Channel; unsigned char SCSI_ID; - boolean IRQ_ChannelAcquired:1; - boolean DMA_ChannelAcquired:1; - boolean ExtendedTranslationEnabled:1; - boolean ParityCheckingEnabled:1; - boolean BusResetEnabled:1; - boolean LevelSensitiveInterrupt:1; - boolean HostWideSCSI:1; - boolean HostDifferentialSCSI:1; - boolean HostSupportsSCAM:1; - boolean HostUltraSCSI:1; - boolean ExtendedLUNSupport:1; - boolean TerminationInfoValid:1; - boolean LowByteTerminated:1; - boolean HighByteTerminated:1; - boolean BounceBuffersRequired:1; - boolean StrictRoundRobinModeSupport:1; - boolean SCAM_Enabled:1; - boolean SCAM_Level2:1; - boolean HostAdapterInitialized:1; - boolean HostAdapterExternalReset:1; - boolean HostAdapterInternalError:1; - boolean ProcessCompletedCCBsActive; - volatile boolean HostAdapterCommandCompleted; + bool IRQ_ChannelAcquired:1; + bool DMA_ChannelAcquired:1; + bool ExtendedTranslationEnabled:1; + bool ParityCheckingEnabled:1; + bool BusResetEnabled:1; + bool LevelSensitiveInterrupt:1; + bool HostWideSCSI:1; + bool HostDifferentialSCSI:1; + bool HostSupportsSCAM:1; + bool HostUltraSCSI:1; + bool ExtendedLUNSupport:1; + bool TerminationInfoValid:1; + bool LowByteTerminated:1; + bool HighByteTerminated:1; + bool BounceBuffersRequired:1; + bool StrictRoundRobinModeSupport:1; + bool SCAM_Enabled:1; + bool SCAM_Level2:1; + bool HostAdapterInitialized:1; + bool HostAdapterExternalReset:1; + bool HostAdapterInternalError:1; + bool ProcessCompletedCCBsActive; + volatile bool HostAdapterCommandCompleted; unsigned short HostAdapterScatterGatherLimit; unsigned short DriverScatterGatherLimit; unsigned short MaxTargetDevices; @@ -1141,25 +1135,25 @@ struct SCSI_Inquiry { unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */ unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */ unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */ - boolean RMB:1; /* Byte 1 Bit 7 */ + bool RMB:1; /* Byte 1 Bit 7 */ unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */ unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */ unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */ unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */ unsigned char:2; /* Byte 3 Bits 4-5 */ - boolean TrmIOP:1; /* Byte 3 Bit 6 */ - boolean AENC:1; /* Byte 3 Bit 7 */ + bool TrmIOP:1; /* Byte 3 Bit 6 */ + bool AENC:1; /* Byte 3 Bit 7 */ unsigned char AdditionalLength; /* Byte 4 */ unsigned char:8; /* Byte 5 */ unsigned char:8; /* Byte 6 */ - boolean SftRe:1; /* Byte 7 Bit 0 */ - boolean CmdQue:1; /* Byte 7 Bit 1 */ - boolean:1; /* Byte 7 Bit 2 */ - boolean Linked:1; /* Byte 7 Bit 3 */ - boolean Sync:1; /* Byte 7 Bit 4 */ - boolean WBus16:1; /* Byte 7 Bit 5 */ - boolean WBus32:1; /* Byte 7 Bit 6 */ - boolean RelAdr:1; /* Byte 7 Bit 7 */ + bool SftRe:1; /* Byte 7 Bit 0 */ + bool CmdQue:1; /* Byte 7 Bit 1 */ + bool:1; /* Byte 7 Bit 2 */ + bool Linked:1; /* Byte 7 Bit 3 */ + bool Sync:1; /* Byte 7 Bit 4 */ + bool WBus16:1; /* Byte 7 Bit 5 */ + bool WBus32:1; /* Byte 7 Bit 6 */ + bool RelAdr:1; /* Byte 7 Bit 7 */ unsigned char VendorIdentification[8]; /* Bytes 8-15 */ unsigned char ProductIdentification[16]; /* Bytes 16-31 */ unsigned char ProductRevisionLevel[4]; /* Bytes 32-35 */ @@ -1348,7 +1342,7 @@ static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *, char *, char **, off_t static int BusLogic_SlaveConfigure(struct scsi_device *); static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *); static irqreturn_t BusLogic_InterruptHandler(int, void *); -static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *, boolean HardReset); +static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *, bool HardReset); static void BusLogic_Message(enum BusLogic_MessageLevel, char *, struct BusLogic_HostAdapter *, ...); static int __init BusLogic_Setup(char *); diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index 7c00680495867d0a81a2f81d379a270fb1ff846a..a7f916c0c9cdcc618476eecf3dcca083065d8d9c 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -7609,7 +7609,7 @@ FlashPoint__AbortCCB(FlashPoint_CardHandle_T CardHandle, FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB); } -static inline boolean +static inline bool FlashPoint__InterruptPending(FlashPoint_CardHandle_T CardHandle) { return FlashPoint_InterruptPending(CardHandle); @@ -7640,7 +7640,7 @@ extern FlashPoint_CardHandle_T FlashPoint_HardwareResetHostAdapter(struct FlashPoint_Info *); extern void FlashPoint_StartCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *); extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *); -extern boolean FlashPoint_InterruptPending(FlashPoint_CardHandle_T); +extern bool FlashPoint_InterruptPending(FlashPoint_CardHandle_T); extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T); extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T); diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 7869c34a4a3eed46f82c281adc238aa48e5591df..5bf3f07870ba14f86a5805e3e9f13260420ba564 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -973,6 +973,15 @@ config SCSI_LASI700 many PA-RISC workstations & servers. If you do not know whether you have a Lasi chip, it is safe to say "Y" here. +config SCSI_SNI_53C710 + tristate "SNI RM SCSI support for 53c710" + depends on SNI_RM && SCSI + select SCSI_SPI_ATTRS + select 53C700_LE_ON_BE + help + This is a driver for the onboard SCSI controller found in older + SNI RM workstations & servers. + config 53C700_LE_ON_BE bool depends on SCSI_LASI700 diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index bd7c9888f7f40ca31052e1fa62796fbb08fb9e37..79ecf4ebe6ebea59b3b662f88ae6fae2d15a526c 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -124,6 +124,7 @@ obj-$(CONFIG_JAZZ_ESP) += NCR53C9x.o jazz_esp.o obj-$(CONFIG_SUN3X_ESP) += NCR53C9x.o sun3x_esp.o obj-$(CONFIG_SCSI_FCAL) += fcal.o obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o +obj-$(CONFIG_SCSI_SNI_53C710) += 53c700.o sni_53c710.o obj-$(CONFIG_SCSI_NSP32) += nsp32.o obj-$(CONFIG_SCSI_IPR) += ipr.o obj-$(CONFIG_SCSI_SRP) += libsrp.o diff --git a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c index 9859cd17fc574ffe4d7791ab7369039f07241f14..f12864abed2f1c99cf52803a989178bee09df122 100644 --- a/drivers/scsi/NCR_D700.c +++ b/drivers/scsi/NCR_D700.c @@ -200,6 +200,7 @@ NCR_D700_probe_one(struct NCR_D700_private *p, int siop, int irq, hostdata->base = ioport_map(region, 64); hostdata->differential = (((1<clock = NCR_D700_CLOCK_MHZ; + hostdata->burst_length = 8; /* and register the siop */ host = NCR_700_detect(&NCR_D700_driver_template, hostdata, p->dev); diff --git a/drivers/scsi/aacraid/Makefile b/drivers/scsi/aacraid/Makefile index 28d133a3094f85ca11824311660561d1f488154b..f1cca4ee541006c6767b5242f124dfcefcc6d6a0 100644 --- a/drivers/scsi/aacraid/Makefile +++ b/drivers/scsi/aacraid/Makefile @@ -3,6 +3,6 @@ obj-$(CONFIG_SCSI_AACRAID) := aacraid.o aacraid-objs := linit.o aachba.o commctrl.o comminit.o commsup.o \ - dpcsup.o rx.o sa.o rkt.o + dpcsup.o rx.o sa.o rkt.o nark.o EXTRA_CFLAGS := -Idrivers/scsi diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 426cd6f49f5db6ad1ddcd01de7bbd2e7850d3b47..ddb33b06e0efffcbaf27b43b13c5102c34b1e7f2 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -170,9 +170,9 @@ int acbsize = -1; module_param(acbsize, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512, 2048, 4096 and 8192. Default is to use suggestion from Firmware."); -int expose_physicals = 0; +int expose_physicals = -1; module_param(expose_physicals, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. 0=off, 1=on"); +MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on"); /** * aac_get_config_status - check the adapter configuration * @common: adapter to query @@ -706,6 +706,309 @@ static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code, } } +static int aac_bounds_32(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba) +{ + if (lba & 0xffffffff00000000LL) { + int cid = scmd_id(cmd); + dprintk((KERN_DEBUG "aacraid: Illegal lba\n")); + cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | + SAM_STAT_CHECK_CONDITION; + set_sense((u8 *) &dev->fsa_dev[cid].sense_data, + HARDWARE_ERROR, + SENCODE_INTERNAL_TARGET_FAILURE, + ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, + 0, 0); + memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data, + (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(cmd->sense_buffer)) + ? sizeof(cmd->sense_buffer) + : sizeof(dev->fsa_dev[cid].sense_data)); + cmd->scsi_done(cmd); + return 1; + } + return 0; +} + +static int aac_bounds_64(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba) +{ + return 0; +} + +static void io_callback(void *context, struct fib * fibptr); + +static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) +{ + u16 fibsize; + struct aac_raw_io *readcmd; + aac_fib_init(fib); + readcmd = (struct aac_raw_io *) fib_data(fib); + readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff)); + readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); + readcmd->count = cpu_to_le32(count<<9); + readcmd->cid = cpu_to_le16(scmd_id(cmd)); + readcmd->flags = cpu_to_le16(1); + readcmd->bpTotal = 0; + readcmd->bpComplete = 0; + + aac_build_sgraw(cmd, &readcmd->sg); + fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw)); + BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr))); + /* + * Now send the Fib to the adapter + */ + return aac_fib_send(ContainerRawIo, + fib, + fibsize, + FsaNormal, + 0, 1, + (fib_callback) io_callback, + (void *) cmd); +} + +static int aac_read_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) +{ + u16 fibsize; + struct aac_read64 *readcmd; + aac_fib_init(fib); + readcmd = (struct aac_read64 *) fib_data(fib); + readcmd->command = cpu_to_le32(VM_CtHostRead64); + readcmd->cid = cpu_to_le16(scmd_id(cmd)); + readcmd->sector_count = cpu_to_le16(count); + readcmd->block = cpu_to_le32((u32)(lba&0xffffffff)); + readcmd->pad = 0; + readcmd->flags = 0; + + aac_build_sg64(cmd, &readcmd->sg); + fibsize = sizeof(struct aac_read64) + + ((le32_to_cpu(readcmd->sg.count) - 1) * + sizeof (struct sgentry64)); + BUG_ON (fibsize > (fib->dev->max_fib_size - + sizeof(struct aac_fibhdr))); + /* + * Now send the Fib to the adapter + */ + return aac_fib_send(ContainerCommand64, + fib, + fibsize, + FsaNormal, + 0, 1, + (fib_callback) io_callback, + (void *) cmd); +} + +static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) +{ + u16 fibsize; + struct aac_read *readcmd; + aac_fib_init(fib); + readcmd = (struct aac_read *) fib_data(fib); + readcmd->command = cpu_to_le32(VM_CtBlockRead); + readcmd->cid = cpu_to_le16(scmd_id(cmd)); + readcmd->block = cpu_to_le32((u32)(lba&0xffffffff)); + readcmd->count = cpu_to_le32(count * 512); + + aac_build_sg(cmd, &readcmd->sg); + fibsize = sizeof(struct aac_read) + + ((le32_to_cpu(readcmd->sg.count) - 1) * + sizeof (struct sgentry)); + BUG_ON (fibsize > (fib->dev->max_fib_size - + sizeof(struct aac_fibhdr))); + /* + * Now send the Fib to the adapter + */ + return aac_fib_send(ContainerCommand, + fib, + fibsize, + FsaNormal, + 0, 1, + (fib_callback) io_callback, + (void *) cmd); +} + +static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) +{ + u16 fibsize; + struct aac_raw_io *writecmd; + aac_fib_init(fib); + writecmd = (struct aac_raw_io *) fib_data(fib); + writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff)); + writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); + writecmd->count = cpu_to_le32(count<<9); + writecmd->cid = cpu_to_le16(scmd_id(cmd)); + writecmd->flags = 0; + writecmd->bpTotal = 0; + writecmd->bpComplete = 0; + + aac_build_sgraw(cmd, &writecmd->sg); + fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw)); + BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr))); + /* + * Now send the Fib to the adapter + */ + return aac_fib_send(ContainerRawIo, + fib, + fibsize, + FsaNormal, + 0, 1, + (fib_callback) io_callback, + (void *) cmd); +} + +static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) +{ + u16 fibsize; + struct aac_write64 *writecmd; + aac_fib_init(fib); + writecmd = (struct aac_write64 *) fib_data(fib); + writecmd->command = cpu_to_le32(VM_CtHostWrite64); + writecmd->cid = cpu_to_le16(scmd_id(cmd)); + writecmd->sector_count = cpu_to_le16(count); + writecmd->block = cpu_to_le32((u32)(lba&0xffffffff)); + writecmd->pad = 0; + writecmd->flags = 0; + + aac_build_sg64(cmd, &writecmd->sg); + fibsize = sizeof(struct aac_write64) + + ((le32_to_cpu(writecmd->sg.count) - 1) * + sizeof (struct sgentry64)); + BUG_ON (fibsize > (fib->dev->max_fib_size - + sizeof(struct aac_fibhdr))); + /* + * Now send the Fib to the adapter + */ + return aac_fib_send(ContainerCommand64, + fib, + fibsize, + FsaNormal, + 0, 1, + (fib_callback) io_callback, + (void *) cmd); +} + +static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) +{ + u16 fibsize; + struct aac_write *writecmd; + aac_fib_init(fib); + writecmd = (struct aac_write *) fib_data(fib); + writecmd->command = cpu_to_le32(VM_CtBlockWrite); + writecmd->cid = cpu_to_le16(scmd_id(cmd)); + writecmd->block = cpu_to_le32((u32)(lba&0xffffffff)); + writecmd->count = cpu_to_le32(count * 512); + writecmd->sg.count = cpu_to_le32(1); + /* ->stable is not used - it did mean which type of write */ + + aac_build_sg(cmd, &writecmd->sg); + fibsize = sizeof(struct aac_write) + + ((le32_to_cpu(writecmd->sg.count) - 1) * + sizeof (struct sgentry)); + BUG_ON (fibsize > (fib->dev->max_fib_size - + sizeof(struct aac_fibhdr))); + /* + * Now send the Fib to the adapter + */ + return aac_fib_send(ContainerCommand, + fib, + fibsize, + FsaNormal, + 0, 1, + (fib_callback) io_callback, + (void *) cmd); +} + +static struct aac_srb * aac_scsi_common(struct fib * fib, struct scsi_cmnd * cmd) +{ + struct aac_srb * srbcmd; + u32 flag; + u32 timeout; + + aac_fib_init(fib); + switch(cmd->sc_data_direction){ + case DMA_TO_DEVICE: + flag = SRB_DataOut; + break; + case DMA_BIDIRECTIONAL: + flag = SRB_DataIn | SRB_DataOut; + break; + case DMA_FROM_DEVICE: + flag = SRB_DataIn; + break; + case DMA_NONE: + default: /* shuts up some versions of gcc */ + flag = SRB_NoDataXfer; + break; + } + + srbcmd = (struct aac_srb*) fib_data(fib); + srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); + srbcmd->channel = cpu_to_le32(aac_logical_to_phys(scmd_channel(cmd))); + srbcmd->id = cpu_to_le32(scmd_id(cmd)); + srbcmd->lun = cpu_to_le32(cmd->device->lun); + srbcmd->flags = cpu_to_le32(flag); + timeout = cmd->timeout_per_command/HZ; + if (timeout == 0) + timeout = 1; + srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds + srbcmd->retry_limit = 0; /* Obsolete parameter */ + srbcmd->cdb_size = cpu_to_le32(cmd->cmd_len); + return srbcmd; +} + +static void aac_srb_callback(void *context, struct fib * fibptr); + +static int aac_scsi_64(struct fib * fib, struct scsi_cmnd * cmd) +{ + u16 fibsize; + struct aac_srb * srbcmd = aac_scsi_common(fib, cmd); + + aac_build_sg64(cmd, (struct sgmap64*) &srbcmd->sg); + srbcmd->count = cpu_to_le32(cmd->request_bufflen); + + memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); + memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len); + /* + * Build Scatter/Gather list + */ + fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) + + ((le32_to_cpu(srbcmd->sg.count) & 0xff) * + sizeof (struct sgentry64)); + BUG_ON (fibsize > (fib->dev->max_fib_size - + sizeof(struct aac_fibhdr))); + + /* + * Now send the Fib to the adapter + */ + return aac_fib_send(ScsiPortCommand64, fib, + fibsize, FsaNormal, 0, 1, + (fib_callback) aac_srb_callback, + (void *) cmd); +} + +static int aac_scsi_32(struct fib * fib, struct scsi_cmnd * cmd) +{ + u16 fibsize; + struct aac_srb * srbcmd = aac_scsi_common(fib, cmd); + + aac_build_sg(cmd, (struct sgmap*)&srbcmd->sg); + srbcmd->count = cpu_to_le32(cmd->request_bufflen); + + memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); + memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len); + /* + * Build Scatter/Gather list + */ + fibsize = sizeof (struct aac_srb) + + (((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) * + sizeof (struct sgentry)); + BUG_ON (fibsize > (fib->dev->max_fib_size - + sizeof(struct aac_fibhdr))); + + /* + * Now send the Fib to the adapter + */ + return aac_fib_send(ScsiPortCommand, fib, fibsize, FsaNormal, 0, 1, + (fib_callback) aac_srb_callback, (void *) cmd); +} + int aac_get_adapter_info(struct aac_dev* dev) { struct fib* fibptr; @@ -874,14 +1177,27 @@ int aac_get_adapter_info(struct aac_dev* dev) } } /* - * 57 scatter gather elements + * Deal with configuring for the individualized limits of each packet + * interface. */ - if (!(dev->raw_io_interface)) { + dev->a_ops.adapter_scsi = (dev->dac_support) + ? aac_scsi_64 + : aac_scsi_32; + if (dev->raw_io_interface) { + dev->a_ops.adapter_bounds = (dev->raw_io_64) + ? aac_bounds_64 + : aac_bounds_32; + dev->a_ops.adapter_read = aac_read_raw_io; + dev->a_ops.adapter_write = aac_write_raw_io; + } else { + dev->a_ops.adapter_bounds = aac_bounds_32; dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size - sizeof(struct aac_fibhdr) - sizeof(struct aac_write) + sizeof(struct sgentry)) / sizeof(struct sgentry); if (dev->dac_support) { + dev->a_ops.adapter_read = aac_read_block64; + dev->a_ops.adapter_write = aac_write_block64; /* * 38 scatter gather elements */ @@ -891,6 +1207,9 @@ int aac_get_adapter_info(struct aac_dev* dev) sizeof(struct aac_write64) + sizeof(struct sgentry64)) / sizeof(struct sgentry64); + } else { + dev->a_ops.adapter_read = aac_read_block; + dev->a_ops.adapter_write = aac_write_block; } dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT; if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) { @@ -1004,8 +1323,6 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) u64 lba; u32 count; int status; - - u16 fibsize; struct aac_dev *dev; struct fib * cmd_fibcontext; @@ -1059,23 +1376,8 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) } dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %llu, t = %ld.\n", smp_processor_id(), (unsigned long long)lba, jiffies)); - if ((!(dev->raw_io_interface) || !(dev->raw_io_64)) && - (lba & 0xffffffff00000000LL)) { - dprintk((KERN_DEBUG "aac_read: Illegal lba\n")); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | - SAM_STAT_CHECK_CONDITION; - set_sense((u8 *) &dev->fsa_dev[cid].sense_data, - HARDWARE_ERROR, - SENCODE_INTERNAL_TARGET_FAILURE, - ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, - 0, 0); - memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, - (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer)) - ? sizeof(scsicmd->sense_buffer) - : sizeof(dev->fsa_dev[cid].sense_data)); - scsicmd->scsi_done(scsicmd); + if (aac_adapter_bounds(dev,scsicmd,lba)) return 0; - } /* * Alocate and initialize a Fib */ @@ -1083,85 +1385,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) return -1; } - aac_fib_init(cmd_fibcontext); - - if (dev->raw_io_interface) { - struct aac_raw_io *readcmd; - readcmd = (struct aac_raw_io *) fib_data(cmd_fibcontext); - readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff)); - readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); - readcmd->count = cpu_to_le32(count<<9); - readcmd->cid = cpu_to_le16(cid); - readcmd->flags = cpu_to_le16(1); - readcmd->bpTotal = 0; - readcmd->bpComplete = 0; - - aac_build_sgraw(scsicmd, &readcmd->sg); - fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw)); - BUG_ON(fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))); - /* - * Now send the Fib to the adapter - */ - status = aac_fib_send(ContainerRawIo, - cmd_fibcontext, - fibsize, - FsaNormal, - 0, 1, - (fib_callback) io_callback, - (void *) scsicmd); - } else if (dev->dac_support == 1) { - struct aac_read64 *readcmd; - readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext); - readcmd->command = cpu_to_le32(VM_CtHostRead64); - readcmd->cid = cpu_to_le16(cid); - readcmd->sector_count = cpu_to_le16(count); - readcmd->block = cpu_to_le32((u32)(lba&0xffffffff)); - readcmd->pad = 0; - readcmd->flags = 0; - - aac_build_sg64(scsicmd, &readcmd->sg); - fibsize = sizeof(struct aac_read64) + - ((le32_to_cpu(readcmd->sg.count) - 1) * - sizeof (struct sgentry64)); - BUG_ON (fibsize > (dev->max_fib_size - - sizeof(struct aac_fibhdr))); - /* - * Now send the Fib to the adapter - */ - status = aac_fib_send(ContainerCommand64, - cmd_fibcontext, - fibsize, - FsaNormal, - 0, 1, - (fib_callback) io_callback, - (void *) scsicmd); - } else { - struct aac_read *readcmd; - readcmd = (struct aac_read *) fib_data(cmd_fibcontext); - readcmd->command = cpu_to_le32(VM_CtBlockRead); - readcmd->cid = cpu_to_le32(cid); - readcmd->block = cpu_to_le32((u32)(lba&0xffffffff)); - readcmd->count = cpu_to_le32(count * 512); - - aac_build_sg(scsicmd, &readcmd->sg); - fibsize = sizeof(struct aac_read) + - ((le32_to_cpu(readcmd->sg.count) - 1) * - sizeof (struct sgentry)); - BUG_ON (fibsize > (dev->max_fib_size - - sizeof(struct aac_fibhdr))); - /* - * Now send the Fib to the adapter - */ - status = aac_fib_send(ContainerCommand, - cmd_fibcontext, - fibsize, - FsaNormal, - 0, 1, - (fib_callback) io_callback, - (void *) scsicmd); - } - - + status = aac_adapter_read(cmd_fibcontext, scsicmd, lba, count); /* * Check that the command queued to the controller @@ -1187,7 +1411,6 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) u64 lba; u32 count; int status; - u16 fibsize; struct aac_dev *dev; struct fib * cmd_fibcontext; @@ -1227,22 +1450,8 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) } dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n", smp_processor_id(), (unsigned long long)lba, jiffies)); - if ((!(dev->raw_io_interface) || !(dev->raw_io_64)) - && (lba & 0xffffffff00000000LL)) { - dprintk((KERN_DEBUG "aac_write: Illegal lba\n")); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; - set_sense((u8 *) &dev->fsa_dev[cid].sense_data, - HARDWARE_ERROR, - SENCODE_INTERNAL_TARGET_FAILURE, - ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, - 0, 0); - memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, - (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer)) - ? sizeof(scsicmd->sense_buffer) - : sizeof(dev->fsa_dev[cid].sense_data)); - scsicmd->scsi_done(scsicmd); + if (aac_adapter_bounds(dev,scsicmd,lba)) return 0; - } /* * Allocate and initialize a Fib then setup a BlockWrite command */ @@ -1251,85 +1460,8 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) scsicmd->scsi_done(scsicmd); return 0; } - aac_fib_init(cmd_fibcontext); - if (dev->raw_io_interface) { - struct aac_raw_io *writecmd; - writecmd = (struct aac_raw_io *) fib_data(cmd_fibcontext); - writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff)); - writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); - writecmd->count = cpu_to_le32(count<<9); - writecmd->cid = cpu_to_le16(cid); - writecmd->flags = 0; - writecmd->bpTotal = 0; - writecmd->bpComplete = 0; - - aac_build_sgraw(scsicmd, &writecmd->sg); - fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw)); - BUG_ON(fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))); - /* - * Now send the Fib to the adapter - */ - status = aac_fib_send(ContainerRawIo, - cmd_fibcontext, - fibsize, - FsaNormal, - 0, 1, - (fib_callback) io_callback, - (void *) scsicmd); - } else if (dev->dac_support == 1) { - struct aac_write64 *writecmd; - writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext); - writecmd->command = cpu_to_le32(VM_CtHostWrite64); - writecmd->cid = cpu_to_le16(cid); - writecmd->sector_count = cpu_to_le16(count); - writecmd->block = cpu_to_le32((u32)(lba&0xffffffff)); - writecmd->pad = 0; - writecmd->flags = 0; - - aac_build_sg64(scsicmd, &writecmd->sg); - fibsize = sizeof(struct aac_write64) + - ((le32_to_cpu(writecmd->sg.count) - 1) * - sizeof (struct sgentry64)); - BUG_ON (fibsize > (dev->max_fib_size - - sizeof(struct aac_fibhdr))); - /* - * Now send the Fib to the adapter - */ - status = aac_fib_send(ContainerCommand64, - cmd_fibcontext, - fibsize, - FsaNormal, - 0, 1, - (fib_callback) io_callback, - (void *) scsicmd); - } else { - struct aac_write *writecmd; - writecmd = (struct aac_write *) fib_data(cmd_fibcontext); - writecmd->command = cpu_to_le32(VM_CtBlockWrite); - writecmd->cid = cpu_to_le32(cid); - writecmd->block = cpu_to_le32((u32)(lba&0xffffffff)); - writecmd->count = cpu_to_le32(count * 512); - writecmd->sg.count = cpu_to_le32(1); - /* ->stable is not used - it did mean which type of write */ - - aac_build_sg(scsicmd, &writecmd->sg); - fibsize = sizeof(struct aac_write) + - ((le32_to_cpu(writecmd->sg.count) - 1) * - sizeof (struct sgentry)); - BUG_ON (fibsize > (dev->max_fib_size - - sizeof(struct aac_fibhdr))); - /* - * Now send the Fib to the adapter - */ - status = aac_fib_send(ContainerCommand, - cmd_fibcontext, - fibsize, - FsaNormal, - 0, 1, - (fib_callback) io_callback, - (void *) scsicmd); - } + status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count); /* * Check that the command queued to the controller @@ -2099,10 +2231,6 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) struct fib* cmd_fibcontext; struct aac_dev* dev; int status; - struct aac_srb *srbcmd; - u16 fibsize; - u32 flag; - u32 timeout; dev = (struct aac_dev *)scsicmd->device->host->hostdata; if (scmd_id(scsicmd) >= dev->maximum_num_physicals || @@ -2112,88 +2240,14 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) return 0; } - switch(scsicmd->sc_data_direction){ - case DMA_TO_DEVICE: - flag = SRB_DataOut; - break; - case DMA_BIDIRECTIONAL: - flag = SRB_DataIn | SRB_DataOut; - break; - case DMA_FROM_DEVICE: - flag = SRB_DataIn; - break; - case DMA_NONE: - default: /* shuts up some versions of gcc */ - flag = SRB_NoDataXfer; - break; - } - - /* * Allocate and initialize a Fib then setup a BlockWrite command */ if (!(cmd_fibcontext = aac_fib_alloc(dev))) { return -1; } - aac_fib_init(cmd_fibcontext); - - srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext); - srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); - srbcmd->channel = cpu_to_le32(aac_logical_to_phys(scmd_channel(scsicmd))); - srbcmd->id = cpu_to_le32(scmd_id(scsicmd)); - srbcmd->lun = cpu_to_le32(scsicmd->device->lun); - srbcmd->flags = cpu_to_le32(flag); - timeout = scsicmd->timeout_per_command/HZ; - if(timeout == 0){ - timeout = 1; - } - srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds - srbcmd->retry_limit = 0; /* Obsolete parameter */ - srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len); - - if( dev->dac_support == 1 ) { - aac_build_sg64(scsicmd, (struct sgmap64*) &srbcmd->sg); - srbcmd->count = cpu_to_le32(scsicmd->request_bufflen); - - memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); - memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len); - /* - * Build Scatter/Gather list - */ - fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) + - ((le32_to_cpu(srbcmd->sg.count) & 0xff) * - sizeof (struct sgentry64)); - BUG_ON (fibsize > (dev->max_fib_size - - sizeof(struct aac_fibhdr))); + status = aac_adapter_scsi(cmd_fibcontext, scsicmd); - /* - * Now send the Fib to the adapter - */ - status = aac_fib_send(ScsiPortCommand64, cmd_fibcontext, - fibsize, FsaNormal, 0, 1, - (fib_callback) aac_srb_callback, - (void *) scsicmd); - } else { - aac_build_sg(scsicmd, (struct sgmap*)&srbcmd->sg); - srbcmd->count = cpu_to_le32(scsicmd->request_bufflen); - - memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); - memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len); - /* - * Build Scatter/Gather list - */ - fibsize = sizeof (struct aac_srb) + - (((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) * - sizeof (struct sgentry)); - BUG_ON (fibsize > (dev->max_fib_size - - sizeof(struct aac_fibhdr))); - - /* - * Now send the Fib to the adapter - */ - status = aac_fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1, - (fib_callback) aac_srb_callback, (void *) scsicmd); - } /* * Check that the command queued to the controller */ diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 4f8b4c53d435867da99381898093ab5cc393dec5..39ecd0d22eb0dcc5e1b6397ec98ee84903a0c8da 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -5,6 +5,7 @@ #define _nblank(x) #x #define nblank(x) _nblank(x)[0] +#include /*------------------------------------------------------------------------------ * D E F I N E S @@ -485,16 +486,28 @@ enum aac_log_level { struct aac_dev; struct fib; +struct scsi_cmnd; struct adapter_ops { + /* Low level operations */ void (*adapter_interrupt)(struct aac_dev *dev); void (*adapter_notify)(struct aac_dev *dev, u32 event); void (*adapter_disable_int)(struct aac_dev *dev); + void (*adapter_enable_int)(struct aac_dev *dev); int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4); int (*adapter_check_health)(struct aac_dev *dev); - int (*adapter_send)(struct fib * fib); + /* Transport operations */ int (*adapter_ioremap)(struct aac_dev * dev, u32 size); + irqreturn_t (*adapter_intr)(int irq, void *dev_id); + /* Packet operations */ + int (*adapter_deliver)(struct fib * fib); + int (*adapter_bounds)(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba); + int (*adapter_read)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count); + int (*adapter_write)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count); + int (*adapter_scsi)(struct fib * fib, struct scsi_cmnd * cmd); + /* Administrative operations */ + int (*adapter_comm)(struct aac_dev * dev, int comm); }; /* @@ -1018,7 +1031,9 @@ struct aac_dev u8 nondasd_support; u8 dac_support; u8 raid_scsi_mode; - u8 new_comm_interface; + u8 comm_interface; +# define AAC_COMM_PRODUCER 0 +# define AAC_COMM_MESSAGE 1 /* macro side-effects BEWARE */ # define raw_io_interface \ init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4) @@ -1036,18 +1051,36 @@ struct aac_dev #define aac_adapter_disable_int(dev) \ (dev)->a_ops.adapter_disable_int(dev) +#define aac_adapter_enable_int(dev) \ + (dev)->a_ops.adapter_enable_int(dev) + #define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \ (dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) #define aac_adapter_check_health(dev) \ (dev)->a_ops.adapter_check_health(dev) -#define aac_adapter_send(fib) \ - ((fib)->dev)->a_ops.adapter_send(fib) - #define aac_adapter_ioremap(dev, size) \ (dev)->a_ops.adapter_ioremap(dev, size) +#define aac_adapter_deliver(fib) \ + ((fib)->dev)->a_ops.adapter_deliver(fib) + +#define aac_adapter_bounds(dev,cmd,lba) \ + dev->a_ops.adapter_bounds(dev,cmd,lba) + +#define aac_adapter_read(fib,cmd,lba,count) \ + ((fib)->dev)->a_ops.adapter_read(fib,cmd,lba,count) + +#define aac_adapter_write(fib,cmd,lba,count) \ + ((fib)->dev)->a_ops.adapter_write(fib,cmd,lba,count) + +#define aac_adapter_scsi(fib,cmd) \ + ((fib)->dev)->a_ops.adapter_scsi(fib,cmd) + +#define aac_adapter_comm(dev,comm) \ + (dev)->a_ops.adapter_comm(dev, comm) + #define FIB_CONTEXT_FLAG_TIMED_OUT (0x00000001) /* @@ -1767,7 +1800,6 @@ static inline u32 cap_to_cyls(sector_t capacity, u32 divisor) return (u32)capacity; } -struct scsi_cmnd; /* SCp.phase values */ #define AAC_OWNER_MIDLEVEL 0x101 #define AAC_OWNER_LOWLEVEL 0x102 @@ -1794,7 +1826,9 @@ int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg); int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg); int aac_rx_init(struct aac_dev *dev); int aac_rkt_init(struct aac_dev *dev); +int aac_nark_init(struct aac_dev *dev); int aac_sa_init(struct aac_dev *dev); +int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify); unsigned int aac_response_normal(struct aac_queue * q); unsigned int aac_command_normal(struct aac_queue * q); unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index); diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 6d305b2f854e2fad06e869ac05c996351cb21c7e..df67ba686023d891a234c3ed9e577a632847e1db 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -95,7 +95,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES); init->InitFlags = 0; - if (dev->new_comm_interface) { + if (dev->comm_interface == AAC_COMM_MESSAGE) { init->InitFlags = cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED); dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n")); } @@ -297,21 +297,23 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) - sizeof(struct aac_fibhdr) - sizeof(struct aac_write) + sizeof(struct sgentry)) / sizeof(struct sgentry); - dev->new_comm_interface = 0; + dev->comm_interface = AAC_COMM_PRODUCER; dev->raw_io_64 = 0; if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES, 0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) && (status[0] == 0x00000001)) { if (status[1] & AAC_OPT_NEW_COMM_64) dev->raw_io_64 = 1; - if (status[1] & AAC_OPT_NEW_COMM) - dev->new_comm_interface = dev->a_ops.adapter_send != 0; - if (dev->new_comm_interface && (status[2] > dev->base_size)) { + if (dev->a_ops.adapter_comm && + (status[1] & AAC_OPT_NEW_COMM)) + dev->comm_interface = AAC_COMM_MESSAGE; + if ((dev->comm_interface == AAC_COMM_MESSAGE) && + (status[2] > dev->base_size)) { aac_adapter_ioremap(dev, 0); dev->base_size = status[2]; if (aac_adapter_ioremap(dev, status[2])) { /* remap failed, go back ... */ - dev->new_comm_interface = 0; + dev->comm_interface = AAC_COMM_PRODUCER; if (aac_adapter_ioremap(dev, AAC_MIN_FOOTPRINT_SIZE)) { printk(KERN_WARNING "aacraid: unable to map adapter.\n"); diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 4893a6d06a332ac6f32500f3e0ebc3a1a7183838..1b97f60652ba2cacdcf9bc9c4d3170c4d6f92adf 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -317,7 +317,7 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr * success. */ -static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify) +int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify) { struct aac_entry * entry = NULL; int map = 0; @@ -387,7 +387,6 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, { struct aac_dev * dev = fibptr->dev; struct hw_fib * hw_fib = fibptr->hw_fib; - struct aac_queue * q; unsigned long flags = 0; unsigned long qflags; @@ -469,38 +468,10 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, if (!dev->queues) return -EBUSY; - q = &dev->queues->queue[AdapNormCmdQueue]; if(wait) spin_lock_irqsave(&fibptr->event_lock, flags); - spin_lock_irqsave(q->lock, qflags); - if (dev->new_comm_interface) { - unsigned long count = 10000000L; /* 50 seconds */ - q->numpending++; - spin_unlock_irqrestore(q->lock, qflags); - while (aac_adapter_send(fibptr) != 0) { - if (--count == 0) { - if (wait) - spin_unlock_irqrestore(&fibptr->event_lock, flags); - spin_lock_irqsave(q->lock, qflags); - q->numpending--; - spin_unlock_irqrestore(q->lock, qflags); - return -ETIMEDOUT; - } - udelay(5); - } - } else { - u32 index; - unsigned long nointr = 0; - aac_queue_get( dev, &index, AdapNormCmdQueue, hw_fib, 1, fibptr, &nointr); - - q->numpending++; - *(q->headers.producer) = cpu_to_le32(index + 1); - spin_unlock_irqrestore(q->lock, qflags); - dprintk((KERN_DEBUG "aac_fib_send: inserting a queue entry at index %d.\n",index)); - if (!(nointr & aac_config.irq_mod)) - aac_adapter_notify(dev, AdapNormCmdQueue); - } + aac_adapter_deliver(fibptr); /* * If the caller wanted us to wait for response wait now. @@ -520,6 +491,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, while (down_trylock(&fibptr->event_wait)) { int blink; if (--count == 0) { + struct aac_queue * q = &dev->queues->queue[AdapNormCmdQueue]; spin_lock_irqsave(q->lock, qflags); q->numpending--; spin_unlock_irqrestore(q->lock, qflags); @@ -659,7 +631,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) unsigned long qflags; if (hw_fib->header.XferState == 0) { - if (dev->new_comm_interface) + if (dev->comm_interface == AAC_COMM_MESSAGE) kfree (hw_fib); return 0; } @@ -667,7 +639,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) * If we plan to do anything check the structure type first. */ if ( hw_fib->header.StructType != FIB_MAGIC ) { - if (dev->new_comm_interface) + if (dev->comm_interface == AAC_COMM_MESSAGE) kfree (hw_fib); return -EINVAL; } @@ -679,7 +651,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) * send the completed cdb to the adapter. */ if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) { - if (dev->new_comm_interface) { + if (dev->comm_interface == AAC_COMM_MESSAGE) { kfree (hw_fib); } else { u32 index; diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index d2cf875af59b6139fa99f63257b1e189fc22551a..a9734e08fe28a7cf35d01727a0ab509c0aff7da3 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -157,6 +157,7 @@ static struct pci_device_id aac_pci_tbl[] = { { 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 58 }, /* Legend Catchall */ { 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */ { 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */ + { 0x9005, 0x0288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 61 }, /* Adaptec NEMER/ARK Catch All */ { 0,} }; MODULE_DEVICE_TABLE(pci, aac_pci_tbl); @@ -230,7 +231,8 @@ static struct aac_driver_ident aac_drivers[] = { { aac_rx_init, "aacraid", "DELL ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Dell Catchall */ { aac_rx_init, "aacraid", "Legend ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Legend Catchall */ { aac_rx_init, "aacraid", "ADAPTEC ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec Catch All */ - { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec Rocket Catch All */ + { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Rocket Catch All */ + { aac_nark_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec NEMER/ARK Catch All */ }; /** @@ -396,11 +398,15 @@ static int aac_slave_configure(struct scsi_device *sdev) sdev->skip_ms_page_3f = 1; } if ((sdev->type == TYPE_DISK) && - !expose_physicals && (sdev_channel(sdev) != CONTAINER_CHANNEL)) { - struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata; - if (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2)) - sdev->no_uld_attach = 1; + if (expose_physicals == 0) + return -ENXIO; + if (expose_physicals < 0) { + struct aac_dev *aac = + (struct aac_dev *)sdev->host->hostdata; + if (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2)) + sdev->no_uld_attach = 1; + } } if (sdev->tagged_supported && (sdev->type == TYPE_DISK) && (sdev_channel(sdev) == CONTAINER_CHANNEL)) { @@ -804,7 +810,6 @@ static struct scsi_host_template aac_driver_template = { .emulated = 1, }; - static int __devinit aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) { diff --git a/drivers/scsi/aacraid/nark.c b/drivers/scsi/aacraid/nark.c new file mode 100644 index 0000000000000000000000000000000000000000..c76b611b6afb8ae4adcf5e75269c86b7933b2c71 --- /dev/null +++ b/drivers/scsi/aacraid/nark.c @@ -0,0 +1,87 @@ +/* + * Adaptec AAC series RAID controller driver + * (c) Copyright 2001 Red Hat Inc. + * + * based on the old aacraid driver that is.. + * Adaptec aacraid device driver for Linux. + * + * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * + * 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; either version 2, or (at your option) + * any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Module Name: + * nark.c + * + * Abstract: Hardware Device Interface for NEMER/ARK + * + */ + +#include +#include + +#include + +#include "aacraid.h" + +/** + * aac_nark_ioremap + * @size: mapping resize request + * + */ +static int aac_nark_ioremap(struct aac_dev * dev, u32 size) +{ + if (!size) { + iounmap(dev->regs.rx); + dev->regs.rx = NULL; + iounmap(dev->base); + dev->base = NULL; + return 0; + } + dev->scsi_host_ptr->base = pci_resource_start(dev->pdev, 2); + dev->regs.rx = ioremap((u64)pci_resource_start(dev->pdev, 0) | + ((u64)pci_resource_start(dev->pdev, 1) << 32), + sizeof(struct rx_registers) - sizeof(struct rx_inbound)); + dev->base = NULL; + if (dev->regs.rx == NULL) + return -1; + dev->base = ioremap(dev->scsi_host_ptr->base, size); + if (dev->base == NULL) { + iounmap(dev->regs.rx); + dev->regs.rx = NULL; + return -1; + } + dev->IndexRegs = &((struct rx_registers __iomem *)dev->base)->IndexRegs; + return 0; +} + +/** + * aac_nark_init - initialize an NEMER/ARK Split Bar card + * @dev: device to configure + * + */ + +int aac_nark_init(struct aac_dev * dev) +{ + extern int _aac_rx_init(struct aac_dev *dev); + extern int aac_rx_select_comm(struct aac_dev *dev, int comm); + + /* + * Fill in the function dispatch table. + */ + dev->a_ops.adapter_ioremap = aac_nark_ioremap; + dev->a_ops.adapter_comm = aac_rx_select_comm; + + return _aac_rx_init(dev); +} diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c index 643f23b5ded884a2e11b79df58e36eaa27d66dc0..d953c3fe998aa99c159bca641903c5e48a7e9d8f 100644 --- a/drivers/scsi/aacraid/rkt.c +++ b/drivers/scsi/aacraid/rkt.c @@ -34,6 +34,40 @@ #include "aacraid.h" +#define AAC_NUM_IO_FIB_RKT (246 - AAC_NUM_MGT_FIB) + +/** + * aac_rkt_select_comm - Select communications method + * @dev: Adapter + * @comm: communications method + */ + +static int aac_rkt_select_comm(struct aac_dev *dev, int comm) +{ + int retval; + extern int aac_rx_select_comm(struct aac_dev *dev, int comm); + retval = aac_rx_select_comm(dev, comm); + if (comm == AAC_COMM_MESSAGE) { + /* + * FIB Setup has already been done, but we can minimize the + * damage by at least ensuring the OS never issues more + * commands than we can handle. The Rocket adapters currently + * can only handle 246 commands and 8 AIFs at the same time, + * and in fact do notify us accordingly if we negotiate the + * FIB size. The problem that causes us to add this check is + * to ensure that we do not overdo it with the adapter when a + * hard coded FIB override is being utilized. This special + * case warrants this half baked, but convenient, check here. + */ + if (dev->scsi_host_ptr->can_queue > AAC_NUM_IO_FIB_RKT) { + dev->init->MaxIoCommands = + cpu_to_le32(AAC_NUM_IO_FIB_RKT + AAC_NUM_MGT_FIB); + dev->scsi_host_ptr->can_queue = AAC_NUM_IO_FIB_RKT; + } + } + return retval; +} + /** * aac_rkt_ioremap * @size: mapping resize request @@ -63,39 +97,13 @@ static int aac_rkt_ioremap(struct aac_dev * dev, u32 size) int aac_rkt_init(struct aac_dev *dev) { - int retval; extern int _aac_rx_init(struct aac_dev *dev); - extern void aac_rx_start_adapter(struct aac_dev *dev); /* * Fill in the function dispatch table. */ dev->a_ops.adapter_ioremap = aac_rkt_ioremap; + dev->a_ops.adapter_comm = aac_rkt_select_comm; - retval = _aac_rx_init(dev); - if (retval) - return retval; - if (dev->new_comm_interface) { - /* - * FIB Setup has already been done, but we can minimize the - * damage by at least ensuring the OS never issues more - * commands than we can handle. The Rocket adapters currently - * can only handle 246 commands and 8 AIFs at the same time, - * and in fact do notify us accordingly if we negotiate the - * FIB size. The problem that causes us to add this check is - * to ensure that we do not overdo it with the adapter when a - * hard coded FIB override is being utilized. This special - * case warrants this half baked, but convenient, check here. - */ - if (dev->scsi_host_ptr->can_queue > (246 - AAC_NUM_MGT_FIB)) { - dev->init->MaxIoCommands = cpu_to_le32(246); - dev->scsi_host_ptr->can_queue = 246 - AAC_NUM_MGT_FIB; - } - } - /* - * Tell the adapter that all is configured, and it can start - * accepting requests - */ - aac_rx_start_adapter(dev); - return 0; + return _aac_rx_init(dev); } diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index dcc8b0ea7a9d213b4605857c574702a059cbb869..c632d9354a261a5af10e9407f38d04bfcabd9bd3 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -46,60 +46,60 @@ #include "aacraid.h" -static irqreturn_t aac_rx_intr(int irq, void *dev_id) +static irqreturn_t aac_rx_intr_producer(int irq, void *dev_id) { struct aac_dev *dev = dev_id; + unsigned long bellbits; + u8 intstat = rx_readb(dev, MUnit.OISR); - dprintk((KERN_DEBUG "aac_rx_intr(%d,%p)\n", irq, dev_id)); - if (dev->new_comm_interface) { - u32 Index = rx_readl(dev, MUnit.OutboundQueue); - if (Index == 0xFFFFFFFFL) - Index = rx_readl(dev, MUnit.OutboundQueue); - if (Index != 0xFFFFFFFFL) { - do { - if (aac_intr_normal(dev, Index)) { - rx_writel(dev, MUnit.OutboundQueue, Index); - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady); - } - Index = rx_readl(dev, MUnit.OutboundQueue); - } while (Index != 0xFFFFFFFFL); - return IRQ_HANDLED; + /* + * Read mask and invert because drawbridge is reversed. + * This allows us to only service interrupts that have + * been enabled. + * Check to see if this is our interrupt. If it isn't just return + */ + if (intstat & ~(dev->OIMR)) { + bellbits = rx_readl(dev, OutboundDoorbellReg); + if (bellbits & DoorBellPrintfReady) { + aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5])); + rx_writel(dev, MUnit.ODR,DoorBellPrintfReady); + rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); } - } else { - unsigned long bellbits; - u8 intstat; - intstat = rx_readb(dev, MUnit.OISR); - /* - * Read mask and invert because drawbridge is reversed. - * This allows us to only service interrupts that have - * been enabled. - * Check to see if this is our interrupt. If it isn't just return - */ - if (intstat & ~(dev->OIMR)) - { - bellbits = rx_readl(dev, OutboundDoorbellReg); - if (bellbits & DoorBellPrintfReady) { - aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5])); - rx_writel(dev, MUnit.ODR,DoorBellPrintfReady); - rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); - } - else if (bellbits & DoorBellAdapterNormCmdReady) { - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); - aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); - } - else if (bellbits & DoorBellAdapterNormRespReady) { - rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); - aac_response_normal(&dev->queues->queue[HostNormRespQueue]); - } - else if (bellbits & DoorBellAdapterNormCmdNotFull) { - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); - } - else if (bellbits & DoorBellAdapterNormRespNotFull) { - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); - } - return IRQ_HANDLED; + else if (bellbits & DoorBellAdapterNormCmdReady) { + rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); + aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); + } + else if (bellbits & DoorBellAdapterNormRespReady) { + rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); + aac_response_normal(&dev->queues->queue[HostNormRespQueue]); + } + else if (bellbits & DoorBellAdapterNormCmdNotFull) { + rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); } + else if (bellbits & DoorBellAdapterNormRespNotFull) { + rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); + rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); + } + return IRQ_HANDLED; + } + return IRQ_NONE; +} + +static irqreturn_t aac_rx_intr_message(int irq, void *dev_id) +{ + struct aac_dev *dev = dev_id; + u32 Index = rx_readl(dev, MUnit.OutboundQueue); + if (Index == 0xFFFFFFFFL) + Index = rx_readl(dev, MUnit.OutboundQueue); + if (Index != 0xFFFFFFFFL) { + do { + if (aac_intr_normal(dev, Index)) { + rx_writel(dev, MUnit.OutboundQueue, Index); + rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady); + } + Index = rx_readl(dev, MUnit.OutboundQueue); + } while (Index != 0xFFFFFFFFL); + return IRQ_HANDLED; } return IRQ_NONE; } @@ -114,6 +114,26 @@ static void aac_rx_disable_interrupt(struct aac_dev *dev) rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff); } +/** + * aac_rx_enable_interrupt_producer - Enable interrupts + * @dev: Adapter + */ + +static void aac_rx_enable_interrupt_producer(struct aac_dev *dev) +{ + rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); +} + +/** + * aac_rx_enable_interrupt_message - Enable interrupts + * @dev: Adapter + */ + +static void aac_rx_enable_interrupt_message(struct aac_dev *dev) +{ + rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7); +} + /** * rx_sync_cmd - send a command and wait * @dev: Adapter @@ -189,10 +209,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, /* * Restore interrupt mask even though we timed out */ - if (dev->new_comm_interface) - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7); - else - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); + aac_adapter_enable_int(dev); return -ETIMEDOUT; } /* @@ -215,10 +232,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, /* * Restore interrupt mask */ - if (dev->new_comm_interface) - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7); - else - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); + aac_adapter_enable_int(dev); return 0; } @@ -360,35 +374,72 @@ static int aac_rx_check_health(struct aac_dev *dev) } /** - * aac_rx_send + * aac_rx_deliver_producer * @fib: fib to issue * * Will send a fib, returning 0 if successful. */ -static int aac_rx_send(struct fib * fib) +static int aac_rx_deliver_producer(struct fib * fib) { - u64 addr = fib->hw_fib_pa; struct aac_dev *dev = fib->dev; - volatile void __iomem *device = dev->regs.rx; + struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue]; + unsigned long qflags; u32 Index; + unsigned long nointr = 0; - dprintk((KERN_DEBUG "%p->aac_rx_send(%p->%llx)\n", dev, fib, addr)); - Index = rx_readl(dev, MUnit.InboundQueue); - if (Index == 0xFFFFFFFFL) + spin_lock_irqsave(q->lock, qflags); + aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib, 1, fib, &nointr); + + q->numpending++; + *(q->headers.producer) = cpu_to_le32(Index + 1); + spin_unlock_irqrestore(q->lock, qflags); + if (!(nointr & aac_config.irq_mod)) + aac_adapter_notify(dev, AdapNormCmdQueue); + + return 0; +} + +/** + * aac_rx_deliver_message + * @fib: fib to issue + * + * Will send a fib, returning 0 if successful. + */ +static int aac_rx_deliver_message(struct fib * fib) +{ + struct aac_dev *dev = fib->dev; + struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue]; + unsigned long qflags; + u32 Index; + u64 addr; + volatile void __iomem *device; + + unsigned long count = 10000000L; /* 50 seconds */ + spin_lock_irqsave(q->lock, qflags); + q->numpending++; + spin_unlock_irqrestore(q->lock, qflags); + for(;;) { Index = rx_readl(dev, MUnit.InboundQueue); - dprintk((KERN_DEBUG "Index = 0x%x\n", Index)); - if (Index == 0xFFFFFFFFL) - return Index; + if (Index == 0xFFFFFFFFL) + Index = rx_readl(dev, MUnit.InboundQueue); + if (Index != 0xFFFFFFFFL) + break; + if (--count == 0) { + spin_lock_irqsave(q->lock, qflags); + q->numpending--; + spin_unlock_irqrestore(q->lock, qflags); + return -ETIMEDOUT; + } + udelay(5); + } device = dev->base + Index; - dprintk((KERN_DEBUG "entry = %x %x %u\n", (u32)(addr & 0xffffffff), - (u32)(addr >> 32), (u32)le16_to_cpu(fib->hw_fib->header.Size))); + addr = fib->hw_fib_pa; writel((u32)(addr & 0xffffffff), device); device += sizeof(u32); writel((u32)(addr >> 32), device); device += sizeof(u32); writel(le16_to_cpu(fib->hw_fib->header.Size), device); rx_writel(dev, MUnit.InboundQueue, Index); - dprintk((KERN_DEBUG "aac_rx_send - return 0\n")); return 0; } @@ -429,6 +480,31 @@ static int aac_rx_restart_adapter(struct aac_dev *dev) return 0; } +/** + * aac_rx_select_comm - Select communications method + * @dev: Adapter + * @comm: communications method + */ + +int aac_rx_select_comm(struct aac_dev *dev, int comm) +{ + switch (comm) { + case AAC_COMM_PRODUCER: + dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt_producer; + dev->a_ops.adapter_intr = aac_rx_intr_producer; + dev->a_ops.adapter_deliver = aac_rx_deliver_producer; + break; + case AAC_COMM_MESSAGE: + dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt_message; + dev->a_ops.adapter_intr = aac_rx_intr_message; + dev->a_ops.adapter_deliver = aac_rx_deliver_message; + break; + default: + return 1; + } + return 0; +} + /** * aac_rx_init - initialize an i960 based AAC card * @dev: device to configure @@ -489,40 +565,42 @@ int _aac_rx_init(struct aac_dev *dev) } msleep(1); } - if (request_irq(dev->scsi_host_ptr->irq, aac_rx_intr, IRQF_SHARED|IRQF_DISABLED, "aacraid", (void *)dev)<0) - { - printk(KERN_ERR "%s%d: Interrupt unavailable.\n", name, instance); - goto error_iounmap; - } /* - * Fill in the function dispatch table. + * Fill in the common function dispatch table. */ dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter; dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt; dev->a_ops.adapter_notify = aac_rx_notify_adapter; dev->a_ops.adapter_sync_cmd = rx_sync_cmd; dev->a_ops.adapter_check_health = aac_rx_check_health; - dev->a_ops.adapter_send = aac_rx_send; /* * First clear out all interrupts. Then enable the one's that we * can handle. */ - rx_writeb(dev, MUnit.OIMR, 0xff); + aac_adapter_comm(dev, AAC_COMM_PRODUCER); + aac_adapter_disable_int(dev); rx_writel(dev, MUnit.ODR, 0xffffffff); - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); + aac_adapter_enable_int(dev); if (aac_init_adapter(dev) == NULL) - goto error_irq; - if (dev->new_comm_interface) - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7); + goto error_iounmap; + aac_adapter_comm(dev, dev->comm_interface); + if (request_irq(dev->scsi_host_ptr->irq, dev->a_ops.adapter_intr, + IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) { + printk(KERN_ERR "%s%d: Interrupt unavailable.\n", + name, instance); + goto error_iounmap; + } + aac_adapter_enable_int(dev); + /* + * Tell the adapter that all is configured, and it can + * start accepting requests + */ + aac_rx_start_adapter(dev); return 0; -error_irq: - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff); - free_irq(dev->scsi_host_ptr->irq, (void *)dev); - error_iounmap: return -1; @@ -530,20 +608,11 @@ int _aac_rx_init(struct aac_dev *dev) int aac_rx_init(struct aac_dev *dev) { - int retval; - /* * Fill in the function dispatch table. */ dev->a_ops.adapter_ioremap = aac_rx_ioremap; + dev->a_ops.adapter_comm = aac_rx_select_comm; - retval = _aac_rx_init(dev); - if (!retval) { - /* - * Tell the adapter that all is configured, and it can - * start accepting requests - */ - aac_rx_start_adapter(dev); - } - return retval; + return _aac_rx_init(dev); } diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c index 511b0a938fb18b4ebcd488b1fe5087e385bc0cdd..8535db068c2f7de3dcd51a824a2ad47064083414 100644 --- a/drivers/scsi/aacraid/sa.c +++ b/drivers/scsi/aacraid/sa.c @@ -91,6 +91,17 @@ static void aac_sa_disable_interrupt (struct aac_dev *dev) sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff); } +/** + * aac_sa_enable_interrupt - enable interrupt + * @dev: Which adapter to enable. + */ + +static void aac_sa_enable_interrupt (struct aac_dev *dev) +{ + sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | + DOORBELL_2 | DOORBELL_3 | DOORBELL_4)); +} + /** * aac_sa_notify_adapter - handle adapter notification * @dev: Adapter that notification is for @@ -347,32 +358,36 @@ int aac_sa_init(struct aac_dev *dev) msleep(1); } - if (request_irq(dev->scsi_host_ptr->irq, aac_sa_intr, IRQF_SHARED|IRQF_DISABLED, "aacraid", (void *)dev ) < 0) { - printk(KERN_WARNING "%s%d: Interrupt unavailable.\n", name, instance); - goto error_iounmap; - } - /* * Fill in the function dispatch table. */ dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter; dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt; + dev->a_ops.adapter_enable_int = aac_sa_enable_interrupt; dev->a_ops.adapter_notify = aac_sa_notify_adapter; dev->a_ops.adapter_sync_cmd = sa_sync_cmd; dev->a_ops.adapter_check_health = aac_sa_check_health; + dev->a_ops.adapter_intr = aac_sa_intr; dev->a_ops.adapter_ioremap = aac_sa_ioremap; /* * First clear out all interrupts. Then enable the one's that * we can handle. */ - sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff); - sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | - DOORBELL_2 | DOORBELL_3 | DOORBELL_4)); + aac_adapter_disable_int(dev); + aac_adapter_enable_int(dev); if(aac_init_adapter(dev) == NULL) goto error_irq; + if (request_irq(dev->scsi_host_ptr->irq, dev->a_ops.adapter_intr, + IRQF_SHARED|IRQF_DISABLED, + "aacraid", (void *)dev ) < 0) { + printk(KERN_WARNING "%s%d: Interrupt unavailable.\n", + name, instance); + goto error_iounmap; + } + aac_adapter_enable_int(dev); /* * Tell the adapter that all is configure, and it can start @@ -382,7 +397,7 @@ int aac_sa_init(struct aac_dev *dev) return 0; error_irq: - sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff); + aac_sa_disable_interrupt(dev); free_irq(dev->scsi_host_ptr->irq, (void *)dev); error_iounmap: diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 306bec355e45c9abc80b03631c23c64616983346..9b3303b64113780b6eff7abfc296b30036fb2b84 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -4403,7 +4403,7 @@ advansys_detect(struct scsi_host_template *tpnt) ASC_DBG1(1, "advansys_detect: probing I/O port 0x%x...\n", iop); - if (check_region(iop, ASC_IOADR_GAP) != 0) { + if (!request_region(iop, ASC_IOADR_GAP, "advansys")){ printk( "AdvanSys SCSI: specified I/O Port 0x%X is busy\n", iop); /* Don't try this I/O port twice. */ @@ -4413,6 +4413,7 @@ advansys_detect(struct scsi_host_template *tpnt) printk( "AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", iop); /* Don't try this I/O port twice. */ + release_region(iop, ASC_IOADR_GAP); asc_ioport[ioport] = 0; goto ioport_try_again; } else { @@ -4431,6 +4432,7 @@ advansys_detect(struct scsi_host_template *tpnt) * 'ioport' past this board. */ ioport++; + release_region(iop, ASC_IOADR_GAP); goto ioport_try_again; } } @@ -9740,13 +9742,14 @@ AscSearchIOPortAddr11( } for (; i < ASC_IOADR_TABLE_MAX_IX; i++) { iop_base = _asc_def_iop_base[i]; - if (check_region(iop_base, ASC_IOADR_GAP) != 0) { + if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")){ ASC_DBG1(1, "AscSearchIOPortAddr11: check_region() failed I/O port 0x%x\n", iop_base); continue; } ASC_DBG1(1, "AscSearchIOPortAddr11: probing I/O port 0x%x\n", iop_base); + release_region(iop_base, ASC_IOADR_GAP); if (AscFindSignature(iop_base)) { return (iop_base); } diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index 170a4344cbb2a62ee9446dd57e40339a1b7d98ff..27adbb294ac1db21cc0b962714f29020a89805bb 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -1337,9 +1337,6 @@ int ahd_pci_test_register_access(struct ahd_softc *); /************************** SCB and SCB queue management **********************/ void ahd_qinfifo_requeue_tail(struct ahd_softc *ahd, struct scb *scb); -int ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, - int target, char channel, int lun, - u_int tag, role_t role); /****************************** Initialization ********************************/ struct ahd_softc *ahd_alloc(void *platform_arg, char *name); diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 07a86a30f676c4d2c64afec835ce44f01201a697..9ddc6e4a74b040d497620675f0cd5dfcf7256078 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -262,6 +262,9 @@ static void ahd_update_coalescing_values(struct ahd_softc *ahd, u_int mincmds); static int ahd_verify_vpd_cksum(struct vpd_config *vpd); static int ahd_wait_seeprom(struct ahd_softc *ahd); +static int ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, + int target, char channel, int lun, + u_int tag, role_t role); /******************************** Private Inlines *****************************/ @@ -7256,7 +7259,7 @@ ahd_busy_tcl(struct ahd_softc *ahd, u_int tcl, u_int scbid) } /************************** SCB and SCB queue management **********************/ -int +static int ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, int target, char channel, int lun, u_int tag, role_t role) { diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 9bfcca5ede088c0c78a8645525376e3b1cf0eb45..c7fe478f481377d4b7add47574c6c3463dbd7b7a 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -1126,15 +1126,6 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa return 0; } -uint64_t -ahd_linux_get_memsize(void) -{ - struct sysinfo si; - - si_meminfo(&si); - return ((uint64_t)si.totalram << PAGE_SHIFT); -} - /* * Place the SCSI bus into a known state by either resetting it, * or forcing transfer negotiations on the next command to any diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index 3a67fc578d78051f6f43b4643e26e54eb4b356b2..147c83c456a57cdfbd20206dba14c50b8c68daa3 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h @@ -496,8 +496,6 @@ ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count) int ahd_linux_register_host(struct ahd_softc *, struct scsi_host_template *); -uint64_t ahd_linux_get_memsize(void); - /*************************** Pretty Printing **********************************/ struct info_str { char *buffer; diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index 1a3ab6aa856bb158e79574a4856e8374bbeb5127..c62ce41f2793750627130b0367547e3cf6fab736 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c @@ -132,6 +132,7 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct ahd_pci_identity *entry; char *name; int error; + struct device *dev = &pdev->dev; pci = pdev; entry = ahd_find_pci_device(pci); @@ -161,20 +162,18 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_master(pdev); if (sizeof(dma_addr_t) > 4) { - uint64_t memsize; - const uint64_t mask_39bit = 0x7FFFFFFFFFULL; + const u64 required_mask = dma_get_required_mask(dev); - memsize = ahd_linux_get_memsize(); - - if (memsize >= 0x8000000000ULL - && pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) { + if (required_mask > DMA_39BIT_MASK && + dma_set_mask(dev, DMA_64BIT_MASK) == 0) ahd->flags |= AHD_64BIT_ADDRESSING; - } else if (memsize > 0x80000000 - && pci_set_dma_mask(pdev, mask_39bit) == 0) { + else if (required_mask > DMA_32BIT_MASK && + dma_set_mask(dev, DMA_39BIT_MASK) == 0) ahd->flags |= AHD_39BIT_ADDRESSING; - } + else + dma_set_mask(dev, DMA_32BIT_MASK); } else { - pci_set_dma_mask(pdev, DMA_32BIT_MASK); + dma_set_mask(dev, DMA_32BIT_MASK); } ahd->dev_softc = pci; error = ahd_pci_config(ahd, entry); diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c index 2cf7bb3123f099c732ba665c514b085ee0eb60e1..8d72bbae96ad1a59a3777b662d8e47b640abc0c1 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c @@ -88,7 +88,7 @@ ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) #define SUBID_9005_LEGACYCONN_FUNC(id) ((id) & 0x20) -#define SUBID_9005_SEEPTYPE(id) ((id) & 0x0C0) >> 6) +#define SUBID_9005_SEEPTYPE(id) (((id) & 0x0C0) >> 6) #define SUBID_9005_SEEPTYPE_NONE 0x0 #define SUBID_9005_SEEPTYPE_4K 0x1 diff --git a/drivers/scsi/aic94xx/aic94xx_dev.c b/drivers/scsi/aic94xx/aic94xx_dev.c index 6f8901b748f737c676d0c22226f06117e09a545e..c520e5b41fb52288982d73ac2ce46362407938d5 100644 --- a/drivers/scsi/aic94xx/aic94xx_dev.c +++ b/drivers/scsi/aic94xx/aic94xx_dev.c @@ -37,18 +37,14 @@ static inline int asd_get_ddb(struct asd_ha_struct *asd_ha) { - unsigned long flags; int ddb, i; - spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); ddb = FIND_FREE_DDB(asd_ha); if (ddb >= asd_ha->hw_prof.max_ddbs) { ddb = -ENOMEM; - spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); goto out; } SET_DDB(ddb, asd_ha); - spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); for (i = 0; i < sizeof(struct asd_ddb_ssp_smp_target_port); i+= 4) asd_ddbsite_write_dword(asd_ha, ddb, i, 0); @@ -77,14 +73,10 @@ static inline int asd_get_ddb(struct asd_ha_struct *asd_ha) static inline void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb) { - unsigned long flags; - if (!ddb || ddb >= 0xFFFF) return; asd_ddbsite_write_byte(asd_ha, ddb, DDB_TYPE, DDB_TYPE_UNUSED); - spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); CLEAR_DDB(ddb, asd_ha); - spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); } static inline void asd_set_ddb_type(struct domain_device *dev) @@ -320,8 +312,11 @@ static int asd_init_sata_pm_ddb(struct domain_device *dev) int asd_dev_found(struct domain_device *dev) { + unsigned long flags; int res = 0; + struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; + spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); switch (dev->dev_type) { case SATA_PM: res = asd_init_sata_pm_ddb(dev); @@ -335,14 +330,18 @@ int asd_dev_found(struct domain_device *dev) else res = asd_init_initiator_ddb(dev); } + spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); + return res; } void asd_dev_gone(struct domain_device *dev) { int ddb, sister_ddb; + unsigned long flags; struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; + spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); ddb = (int) (unsigned long) dev->lldd_dev; sister_ddb = asd_ddbsite_read_word(asd_ha, ddb, SISTER_DDB); @@ -350,4 +349,5 @@ void asd_dev_gone(struct domain_device *dev) asd_free_ddb(asd_ha, sister_ddb); asd_free_ddb(asd_ha, ddb); dev->lldd_dev = NULL; + spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); } diff --git a/drivers/scsi/aic94xx/aic94xx_dump.c b/drivers/scsi/aic94xx/aic94xx_dump.c index e6ade5996d9592ebaf5ab6454d59aac8cfb965a9..6bd8e3059d27d8a551b823c7dc54007f956d3380 100644 --- a/drivers/scsi/aic94xx/aic94xx_dump.c +++ b/drivers/scsi/aic94xx/aic94xx_dump.c @@ -556,7 +556,7 @@ static void asd_dump_lseq_state(struct asd_ha_struct *asd_ha, int lseq) PRINT_LMIP_word(asd_ha, lseq, Q_TGTXFR_TAIL); PRINT_LMIP_byte(asd_ha, lseq, LINK_NUMBER); PRINT_LMIP_byte(asd_ha, lseq, SCRATCH_FLAGS); - PRINT_LMIP_qword(asd_ha, lseq, CONNECTION_STATE); + PRINT_LMIP_dword(asd_ha, lseq, CONNECTION_STATE); PRINT_LMIP_word(asd_ha, lseq, CONCTL); PRINT_LMIP_byte(asd_ha, lseq, CONSTAT); PRINT_LMIP_byte(asd_ha, lseq, CONNECTION_MODES); diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index fbc82b00a418cf8ff6d43603a36ca75f2a83fa81..bc7744e35ad0369a27d7e3b38a3e0048bf047ce2 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -38,7 +38,7 @@ #include "aic94xx_seq.h" /* The format is "version.release.patchlevel" */ -#define ASD_DRIVER_VERSION "1.0.2" +#define ASD_DRIVER_VERSION "1.0.3" static int use_msi = 0; module_param_named(use_msi, use_msi, int, S_IRUGO); @@ -57,6 +57,8 @@ MODULE_PARM_DESC(collector, "\n" char sas_addr_str[2*SAS_ADDR_SIZE + 1] = ""; static struct scsi_transport_template *aic94xx_transport_template; +static int asd_scan_finished(struct Scsi_Host *, unsigned long); +static void asd_scan_start(struct Scsi_Host *); static struct scsi_host_template aic94xx_sht = { .module = THIS_MODULE, @@ -66,6 +68,8 @@ static struct scsi_host_template aic94xx_sht = { .target_alloc = sas_target_alloc, .slave_configure = sas_slave_configure, .slave_destroy = sas_slave_destroy, + .scan_finished = asd_scan_finished, + .scan_start = asd_scan_start, .change_queue_depth = sas_change_queue_depth, .change_queue_type = sas_change_queue_type, .bios_param = sas_bios_param, @@ -75,6 +79,8 @@ static struct scsi_host_template aic94xx_sht = { .sg_tablesize = SG_ALL, .max_sectors = SCSI_DEFAULT_MAX_SECTORS, .use_clustering = ENABLE_CLUSTERING, + .eh_device_reset_handler = sas_eh_device_reset_handler, + .eh_bus_reset_handler = sas_eh_bus_reset_handler, }; static int __devinit asd_map_memio(struct asd_ha_struct *asd_ha) @@ -234,7 +240,7 @@ static int __devinit asd_common_setup(struct asd_ha_struct *asd_ha) } /* Provide some sane default values. */ asd_ha->hw_prof.max_scbs = 512; - asd_ha->hw_prof.max_ddbs = 128; + asd_ha->hw_prof.max_ddbs = ASD_MAX_DDBS; asd_ha->hw_prof.num_phys = ASD_MAX_PHYS; /* All phys are enabled, by default. */ asd_ha->hw_prof.enabled_phys = 0xFF; @@ -526,6 +532,7 @@ static int asd_register_sas_ha(struct asd_ha_struct *asd_ha) asd_ha->sas_ha.num_phys= ASD_MAX_PHYS; asd_ha->sas_ha.lldd_queue_size = asd_ha->seq.can_queue; + asd_ha->sas_ha.lldd_max_execute_num = lldd_max_execute_num; return sas_register_ha(&asd_ha->sas_ha); } @@ -671,21 +678,10 @@ static int __devinit asd_pci_probe(struct pci_dev *dev, if (err) goto Err_reg_sas; - err = asd_enable_phys(asd_ha, asd_ha->hw_prof.enabled_phys); - if (err) { - asd_printk("coudln't enable phys, err:%d\n", err); - goto Err_en_phys; - } - ASD_DPRINTK("enabled phys\n"); - /* give the phy enabling interrupt event time to come in (1s - * is empirically about all it takes) */ - ssleep(1); - /* Wait for discovery to finish */ - scsi_flush_work(asd_ha->sas_ha.core.shost); + scsi_scan_host(shost); return 0; -Err_en_phys: - asd_unregister_sas_ha(asd_ha); + Err_reg_sas: asd_remove_dev_attrs(asd_ha); Err_dev_attrs: @@ -778,6 +774,28 @@ static void __devexit asd_pci_remove(struct pci_dev *dev) return; } +static void asd_scan_start(struct Scsi_Host *shost) +{ + struct asd_ha_struct *asd_ha; + int err; + + asd_ha = SHOST_TO_SAS_HA(shost)->lldd_ha; + err = asd_enable_phys(asd_ha, asd_ha->hw_prof.enabled_phys); + if (err) + asd_printk("Couldn't enable phys, err:%d\n", err); +} + +static int asd_scan_finished(struct Scsi_Host *shost, unsigned long time) +{ + /* give the phy enabling interrupt event time to come in (1s + * is empirically about all it takes) */ + if (time < HZ) + return 0; + /* Wait for discovery to finish */ + scsi_flush_work(shost); + return 1; +} + static ssize_t asd_version_show(struct device_driver *driver, char *buf) { return snprintf(buf, PAGE_SIZE, "%s\n", ASD_DRIVER_VERSION); @@ -885,6 +903,7 @@ static void __exit aic94xx_exit(void) asd_remove_driver_attrs(&aic94xx_pci_driver.driver); pci_unregister_driver(&aic94xx_pci_driver); sas_release_transport(aic94xx_transport_template); + asd_release_firmware(); asd_destroy_global_caches(); asd_printk("%s version %s unloaded\n", ASD_DRIVER_DESCRIPTION, ASD_DRIVER_VERSION); diff --git a/drivers/scsi/aic94xx/aic94xx_reg_def.h b/drivers/scsi/aic94xx/aic94xx_reg_def.h index a11f4e6d8bd93698260a7c574deda49bfb325d5e..a43e8cdf4ee4fce658899fc5713a1d77219412b4 100644 --- a/drivers/scsi/aic94xx/aic94xx_reg_def.h +++ b/drivers/scsi/aic94xx/aic94xx_reg_def.h @@ -2226,9 +2226,10 @@ #define LmSEQ_SAS_RESET_MODE(LinkNum) (LmSCRATCH(LinkNum) + 0x0074) #define LmSEQ_LINK_RESET_RETRY_COUNT(LinkNum) (LmSCRATCH(LinkNum) + 0x0075) #define LmSEQ_NUM_LINK_RESET_RETRIES(LinkNum) (LmSCRATCH(LinkNum) + 0x0076) -#define LmSEQ_OOB_INT_ENABLES(LinkNum) (LmSCRATCH(LinkNum) + 0x007A) +#define LmSEQ_OOB_INT_ENABLES(LinkNum) (LmSCRATCH(LinkNum) + 0x0078) +#define LmSEQ_NOTIFY_TIMER_DOWN_COUNT(LinkNum) (LmSCRATCH(LinkNum) + 0x007A) #define LmSEQ_NOTIFY_TIMER_TIMEOUT(LinkNum) (LmSCRATCH(LinkNum) + 0x007C) -#define LmSEQ_NOTIFY_TIMER_DOWN_COUNT(LinkNum) (LmSCRATCH(LinkNum) + 0x007E) +#define LmSEQ_NOTIFY_TIMER_INITIAL_COUNT(LinkNum) (LmSCRATCH(LinkNum) + 0x007E) /* Mode dependent scratch page 1, mode 0 and mode 1 */ #define LmSEQ_SG_LIST_PTR_ADDR0(LinkNum) (LmSCRATCH(LinkNum) + 0x0020) diff --git a/drivers/scsi/aic94xx/aic94xx_sas.h b/drivers/scsi/aic94xx/aic94xx_sas.h index 9050e93bfd5e9be8bf9dbe49843b71315058c1d3..fa7c5290257d708f52ba5b1053bd3d8412c2a21b 100644 --- a/drivers/scsi/aic94xx/aic94xx_sas.h +++ b/drivers/scsi/aic94xx/aic94xx_sas.h @@ -34,6 +34,7 @@ * domain that this sequencer can maintain low-level connections for * us. They are be 64 bytes. */ +#define ASD_MAX_DDBS 128 struct asd_ddb_ssp_smp_target_port { u8 conn_type; /* byte 0 */ diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c index 75ed6b0569d1ad9243e8be51e265f7df144abbd6..8f43ff772f2378290d99af151a409b7dd19d6792 100644 --- a/drivers/scsi/aic94xx/aic94xx_scb.c +++ b/drivers/scsi/aic94xx/aic94xx_scb.c @@ -413,40 +413,6 @@ void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id) } } -/* hard reset a phy later */ -static void do_phy_reset_later(struct work_struct *work) -{ - struct sas_phy *sas_phy = - container_of(work, struct sas_phy, reset_work); - int error; - - ASD_DPRINTK("%s: About to hard reset phy %d\n", __FUNCTION__, - sas_phy->identify.phy_identifier); - /* Reset device port */ - error = sas_phy_reset(sas_phy, 1); - if (error) - ASD_DPRINTK("%s: Hard reset of phy %d failed (%d).\n", - __FUNCTION__, sas_phy->identify.phy_identifier, error); -} - -static void phy_reset_later(struct sas_phy *sas_phy, struct Scsi_Host *shost) -{ - INIT_WORK(&sas_phy->reset_work, do_phy_reset_later); - queue_work(shost->work_q, &sas_phy->reset_work); -} - -/* start up the ABORT TASK tmf... */ -static void task_kill_later(struct asd_ascb *ascb) -{ - struct asd_ha_struct *asd_ha = ascb->ha; - struct sas_ha_struct *sas_ha = &asd_ha->sas_ha; - struct Scsi_Host *shost = sas_ha->core.shost; - struct sas_task *task = ascb->uldd_task; - - INIT_WORK(&task->abort_work, sas_task_abort); - queue_work(shost->work_q, &task->abort_work); -} - static void escb_tasklet_complete(struct asd_ascb *ascb, struct done_list_struct *dl) { @@ -479,26 +445,55 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, case REQ_TASK_ABORT: { struct asd_ascb *a, *b; u16 tc_abort; + struct domain_device *failed_dev = NULL; + + ASD_DPRINTK("%s: REQ_TASK_ABORT, reason=0x%X\n", + __FUNCTION__, dl->status_block[3]); + /* + * Find the task that caused the abort and abort it first. + * The sequencer won't put anything on the done list until + * that happens. + */ tc_abort = *((u16*)(&dl->status_block[1])); tc_abort = le16_to_cpu(tc_abort); - ASD_DPRINTK("%s: REQ_TASK_ABORT, reason=0x%X\n", - __FUNCTION__, dl->status_block[3]); + list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) { + struct sas_task *task = ascb->uldd_task; - /* Find the pending task and abort it. */ - list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) - if (a->tc_index == tc_abort) { - task_kill_later(a); + if (task && a->tc_index == tc_abort) { + failed_dev = task->dev; + sas_task_abort(task); break; } + } + + if (!failed_dev) { + ASD_DPRINTK("%s: Can't find task (tc=%d) to abort!\n", + __FUNCTION__, tc_abort); + goto out; + } + + /* + * Now abort everything else for that device (hba?) so + * that the EH will wake up and do something. + */ + list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) { + struct sas_task *task = ascb->uldd_task; + + if (task && + task->dev == failed_dev && + a->tc_index != tc_abort) + sas_task_abort(task); + } + goto out; } case REQ_DEVICE_RESET: { - struct Scsi_Host *shost = sas_ha->core.shost; - struct sas_phy *dev_phy; struct asd_ascb *a; u16 conn_handle; + unsigned long flags; + struct sas_task *last_dev_task = NULL; conn_handle = *((u16*)(&dl->status_block[1])); conn_handle = le16_to_cpu(conn_handle); @@ -506,32 +501,47 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, ASD_DPRINTK("%s: REQ_DEVICE_RESET, reason=0x%X\n", __FUNCTION__, dl->status_block[3]); - /* Kill all pending tasks and reset the device */ - dev_phy = NULL; + /* Find the last pending task for the device... */ list_for_each_entry(a, &asd_ha->seq.pend_q, list) { - struct sas_task *task; - struct domain_device *dev; u16 x; + struct domain_device *dev; + struct sas_task *task = a->uldd_task; - task = a->uldd_task; if (!task) continue; dev = task->dev; x = (unsigned long)dev->lldd_dev; - if (x == conn_handle) { - dev_phy = dev->port->phy; - task_kill_later(a); - } + if (x == conn_handle) + last_dev_task = task; } - /* Reset device port */ - if (!dev_phy) { - ASD_DPRINTK("%s: No pending commands; can't reset.\n", - __FUNCTION__); + if (!last_dev_task) { + ASD_DPRINTK("%s: Device reset for idle device %d?\n", + __FUNCTION__, conn_handle); goto out; } - phy_reset_later(dev_phy, shost); + + /* ...and set the reset flag */ + spin_lock_irqsave(&last_dev_task->task_state_lock, flags); + last_dev_task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; + spin_unlock_irqrestore(&last_dev_task->task_state_lock, flags); + + /* Kill all pending tasks for the device */ + list_for_each_entry(a, &asd_ha->seq.pend_q, list) { + u16 x; + struct domain_device *dev; + struct sas_task *task = a->uldd_task; + + if (!task) + continue; + dev = task->dev; + + x = (unsigned long)dev->lldd_dev; + if (x == conn_handle) + sas_task_abort(task); + } + goto out; } case SIGNAL_NCQ_ERROR: diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c index e5a0ec37e9544caf9703be97d618e7ab2a7c23be..5b0932f6147389c5c0919a799036b75b2b69b3ed 100644 --- a/drivers/scsi/aic94xx/aic94xx_sds.c +++ b/drivers/scsi/aic94xx/aic94xx_sds.c @@ -427,7 +427,7 @@ struct asd_manuf_sec { struct asd_manuf_phy_desc { u8 state; /* low 4 bits */ -#define MS_PHY_STATE_ENABLEABLE 0 +#define MS_PHY_STATE_ENABLED 0 #define MS_PHY_STATE_REPORTED 1 #define MS_PHY_STATE_HIDDEN 2 u8 phy_id; @@ -756,11 +756,11 @@ static void *asd_find_ll_by_id(void * const start, const u8 id0, const u8 id1) * * HIDDEN phys do not count in the total count. REPORTED phys cannot * be enabled but are reported and counted towards the total. - * ENEBLEABLE phys are enabled by default and count towards the total. + * ENABLED phys are enabled by default and count towards the total. * The absolute total phy number is ASD_MAX_PHYS. hw_prof->num_phys * merely specifies the number of phys the host adapter decided to * report. E.g., it is possible for phys 0, 1 and 2 to be HIDDEN, - * phys 3, 4 and 5 to be REPORTED and phys 6 and 7 to be ENEBLEABLE. + * phys 3, 4 and 5 to be REPORTED and phys 6 and 7 to be ENABLED. * In this case ASD_MAX_PHYS is 8, hw_prof->num_phys is 5, and only 2 * are actually enabled (enabled by default, max number of phys * enableable in this case). @@ -816,8 +816,8 @@ static int asd_ms_get_phy_params(struct asd_ha_struct *asd_ha, asd_ha->hw_prof.enabled_phys &= ~(1 << i); rep_phys++; continue; - case MS_PHY_STATE_ENABLEABLE: - ASD_DPRINTK("ms: phy%d: ENEBLEABLE\n", i); + case MS_PHY_STATE_ENABLED: + ASD_DPRINTK("ms: phy%d: ENABLED\n", i); asd_ha->hw_prof.enabled_phys |= (1 << i); en_phys++; break; diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c index 845112539d05bd02617e3abae81e83a80ab75a35..eae7a247becebf8d6f512dcd7fba384aa5aa7957 100644 --- a/drivers/scsi/aic94xx/aic94xx_seq.c +++ b/drivers/scsi/aic94xx/aic94xx_seq.c @@ -810,6 +810,8 @@ static void asd_init_lseq_mdp(struct asd_ha_struct *asd_ha, int lseq) /* No delay for the first NOTIFY to be sent to the attached target. */ asd_write_reg_word(asd_ha, LmSEQ_NOTIFY_TIMER_DOWN_COUNT(lseq), ASD_NOTIFY_DOWN_COUNT); + asd_write_reg_word(asd_ha, LmSEQ_NOTIFY_TIMER_INITIAL_COUNT(lseq), + ASD_NOTIFY_DOWN_COUNT); /* LSEQ Mode dependent, mode 0 and 1, page 1 setup. */ for (i = 0; i < 2; i++) { @@ -907,6 +909,16 @@ static void asd_init_scb_sites(struct asd_ha_struct *asd_ha) for (i = 0; i < ASD_SCB_SIZE; i += 4) asd_scbsite_write_dword(asd_ha, site_no, i, 0); + /* Initialize SCB Site Opcode field to invalid. */ + asd_scbsite_write_byte(asd_ha, site_no, + offsetof(struct scb_header, opcode), + 0xFF); + + /* Initialize SCB Site Flags field to mean a response + * frame has been received. This means inadvertent + * frames received to be dropped. */ + asd_scbsite_write_byte(asd_ha, site_no, 0x49, 0x01); + /* Workaround needed by SEQ to fix a SATA issue is to exclude * certain SCB sites from the free list. */ if (!SCB_SITE_VALID(site_no)) @@ -922,16 +934,6 @@ static void asd_init_scb_sites(struct asd_ha_struct *asd_ha) /* Q_NEXT field of the last SCB is invalidated. */ asd_scbsite_write_word(asd_ha, site_no, 0, first_scb_site_no); - /* Initialize SCB Site Opcode field to invalid. */ - asd_scbsite_write_byte(asd_ha, site_no, - offsetof(struct scb_header, opcode), - 0xFF); - - /* Initialize SCB Site Flags field to mean a response - * frame has been received. This means inadvertent - * frames received to be dropped. */ - asd_scbsite_write_byte(asd_ha, site_no, 0x49, 0x01); - first_scb_site_no = site_no; max_scbs++; } @@ -1173,6 +1175,16 @@ static void asd_init_ddb_0(struct asd_ha_struct *asd_ha) set_bit(0, asd_ha->hw_prof.ddb_bitmap); } +static void asd_seq_init_ddb_sites(struct asd_ha_struct *asd_ha) +{ + unsigned int i; + unsigned int ddb_site; + + for (ddb_site = 0 ; ddb_site < ASD_MAX_DDBS; ddb_site++) + for (i = 0; i < sizeof(struct asd_ddb_ssp_smp_target_port); i+= 4) + asd_ddbsite_write_dword(asd_ha, ddb_site, i, 0); +} + /** * asd_seq_setup_seqs -- setup and initialize central and link sequencers * @asd_ha: pointer to host adapter structure @@ -1182,6 +1194,9 @@ static void asd_seq_setup_seqs(struct asd_ha_struct *asd_ha) int lseq; u8 lseq_mask; + /* Initialize DDB sites */ + asd_seq_init_ddb_sites(asd_ha); + /* Initialize SCB sites. Done first to compute some values which * the rest of the init code depends on. */ asd_init_scb_sites(asd_ha); @@ -1232,6 +1247,13 @@ static int asd_seq_start_lseq(struct asd_ha_struct *asd_ha, int lseq) return asd_seq_unpause_lseq(asd_ha, lseq); } +int asd_release_firmware(void) +{ + if (sequencer_fw) + release_firmware(sequencer_fw); + return 0; +} + static int asd_request_firmware(struct asd_ha_struct *asd_ha) { int err, i; @@ -1375,7 +1397,9 @@ void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy) u8 phy_is_up; u8 mask; int i, err; + unsigned long flags; + spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); for_each_phy(phy_mask, mask, i) asd_ddbsite_write_byte(asd_ha, 0, offsetof(struct asd_ddb_seq_shared, @@ -1395,6 +1419,7 @@ void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy) break; } } + spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); if (err) asd_printk("couldn't update DDB 0:error:%d\n", err); diff --git a/drivers/scsi/aic94xx/aic94xx_seq.h b/drivers/scsi/aic94xx/aic94xx_seq.h index 9e715e5496af93b4a585b9764a645d7dcbd2db86..9437ff0ae3a4f6ce9852c8c08a2b48588db3ea2b 100644 --- a/drivers/scsi/aic94xx/aic94xx_seq.h +++ b/drivers/scsi/aic94xx/aic94xx_seq.h @@ -63,6 +63,7 @@ int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask); int asd_unpause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask); int asd_init_seqs(struct asd_ha_struct *asd_ha); int asd_start_seqs(struct asd_ha_struct *asd_ha); +int asd_release_firmware(void); void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy); #endif diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c index d202ed5a6709560b5793bcb53c6314b1ea3b967d..e2ad5bed94035c0dd594c237e0c59a8dba3dd1c1 100644 --- a/drivers/scsi/aic94xx/aic94xx_task.c +++ b/drivers/scsi/aic94xx/aic94xx_task.c @@ -349,6 +349,7 @@ static void asd_task_tasklet_complete(struct asd_ascb *ascb, spin_lock_irqsave(&task->task_state_lock, flags); task->task_state_flags &= ~SAS_TASK_STATE_PENDING; + task->task_state_flags &= ~SAS_TASK_AT_INITIATOR; task->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((task->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&task->task_state_lock, flags); @@ -557,6 +558,7 @@ int asd_execute_task(struct sas_task *task, const int num, struct sas_task *t = task; struct asd_ascb *ascb = NULL, *a; struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha; + unsigned long flags; res = asd_can_queue(asd_ha, num); if (res) @@ -599,6 +601,10 @@ int asd_execute_task(struct sas_task *task, const int num, } if (res) goto out_err_unmap; + + spin_lock_irqsave(&t->task_state_lock, flags); + t->task_state_flags |= SAS_TASK_AT_INITIATOR; + spin_unlock_irqrestore(&t->task_state_lock, flags); } list_del_init(&alist); @@ -617,6 +623,9 @@ int asd_execute_task(struct sas_task *task, const int num, if (a == b) break; t = a->uldd_task; + spin_lock_irqsave(&t->task_state_lock, flags); + t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; + spin_unlock_irqrestore(&t->task_state_lock, flags); switch (t->task_proto) { case SATA_PROTO: case SAS_PROTO_STP: diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c index 61234384503b6ac28bb82216d26cd474a84009e1..9a14a6d9727548039051e3999f0a8817e076cfce 100644 --- a/drivers/scsi/aic94xx/aic94xx_tmf.c +++ b/drivers/scsi/aic94xx/aic94xx_tmf.c @@ -566,9 +566,7 @@ static int asd_initiate_ssp_tmf(struct domain_device *dev, u8 *lun, res = TMF_RESP_FUNC_ESUPP; break; default: - ASD_DPRINTK("%s: converting result 0x%x to TMF_RESP_FUNC_FAILED\n", - __FUNCTION__, res); - res = TMF_RESP_FUNC_FAILED; + /* Allow TMF response codes to propagate upwards */ break; } out_err: diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 821386c7b57639e8c1ad5098a3de4635a6a57429..95045e33710d488b758374d17956f0f4074b837a 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -595,10 +595,8 @@ static int ipr_save_pcix_cmd_reg(struct ipr_ioa_cfg *ioa_cfg) { int pcix_cmd_reg = pci_find_capability(ioa_cfg->pdev, PCI_CAP_ID_PCIX); - if (pcix_cmd_reg == 0) { - dev_err(&ioa_cfg->pdev->dev, "Failed to save PCI-X command register\n"); - return -EIO; - } + if (pcix_cmd_reg == 0) + return 0; if (pci_read_config_word(ioa_cfg->pdev, pcix_cmd_reg + PCI_X_CMD, &ioa_cfg->saved_pcix_cmd_reg) != PCIBIOS_SUCCESSFUL) { @@ -627,10 +625,6 @@ static int ipr_set_pcix_cmd_reg(struct ipr_ioa_cfg *ioa_cfg) dev_err(&ioa_cfg->pdev->dev, "Failed to setup PCI-X command register\n"); return -EIO; } - } else { - dev_err(&ioa_cfg->pdev->dev, - "Failed to setup PCI-X command register\n"); - return -EIO; } return 0; @@ -6314,7 +6308,6 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) int rc; ENTER; - pci_unblock_user_cfg_access(ioa_cfg->pdev); rc = pci_restore_state(ioa_cfg->pdev); if (rc != PCIBIOS_SUCCESSFUL) { @@ -6354,6 +6347,24 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) return IPR_RC_JOB_CONTINUE; } +/** + * ipr_reset_bist_done - BIST has completed on the adapter. + * @ipr_cmd: ipr command struct + * + * Description: Unblock config space and resume the reset process. + * + * Return value: + * IPR_RC_JOB_CONTINUE + **/ +static int ipr_reset_bist_done(struct ipr_cmnd *ipr_cmd) +{ + ENTER; + pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev); + ipr_cmd->job_step = ipr_reset_restore_cfg_space; + LEAVE; + return IPR_RC_JOB_CONTINUE; +} + /** * ipr_reset_start_bist - Run BIST on the adapter. * @ipr_cmd: ipr command struct @@ -6376,7 +6387,7 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd) ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); rc = IPR_RC_JOB_CONTINUE; } else { - ipr_cmd->job_step = ipr_reset_restore_cfg_space; + ipr_cmd->job_step = ipr_reset_bist_done; ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT); rc = IPR_RC_JOB_RETURN; } @@ -7166,9 +7177,6 @@ ipr_get_chip_cfg(const struct pci_device_id *dev_id) { int i; - if (dev_id->driver_data) - return (const struct ipr_chip_cfg_t *)dev_id->driver_data; - for (i = 0; i < ARRAY_SIZE(ipr_chip); i++) if (ipr_chip[i].vendor == dev_id->vendor && ipr_chip[i].device == dev_id->device) @@ -7517,62 +7525,43 @@ static void ipr_shutdown(struct pci_dev *pdev) static struct pci_device_id ipr_pci_table[] __devinitdata = { { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5702, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5702, 0, 0, 0 }, { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5703, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5703, 0, 0, 0 }, { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573D, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573D, 0, 0, 0 }, { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573E, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573E, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571B, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571B, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572E, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572E, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571A, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571A, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575B, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575B, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571E, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571E, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, 0, 0, 0 }, { } }; MODULE_DEVICE_TABLE(pci, ipr_pci_table); diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 9f62a1d4d5118b0e197d15ea44d2ba07ff5f9424..88f285de97bb22ab45c607c8026da1dd0438830e 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -37,8 +37,8 @@ /* * Literals */ -#define IPR_DRIVER_VERSION "2.3.0" -#define IPR_DRIVER_DATE "(November 8, 2006)" +#define IPR_DRIVER_VERSION "2.3.1" +#define IPR_DRIVER_DATE "(January 23, 2007)" /* * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c index f0871c3ac3d98d279a7d465c487b3b7bd70da65d..2aae1b081fcf405ee864f0284effe43ff3e45aec 100644 --- a/drivers/scsi/lasi700.c +++ b/drivers/scsi/lasi700.c @@ -123,6 +123,7 @@ lasi700_probe(struct parisc_device *dev) hostdata->force_le_on_be = 0; hostdata->chip710 = 1; hostdata->dmode_extra = DMODE_FC2; + hostdata->burst_length = 8; } host = NCR_700_detect(&lasi700_template, hostdata, &dev->dev); diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index fb7df7b758112b59359e6bc2d37b8afe11f18c66..a65598b1e5363b386c6a235f8d7c3e61ffe834bb 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -548,7 +548,7 @@ int sas_discover_sata(struct domain_device *dev) res = sas_notify_lldd_dev_found(dev); if (res) - return res; + goto out_err2; switch (dev->dev_type) { case SATA_DEV: @@ -560,11 +560,23 @@ int sas_discover_sata(struct domain_device *dev) default: break; } + if (res) + goto out_err; sas_notify_lldd_dev_gone(dev); - if (!res) { - sas_notify_lldd_dev_found(dev); - } + res = sas_notify_lldd_dev_found(dev); + if (res) + goto out_err2; + + res = sas_rphy_add(dev->rphy); + if (res) + goto out_err; + + return res; + +out_err: + sas_notify_lldd_dev_gone(dev); +out_err2: return res; } @@ -580,21 +592,17 @@ int sas_discover_end_dev(struct domain_device *dev) res = sas_notify_lldd_dev_found(dev); if (res) - return res; + goto out_err2; res = sas_rphy_add(dev->rphy); if (res) goto out_err; - /* do this to get the end device port attributes which will have - * been scanned in sas_rphy_add */ - sas_notify_lldd_dev_gone(dev); - sas_notify_lldd_dev_found(dev); - return 0; out_err: sas_notify_lldd_dev_gone(dev); +out_err2: return res; } @@ -649,6 +657,7 @@ void sas_unregister_domain_devices(struct asd_sas_port *port) */ static void sas_discover_domain(struct work_struct *work) { + struct domain_device *dev; int error = 0; struct sas_discovery_event *ev = container_of(work, struct sas_discovery_event, work); @@ -658,35 +667,42 @@ static void sas_discover_domain(struct work_struct *work) &port->disc.pending); if (port->port_dev) - return ; - else { - error = sas_get_port_device(port); - if (error) - return; - } + return; + + error = sas_get_port_device(port); + if (error) + return; + dev = port->port_dev; SAS_DPRINTK("DOING DISCOVERY on port %d, pid:%d\n", port->id, current->pid); - switch (port->port_dev->dev_type) { + switch (dev->dev_type) { case SAS_END_DEV: - error = sas_discover_end_dev(port->port_dev); + error = sas_discover_end_dev(dev); break; case EDGE_DEV: case FANOUT_DEV: - error = sas_discover_root_expander(port->port_dev); + error = sas_discover_root_expander(dev); break; case SATA_DEV: case SATA_PM: - error = sas_discover_sata(port->port_dev); + error = sas_discover_sata(dev); break; default: - SAS_DPRINTK("unhandled device %d\n", port->port_dev->dev_type); + SAS_DPRINTK("unhandled device %d\n", dev->dev_type); break; } if (error) { - kfree(port->port_dev); /* not kobject_register-ed yet */ + sas_rphy_free(dev->rphy); + dev->rphy = NULL; + + spin_lock(&port->dev_list_lock); + list_del_init(&dev->dev_list_node); + spin_unlock(&port->dev_list_lock); + + kfree(dev); /* not kobject_register-ed yet */ port->port_dev = NULL; } @@ -726,7 +742,7 @@ int sas_discover_event(struct asd_sas_port *port, enum discover_event ev) BUG_ON(ev >= DISC_NUM_EVENTS); sas_queue_event(ev, &disc->disc_event_lock, &disc->pending, - &disc->disc_work[ev].work, port->ha->core.shost); + &disc->disc_work[ev].work, port->ha); return 0; } diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c index d83392ee6823f09dab380b1008d2e2bbbf0031ba..9db30fb5caf2e1be01aa27b5433aa78d63889eb4 100644 --- a/drivers/scsi/libsas/sas_event.c +++ b/drivers/scsi/libsas/sas_event.c @@ -31,7 +31,7 @@ static void notify_ha_event(struct sas_ha_struct *sas_ha, enum ha_event event) BUG_ON(event >= HA_NUM_EVENTS); sas_queue_event(event, &sas_ha->event_lock, &sas_ha->pending, - &sas_ha->ha_events[event].work, sas_ha->core.shost); + &sas_ha->ha_events[event].work, sas_ha); } static void notify_port_event(struct asd_sas_phy *phy, enum port_event event) @@ -41,7 +41,7 @@ static void notify_port_event(struct asd_sas_phy *phy, enum port_event event) BUG_ON(event >= PORT_NUM_EVENTS); sas_queue_event(event, &ha->event_lock, &phy->port_events_pending, - &phy->port_events[event].work, ha->core.shost); + &phy->port_events[event].work, ha); } static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) @@ -51,7 +51,7 @@ static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) BUG_ON(event >= PHY_NUM_EVENTS); sas_queue_event(event, &ha->event_lock, &phy->phy_events_pending, - &phy->phy_events[event].work, ha->core.shost); + &phy->phy_events[event].work, ha); } int sas_init_events(struct sas_ha_struct *sas_ha) diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index d31e6fa466f79668f151c0d0c301bbccf27c848f..dc70c180e1155ee98c88ab0e7b03975190145d87 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -667,8 +667,9 @@ static struct domain_device *sas_ex_discover_end_dev( return child; out_list_del: + sas_rphy_free(child->rphy); + child->rphy = NULL; list_del(&child->dev_list_node); - sas_rphy_free(rphy); out_free: sas_port_delete(phy->port); out_err: @@ -677,6 +678,29 @@ static struct domain_device *sas_ex_discover_end_dev( return NULL; } +/* See if this phy is part of a wide port */ +static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id) +{ + struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id]; + int i; + + for (i = 0; i < parent->ex_dev.num_phys; i++) { + struct ex_phy *ephy = &parent->ex_dev.ex_phy[i]; + + if (ephy == phy) + continue; + + if (!memcmp(phy->attached_sas_addr, ephy->attached_sas_addr, + SAS_ADDR_SIZE) && ephy->port) { + sas_port_add_phy(ephy->port, phy->phy); + phy->phy_state = PHY_DEVICE_DISCOVERED; + return 0; + } + } + + return -ENODEV; +} + static struct domain_device *sas_ex_discover_expander( struct domain_device *parent, int phy_id) { @@ -809,6 +833,13 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) return res; } + res = sas_ex_join_wide_port(dev, phy_id); + if (!res) { + SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n", + phy_id, SAS_ADDR(ex_phy->attached_sas_addr)); + return res; + } + switch (ex_phy->attached_dev_type) { case SAS_END_DEV: child = sas_ex_discover_end_dev(dev, phy_id); @@ -1431,14 +1462,23 @@ int sas_discover_root_expander(struct domain_device *dev) int res; struct sas_expander_device *ex = rphy_to_expander_device(dev->rphy); - sas_rphy_add(dev->rphy); + res = sas_rphy_add(dev->rphy); + if (res) + goto out_err; ex->level = dev->port->disc.max_level; /* 0 */ res = sas_discover_expander(dev); - if (!res) - sas_ex_bfs_disc(dev->port); + if (res) + goto out_err2; + + sas_ex_bfs_disc(dev->port); return res; + +out_err2: + sas_rphy_remove(dev->rphy); +out_err: + return res; } /* ---------- Domain revalidation ---------- */ diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index 2f0c07fc3f48c1da732c37e4862727b976595432..965698c8b7bff407cf2157922b93e7895ede92e7 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c @@ -87,6 +87,9 @@ int sas_register_ha(struct sas_ha_struct *sas_ha) else if (sas_ha->lldd_queue_size == -1) sas_ha->lldd_queue_size = 128; /* Sanity */ + sas_ha->state = SAS_HA_REGISTERED; + spin_lock_init(&sas_ha->state_lock); + error = sas_register_phys(sas_ha); if (error) { printk(KERN_NOTICE "couldn't register sas phys:%d\n", error); @@ -127,12 +130,22 @@ int sas_register_ha(struct sas_ha_struct *sas_ha) int sas_unregister_ha(struct sas_ha_struct *sas_ha) { + unsigned long flags; + + /* Set the state to unregistered to avoid further + * events to be queued */ + spin_lock_irqsave(&sas_ha->state_lock, flags); + sas_ha->state = SAS_HA_UNREGISTERED; + spin_unlock_irqrestore(&sas_ha->state_lock, flags); + scsi_flush_work(sas_ha->core.shost); + + sas_unregister_ports(sas_ha); + if (sas_ha->lldd_max_execute_num > 1) { sas_shutdown_queue(sas_ha); + sas_ha->lldd_max_execute_num = 1; } - sas_unregister_ports(sas_ha); - return 0; } @@ -146,6 +159,36 @@ static int sas_get_linkerrors(struct sas_phy *phy) return sas_smp_get_phy_events(phy); } +int sas_phy_enable(struct sas_phy *phy, int enable) +{ + int ret; + enum phy_func command; + + if (enable) + command = PHY_FUNC_LINK_RESET; + else + command = PHY_FUNC_DISABLE; + + if (scsi_is_sas_phy_local(phy)) { + struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); + struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost); + struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number]; + struct sas_internal *i = + to_sas_internal(sas_ha->core.shost->transportt); + + if (!enable) { + sas_phy_disconnected(asd_phy); + sas_ha->notify_phy_event(asd_phy, PHYE_LOSS_OF_SIGNAL); + } + ret = i->dft->lldd_control_phy(asd_phy, command, NULL); + } else { + struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent); + struct domain_device *ddev = sas_find_dev_by_rphy(rphy); + ret = sas_smp_phy_control(ddev, phy->number, command, NULL); + } + return ret; +} + int sas_phy_reset(struct sas_phy *phy, int hard_reset) { int ret; @@ -172,8 +215,8 @@ int sas_phy_reset(struct sas_phy *phy, int hard_reset) return ret; } -static int sas_set_phy_speed(struct sas_phy *phy, - struct sas_phy_linkrates *rates) +int sas_set_phy_speed(struct sas_phy *phy, + struct sas_phy_linkrates *rates) { int ret; @@ -212,6 +255,7 @@ static int sas_set_phy_speed(struct sas_phy *phy, } static struct sas_function_template sft = { + .phy_enable = sas_phy_enable, .phy_reset = sas_phy_reset, .set_phy_speed = sas_set_phy_speed, .get_linkerrors = sas_get_linkerrors, diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index 137d7e496b6d99ab6d1f6c8cbac094e27d072760..a78638df2018dd50cb8fb420076052252f130ffc 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h @@ -80,7 +80,7 @@ void sas_hae_reset(struct work_struct *work); static inline void sas_queue_event(int event, spinlock_t *lock, unsigned long *pending, struct work_struct *work, - struct Scsi_Host *shost) + struct sas_ha_struct *sas_ha) { unsigned long flags; @@ -91,7 +91,12 @@ static inline void sas_queue_event(int event, spinlock_t *lock, } __set_bit(event, pending); spin_unlock_irqrestore(lock, flags); - scsi_queue_work(shost, work); + + spin_lock_irqsave(&sas_ha->state_lock, flags); + if (sas_ha->state != SAS_HA_UNREGISTERED) { + scsi_queue_work(sas_ha->core.shost, work); + } + spin_unlock_irqrestore(&sas_ha->state_lock, flags); } static inline void sas_begin_event(int event, spinlock_t *lock, diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index 971c37ceecb4a517fbba785e35b951545d4f8208..e1e2d085c920918dc508d4ec8d67dfad98095450 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c @@ -42,10 +42,11 @@ static void sas_form_port(struct asd_sas_phy *phy) struct asd_sas_port *port = phy->port; struct sas_internal *si = to_sas_internal(sas_ha->core.shost->transportt); + unsigned long flags; if (port) { if (memcmp(port->attached_sas_addr, phy->attached_sas_addr, - SAS_ADDR_SIZE) == 0) + SAS_ADDR_SIZE) != 0) sas_deform_port(phy); else { SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n", @@ -56,7 +57,7 @@ static void sas_form_port(struct asd_sas_phy *phy) } /* find a port */ - spin_lock(&sas_ha->phy_port_lock); + spin_lock_irqsave(&sas_ha->phy_port_lock, flags); for (i = 0; i < sas_ha->num_phys; i++) { port = sas_ha->sas_port[i]; spin_lock(&port->phy_list_lock); @@ -78,7 +79,7 @@ static void sas_form_port(struct asd_sas_phy *phy) if (i >= sas_ha->num_phys) { printk(KERN_NOTICE "%s: couldn't find a free port, bug?\n", __FUNCTION__); - spin_unlock(&sas_ha->phy_port_lock); + spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags); return; } @@ -105,7 +106,7 @@ static void sas_form_port(struct asd_sas_phy *phy) } else port->linkrate = max(port->linkrate, phy->linkrate); spin_unlock(&port->phy_list_lock); - spin_unlock(&sas_ha->phy_port_lock); + spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags); if (!port->port) { port->port = sas_port_alloc(phy->phy->dev.parent, port->id); @@ -137,6 +138,7 @@ void sas_deform_port(struct asd_sas_phy *phy) struct asd_sas_port *port = phy->port; struct sas_internal *si = to_sas_internal(sas_ha->core.shost->transportt); + unsigned long flags; if (!port) return; /* done by a phy event */ @@ -155,7 +157,7 @@ void sas_deform_port(struct asd_sas_phy *phy) if (si->dft->lldd_port_deformed) si->dft->lldd_port_deformed(phy); - spin_lock(&sas_ha->phy_port_lock); + spin_lock_irqsave(&sas_ha->phy_port_lock, flags); spin_lock(&port->phy_list_lock); list_del_init(&phy->port_phy_el); @@ -174,7 +176,7 @@ void sas_deform_port(struct asd_sas_phy *phy) port->phy_mask = 0; } spin_unlock(&port->phy_list_lock); - spin_unlock(&sas_ha->phy_port_lock); + spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags); return; } diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 22672d54aa2742d7c515f6c89f818b4159b49a22..897a5e2c55e438a806c6e93072547a7386922832 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -34,6 +34,7 @@ #include #include "../scsi_sas_internal.h" #include "../scsi_transport_api.h" +#include "../scsi_priv.h" #include #include @@ -130,7 +131,7 @@ static enum task_attribute sas_scsi_get_task_attr(struct scsi_cmnd *cmd) if (cmd->request && blk_rq_tagged(cmd->request)) { if (cmd->device->ordered_tags && (cmd->request->cmd_flags & REQ_HARDBARRIER)) - ta = TASK_ATTR_HOQ; + ta = TASK_ATTR_ORDERED; } return ta; } @@ -281,6 +282,7 @@ enum task_disposition { TASK_IS_ABORTED, TASK_IS_AT_LU, TASK_IS_NOT_AT_LU, + TASK_ABORT_FAILED, }; static enum task_disposition sas_scsi_find_task(struct sas_task *task) @@ -310,15 +312,6 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task) spin_unlock_irqrestore(&core->task_queue_lock, flags); } - spin_lock_irqsave(&task->task_state_lock, flags); - if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) { - spin_unlock_irqrestore(&task->task_state_lock, flags); - SAS_DPRINTK("%s: task 0x%p already aborted\n", - __FUNCTION__, task); - return TASK_IS_ABORTED; - } - spin_unlock_irqrestore(&task->task_state_lock, flags); - for (i = 0; i < 5; i++) { SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task); res = si->dft->lldd_abort_task(task); @@ -340,15 +333,21 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task) SAS_DPRINTK("%s: querying task 0x%p\n", __FUNCTION__, task); res = si->dft->lldd_query_task(task); - if (res == TMF_RESP_FUNC_SUCC) { + switch (res) { + case TMF_RESP_FUNC_SUCC: SAS_DPRINTK("%s: task 0x%p at LU\n", __FUNCTION__, task); return TASK_IS_AT_LU; - } else if (res == TMF_RESP_FUNC_COMPLETE) { + case TMF_RESP_FUNC_COMPLETE: SAS_DPRINTK("%s: task 0x%p not at LU\n", __FUNCTION__, task); return TASK_IS_NOT_AT_LU; - } + case TMF_RESP_FUNC_FAILED: + SAS_DPRINTK("%s: task 0x%p failed to abort\n", + __FUNCTION__, task); + return TASK_ABORT_FAILED; + } + } } return res; @@ -398,35 +397,113 @@ static int sas_recover_I_T(struct domain_device *dev) return res; } -void sas_scsi_recover_host(struct Scsi_Host *shost) +/* Find the sas_phy that's attached to this device */ +struct sas_phy *find_local_sas_phy(struct domain_device *dev) +{ + struct domain_device *pdev = dev->parent; + struct ex_phy *exphy = NULL; + int i; + + /* Directly attached device */ + if (!pdev) + return dev->port->phy; + + /* Otherwise look in the expander */ + for (i = 0; i < pdev->ex_dev.num_phys; i++) + if (!memcmp(dev->sas_addr, + pdev->ex_dev.ex_phy[i].attached_sas_addr, + SAS_ADDR_SIZE)) { + exphy = &pdev->ex_dev.ex_phy[i]; + break; + } + + BUG_ON(!exphy); + return exphy->phy; +} + +/* Attempt to send a LUN reset message to a device */ +int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) +{ + struct domain_device *dev = cmd_to_domain_dev(cmd); + struct sas_internal *i = + to_sas_internal(dev->port->ha->core.shost->transportt); + struct scsi_lun lun; + int res; + + int_to_scsilun(cmd->device->lun, &lun); + + if (!i->dft->lldd_lu_reset) + return FAILED; + + res = i->dft->lldd_lu_reset(dev, lun.scsi_lun); + if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE) + return SUCCESS; + + return FAILED; +} + +/* Attempt to send a phy (bus) reset */ +int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd) +{ + struct domain_device *dev = cmd_to_domain_dev(cmd); + struct sas_phy *phy = find_local_sas_phy(dev); + int res; + + res = sas_phy_reset(phy, 1); + if (res) + SAS_DPRINTK("Bus reset of %s failed 0x%x\n", + phy->dev.kobj.k_name, + res); + if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE) + return SUCCESS; + + return FAILED; +} + +/* Try to reset a device */ +static int try_to_reset_cmd_device(struct Scsi_Host *shost, + struct scsi_cmnd *cmd) +{ + int res; + + if (!shost->hostt->eh_device_reset_handler) + goto try_bus_reset; + + res = shost->hostt->eh_device_reset_handler(cmd); + if (res == SUCCESS) + return res; + +try_bus_reset: + if (shost->hostt->eh_bus_reset_handler) + return shost->hostt->eh_bus_reset_handler(cmd); + + return FAILED; +} + +static int sas_eh_handle_sas_errors(struct Scsi_Host *shost, + struct list_head *work_q, + struct list_head *done_q) { - struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); - unsigned long flags; - LIST_HEAD(error_q); struct scsi_cmnd *cmd, *n; enum task_disposition res = TASK_IS_DONE; - int tmf_resp; + int tmf_resp, need_reset; struct sas_internal *i = to_sas_internal(shost->transportt); + unsigned long flags; + struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); - spin_lock_irqsave(shost->host_lock, flags); - list_splice_init(&shost->eh_cmd_q, &error_q); - spin_unlock_irqrestore(shost->host_lock, flags); - - SAS_DPRINTK("Enter %s\n", __FUNCTION__); - - /* All tasks on this list were marked SAS_TASK_STATE_ABORTED - * by sas_scsi_timed_out() callback. - */ Again: - SAS_DPRINTK("going over list...\n"); - list_for_each_entry_safe(cmd, n, &error_q, eh_entry) { + list_for_each_entry_safe(cmd, n, work_q, eh_entry) { struct sas_task *task = TO_SAS_TASK(cmd); - list_del_init(&cmd->eh_entry); - if (!task) { - SAS_DPRINTK("%s: taskless cmd?!\n", __FUNCTION__); + if (!task) continue; - } + + list_del_init(&cmd->eh_entry); + + spin_lock_irqsave(&task->task_state_lock, flags); + need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET; + spin_unlock_irqrestore(&task->task_state_lock, flags); + SAS_DPRINTK("trying to find task 0x%p\n", task); res = sas_scsi_find_task(task); @@ -437,11 +514,15 @@ void sas_scsi_recover_host(struct Scsi_Host *shost) SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__, task); task->task_done(task); + if (need_reset) + try_to_reset_cmd_device(shost, cmd); continue; case TASK_IS_ABORTED: SAS_DPRINTK("%s: task 0x%p is aborted\n", __FUNCTION__, task); task->task_done(task); + if (need_reset) + try_to_reset_cmd_device(shost, cmd); continue; case TASK_IS_AT_LU: SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); @@ -452,11 +533,14 @@ void sas_scsi_recover_host(struct Scsi_Host *shost) SAS_ADDR(task->dev), cmd->device->lun); task->task_done(task); - sas_scsi_clear_queue_lu(&error_q, cmd); + if (need_reset) + try_to_reset_cmd_device(shost, cmd); + sas_scsi_clear_queue_lu(work_q, cmd); goto Again; } /* fallthrough */ case TASK_IS_NOT_AT_LU: + case TASK_ABORT_FAILED: SAS_DPRINTK("task 0x%p is not at LU: I_T recover\n", task); tmf_resp = sas_recover_I_T(task->dev); @@ -464,7 +548,9 @@ void sas_scsi_recover_host(struct Scsi_Host *shost) SAS_DPRINTK("I_T %016llx recovered\n", SAS_ADDR(task->dev->sas_addr)); task->task_done(task); - sas_scsi_clear_queue_I_T(&error_q, task->dev); + if (need_reset) + try_to_reset_cmd_device(shost, cmd); + sas_scsi_clear_queue_I_T(work_q, task->dev); goto Again; } /* Hammer time :-) */ @@ -477,7 +563,9 @@ void sas_scsi_recover_host(struct Scsi_Host *shost) SAS_DPRINTK("clear nexus port:%d " "succeeded\n", port->id); task->task_done(task); - sas_scsi_clear_queue_port(&error_q, + if (need_reset) + try_to_reset_cmd_device(shost, cmd); + sas_scsi_clear_queue_port(work_q, port); goto Again; } @@ -489,6 +577,8 @@ void sas_scsi_recover_host(struct Scsi_Host *shost) SAS_DPRINTK("clear nexus ha " "succeeded\n"); task->task_done(task); + if (need_reset) + try_to_reset_cmd_device(shost, cmd); goto out; } } @@ -502,20 +592,54 @@ void sas_scsi_recover_host(struct Scsi_Host *shost) cmd->device->lun); task->task_done(task); + if (need_reset) + try_to_reset_cmd_device(shost, cmd); goto clear_q; } } out: - scsi_eh_flush_done_q(&ha->eh_done_q); - SAS_DPRINTK("--- Exit %s\n", __FUNCTION__); - return; + return list_empty(work_q); clear_q: SAS_DPRINTK("--- Exit %s -- clear_q\n", __FUNCTION__); - list_for_each_entry_safe(cmd, n, &error_q, eh_entry) { + list_for_each_entry_safe(cmd, n, work_q, eh_entry) { struct sas_task *task = TO_SAS_TASK(cmd); list_del_init(&cmd->eh_entry); task->task_done(task); } + return list_empty(work_q); +} + +void sas_scsi_recover_host(struct Scsi_Host *shost) +{ + struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); + unsigned long flags; + LIST_HEAD(eh_work_q); + + spin_lock_irqsave(shost->host_lock, flags); + list_splice_init(&shost->eh_cmd_q, &eh_work_q); + spin_unlock_irqrestore(shost->host_lock, flags); + + SAS_DPRINTK("Enter %s\n", __FUNCTION__); + /* + * Deal with commands that still have SAS tasks (i.e. they didn't + * complete via the normal sas_task completion mechanism) + */ + if (sas_eh_handle_sas_errors(shost, &eh_work_q, &ha->eh_done_q)) + goto out; + + /* + * Now deal with SCSI commands that completed ok but have a an error + * code (and hopefully sense data) attached. This is roughly what + * scsi_unjam_host does, but we skip scsi_eh_abort_cmds because any + * command we see here has no sas_task and is thus unknown to the HA. + */ + if (!scsi_eh_get_sense(&eh_work_q, &ha->eh_done_q)) + scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q); + +out: + scsi_eh_flush_done_q(&ha->eh_done_q); + SAS_DPRINTK("--- Exit %s\n", __FUNCTION__); + return; } enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) @@ -524,24 +648,30 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) unsigned long flags; if (!task) { - SAS_DPRINTK("command 0x%p, task 0x%p, gone: EH_HANDLED\n", - cmd, task); - return EH_HANDLED; + cmd->timeout_per_command /= 2; + SAS_DPRINTK("command 0x%p, task 0x%p, gone: %s\n", + cmd, task, (cmd->timeout_per_command ? + "EH_RESET_TIMER" : "EH_NOT_HANDLED")); + if (!cmd->timeout_per_command) + return EH_NOT_HANDLED; + return EH_RESET_TIMER; } spin_lock_irqsave(&task->task_state_lock, flags); - if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) { - spin_unlock_irqrestore(&task->task_state_lock, flags); - SAS_DPRINTK("command 0x%p, task 0x%p, aborted by initiator: " - "EH_NOT_HANDLED\n", cmd, task); - return EH_NOT_HANDLED; - } + BUG_ON(task->task_state_flags & SAS_TASK_STATE_ABORTED); if (task->task_state_flags & SAS_TASK_STATE_DONE) { spin_unlock_irqrestore(&task->task_state_lock, flags); SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", cmd, task); return EH_HANDLED; } + if (!(task->task_state_flags & SAS_TASK_AT_INITIATOR)) { + spin_unlock_irqrestore(&task->task_state_lock, flags); + SAS_DPRINTK("command 0x%p, task 0x%p, not at initiator: " + "EH_RESET_TIMER\n", + cmd, task); + return EH_RESET_TIMER; + } task->task_state_flags |= SAS_TASK_STATE_ABORTED; spin_unlock_irqrestore(&task->task_state_lock, flags); @@ -557,8 +687,9 @@ struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy) struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); struct domain_device *found_dev = NULL; int i; + unsigned long flags; - spin_lock(&ha->phy_port_lock); + spin_lock_irqsave(&ha->phy_port_lock, flags); for (i = 0; i < ha->num_phys; i++) { struct asd_sas_port *port = ha->sas_port[i]; struct domain_device *dev; @@ -574,7 +705,7 @@ struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy) spin_unlock(&port->dev_list_lock); } found: - spin_unlock(&ha->phy_port_lock); + spin_unlock_irqrestore(&ha->phy_port_lock, flags); return found_dev; } @@ -623,6 +754,8 @@ int sas_slave_configure(struct scsi_device *scsi_dev) scsi_deactivate_tcq(scsi_dev, 1); } + scsi_dev->allow_restart = 1; + return 0; } @@ -799,46 +932,42 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha) spin_unlock_irqrestore(&core->task_queue_lock, flags); } -static int do_sas_task_abort(struct sas_task *task) +/* + * Call the LLDD task abort routine directly. This function is intended for + * use by upper layers that need to tell the LLDD to abort a task. + */ +int __sas_task_abort(struct sas_task *task) { - struct scsi_cmnd *sc = task->uldd_task; struct sas_internal *si = to_sas_internal(task->dev->port->ha->core.shost->transportt); unsigned long flags; int res; spin_lock_irqsave(&task->task_state_lock, flags); - if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { + if (task->task_state_flags & SAS_TASK_STATE_ABORTED || + task->task_state_flags & SAS_TASK_STATE_DONE) { spin_unlock_irqrestore(&task->task_state_lock, flags); - SAS_DPRINTK("%s: Task %p already aborted.\n", __FUNCTION__, + SAS_DPRINTK("%s: Task %p already finished.\n", __FUNCTION__, task); return 0; } - - task->task_state_flags |= SAS_TASK_INITIATOR_ABORTED; - if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) - task->task_state_flags |= SAS_TASK_STATE_ABORTED; + task->task_state_flags |= SAS_TASK_STATE_ABORTED; spin_unlock_irqrestore(&task->task_state_lock, flags); if (!si->dft->lldd_abort_task) return -ENODEV; res = si->dft->lldd_abort_task(task); + + spin_lock_irqsave(&task->task_state_lock, flags); if ((task->task_state_flags & SAS_TASK_STATE_DONE) || (res == TMF_RESP_FUNC_COMPLETE)) { - /* SMP commands don't have scsi_cmds(?) */ - if (!sc) { - task->task_done(task); - return 0; - } - scsi_req_abort_cmd(sc); - scsi_schedule_eh(sc->device->host); + spin_unlock_irqrestore(&task->task_state_lock, flags); + task->task_done(task); return 0; } - spin_lock_irqsave(&task->task_state_lock, flags); - task->task_state_flags &= ~SAS_TASK_INITIATOR_ABORTED; if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) task->task_state_flags &= ~SAS_TASK_STATE_ABORTED; spin_unlock_irqrestore(&task->task_state_lock, flags); @@ -846,17 +975,24 @@ static int do_sas_task_abort(struct sas_task *task) return -EAGAIN; } -void sas_task_abort(struct work_struct *work) +/* + * Tell an upper layer that it needs to initiate an abort for a given task. + * This should only ever be called by an LLDD. + */ +void sas_task_abort(struct sas_task *task) { - struct sas_task *task = - container_of(work, struct sas_task, abort_work); - int i; + struct scsi_cmnd *sc = task->uldd_task; - for (i = 0; i < 5; i++) - if (!do_sas_task_abort(task)) + /* Escape for libsas internal commands */ + if (!sc) { + if (!del_timer(&task->timer)) return; + task->timer.function(task->timer.data); + return; + } - SAS_DPRINTK("%s: Could not kill task!\n", __FUNCTION__); + scsi_req_abort_cmd(sc); + scsi_schedule_eh(sc->device->host); } EXPORT_SYMBOL_GPL(sas_queuecommand); @@ -866,5 +1002,9 @@ EXPORT_SYMBOL_GPL(sas_slave_destroy); EXPORT_SYMBOL_GPL(sas_change_queue_depth); EXPORT_SYMBOL_GPL(sas_change_queue_type); EXPORT_SYMBOL_GPL(sas_bios_param); +EXPORT_SYMBOL_GPL(__sas_task_abort); EXPORT_SYMBOL_GPL(sas_task_abort); EXPORT_SYMBOL_GPL(sas_phy_reset); +EXPORT_SYMBOL_GPL(sas_phy_enable); +EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler); +EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler); diff --git a/drivers/scsi/megaraid/mbox_defs.h b/drivers/scsi/megaraid/mbox_defs.h index 3052869f51f4fadf9eda7c923db07115748664cb..170399ef06f4ac3e7bcd5de6e343765588c6e419 100644 --- a/drivers/scsi/megaraid/mbox_defs.h +++ b/drivers/scsi/megaraid/mbox_defs.h @@ -748,7 +748,7 @@ typedef struct { /** - * private_bios_data - bios private data for boot devices + * struct private_bios_data - bios private data for boot devices * @geometry : bits 0-3 - BIOS geometry, 0x0001 - 1GB, 0x0010 - 2GB, * 0x1000 - 8GB, Others values are invalid * @unused : bits 4-7 are unused diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h index b50e27e660244ebf6e11a79adb8543557981742b..26e1e6c55654e0a71b4e272eac98ec6a43ec90fd 100644 --- a/drivers/scsi/megaraid/mega_common.h +++ b/drivers/scsi/megaraid/mega_common.h @@ -46,17 +46,17 @@ /** * scb_t - scsi command control block - * @param ccb : command control block for individual driver - * @param list : list of control blocks - * @param gp : general purpose field for LLDs - * @param sno : all SCBs have a serial number - * @param scp : associated scsi command - * @param state : current state of scb - * @param dma_dir : direction of data transfer - * @param dma_type : transfer with sg list, buffer, or no data transfer - * @param dev_channel : actual channel on the device - * @param dev_target : actual target on the device - * @param status : completion status + * @ccb : command control block for individual driver + * @list : list of control blocks + * @gp : general purpose field for LLDs + * @sno : all SCBs have a serial number + * @scp : associated scsi command + * @state : current state of scb + * @dma_dir : direction of data transfer + * @dma_type : transfer with sg list, buffer, or no data transfer + * @dev_channel : actual channel on the device + * @dev_target : actual target on the device + * @status : completion status * * This is our central data structure to issue commands the each driver. * Driver specific data structures are maintained in the ccb field. @@ -99,42 +99,42 @@ typedef struct { /** * struct adapter_t - driver's initialization structure - * @param dpc_h : tasklet handle - * @param pdev : pci configuration pointer for kernel - * @param host : pointer to host structure of mid-layer - * @param lock : synchronization lock for mid-layer and driver - * @param quiescent : driver is quiescent for now. - * @param outstanding_cmds : number of commands pending in the driver - * @param kscb_list : pointer to the bulk of SCBs pointers for IO - * @param kscb_pool : pool of free scbs for IO - * @param kscb_pool_lock : lock for pool of free scbs - * @param pend_list : pending commands list - * @param pend_list_lock : exlusion lock for pending commands list - * @param completed_list : list of completed commands - * @param completed_list_lock : exclusion lock for list of completed commands - * @param sglen : max sg elements supported - * @param device_ids : to convert kernel device addr to our devices. - * @param raid_device : raid adapter specific pointer - * @param max_channel : maximum channel number supported - inclusive - * @param max_target : max target supported - inclusive - * @param max_lun : max lun supported - inclusive - * @param unique_id : unique identifier for each adapter - * @param irq : IRQ for this adapter - * @param ito : internal timeout value, (-1) means no timeout - * @param ibuf : buffer to issue internal commands - * @param ibuf_dma_h : dma handle for the above buffer - * @param uscb_list : SCB pointers for user cmds, common mgmt module - * @param uscb_pool : pool of SCBs for user commands - * @param uscb_pool_lock : exclusion lock for these SCBs - * @param max_cmds : max outstanding commands - * @param fw_version : firmware version - * @param bios_version : bios version - * @param max_cdb_sz : biggest CDB size supported. - * @param ha : is high availability present - clustering - * @param init_id : initiator ID, the default value should be 7 - * @param max_sectors : max sectors per request - * @param cmd_per_lun : max outstanding commands per LUN - * @param being_detached : set when unloading, no more mgmt calls + * @aram dpc_h : tasklet handle + * @pdev : pci configuration pointer for kernel + * @host : pointer to host structure of mid-layer + * @lock : synchronization lock for mid-layer and driver + * @quiescent : driver is quiescent for now. + * @outstanding_cmds : number of commands pending in the driver + * @kscb_list : pointer to the bulk of SCBs pointers for IO + * @kscb_pool : pool of free scbs for IO + * @kscb_pool_lock : lock for pool of free scbs + * @pend_list : pending commands list + * @pend_list_lock : exclusion lock for pending commands list + * @completed_list : list of completed commands + * @completed_list_lock : exclusion lock for list of completed commands + * @sglen : max sg elements supported + * @device_ids : to convert kernel device addr to our devices. + * @raid_device : raid adapter specific pointer + * @max_channel : maximum channel number supported - inclusive + * @max_target : max target supported - inclusive + * @max_lun : max lun supported - inclusive + * @unique_id : unique identifier for each adapter + * @irq : IRQ for this adapter + * @ito : internal timeout value, (-1) means no timeout + * @ibuf : buffer to issue internal commands + * @ibuf_dma_h : dma handle for the above buffer + * @uscb_list : SCB pointers for user cmds, common mgmt module + * @uscb_pool : pool of SCBs for user commands + * @uscb_pool_lock : exclusion lock for these SCBs + * @max_cmds : max outstanding commands + * @fw_version : firmware version + * @bios_version : bios version + * @max_cdb_sz : biggest CDB size supported. + * @ha : is high availability present - clustering + * @init_id : initiator ID, the default value should be 7 + * @max_sectors : max sectors per request + * @cmd_per_lun : max outstanding commands per LUN + * @being_detached : set when unloading, no more mgmt calls * * * mraid_setup_device_map() can be called anytime after the device map is @@ -211,23 +211,23 @@ typedef struct { #define SCP2ADAPTER(scp) (adapter_t *)SCSIHOST2ADAP(SCP2HOST(scp)) -/** - * MRAID_GET_DEVICE_MAP - device ids - * @param adp - Adapter's soft state - * @param scp - mid-layer scsi command pointer - * @param p_chan - physical channel on the controller - * @param target - target id of the device or logical drive number - * @param islogical - set if the command is for the logical drive - * - * Macro to retrieve information about device class, logical or physical and - * the corresponding physical channel and target or logical drive number - **/ #define MRAID_IS_LOGICAL(adp, scp) \ (SCP2CHANNEL(scp) == (adp)->max_channel) ? 1 : 0 #define MRAID_IS_LOGICAL_SDEV(adp, sdev) \ (sdev->channel == (adp)->max_channel) ? 1 : 0 +/** + * MRAID_GET_DEVICE_MAP - device ids + * @adp : adapter's soft state + * @scp : mid-layer scsi command pointer + * @p_chan : physical channel on the controller + * @target : target id of the device or logical drive number + * @islogical : set if the command is for the logical drive + * + * Macro to retrieve information about device class, logical or physical and + * the corresponding physical channel and target or logical drive number + */ #define MRAID_GET_DEVICE_MAP(adp, scp, p_chan, target, islogical) \ /* \ * Is the request coming for the virtual channel \ @@ -271,10 +271,10 @@ typedef struct { #define ASSERT(expression) #endif -/* +/** * struct mraid_pci_blk - structure holds DMA memory block info - * @param vaddr : virtual address to a memory block - * @param dma_addr : DMA handle to a memory block + * @vaddr : virtual address to a memory block + * @dma_addr : DMA handle to a memory block * * This structure is filled up for the caller. It is the responsibilty of the * caller to allocate this array big enough to store addresses for all diff --git a/drivers/scsi/megaraid/megaraid_ioctl.h b/drivers/scsi/megaraid/megaraid_ioctl.h index b8aa34202ec334cd296dc911dac9c754a27875bc..706fa05a187af715c9abc50fbf47cac4f8fcd2f2 100644 --- a/drivers/scsi/megaraid/megaraid_ioctl.h +++ b/drivers/scsi/megaraid/megaraid_ioctl.h @@ -22,23 +22,23 @@ #include "mbox_defs.h" +/* + * console messages debug levels + */ +#define CL_ANN 0 /* print unconditionally, announcements */ +#define CL_DLEVEL1 1 /* debug level 1, informative */ +#define CL_DLEVEL2 2 /* debug level 2, verbose */ +#define CL_DLEVEL3 3 /* debug level 3, very verbose */ + /** * con_log() - console log routine - * @param level : indicates the severity of the message. - * @fparam mt : format string + * @level : indicates the severity of the message. + * @fmt : format string * * con_log displays the error messages on the console based on the current * debug level. Also it attaches the appropriate kernel severity level with * the message. - * - * - * consolge messages debug levels */ -#define CL_ANN 0 /* print unconditionally, announcements */ -#define CL_DLEVEL1 1 /* debug level 1, informative */ -#define CL_DLEVEL2 2 /* debug level 2, verbose */ -#define CL_DLEVEL3 3 /* debug level 3, very verbose */ - #define con_log(level, fmt) if (LSI_DBGLVL >= level) printk fmt; /* @@ -157,14 +157,14 @@ typedef struct uioc { /** * struct mraid_hba_info - information about the controller * - * @param pci_vendor_id : PCI vendor id - * @param pci_device_id : PCI device id - * @param subsystem_vendor_id : PCI subsystem vendor id - * @param subsystem_device_id : PCI subsystem device id - * @param baseport : base port of hba memory - * @param pci_bus : PCI bus - * @param pci_dev_fn : PCI device/function values - * @param irq : interrupt vector for the device + * @pci_vendor_id : PCI vendor id + * @pci_device_id : PCI device id + * @subsystem_vendor_id : PCI subsystem vendor id + * @subsystem_device_id : PCI subsystem device id + * @baseport : base port of hba memory + * @pci_bus : PCI bus + * @pci_dev_fn : PCI device/function values + * @irq : interrupt vector for the device * * Extended information of 256 bytes about the controller. Align on the single * byte boundary so that 32-bit applications can be run on 64-bit platform diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 7bac86dda88f9fdc053105ae149e9c9753125421..04d0b6918c6167749dcac06d8ab9e8152f031995 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -10,13 +10,13 @@ * 2 of the License, or (at your option) any later version. * * FILE : megaraid_mbox.c - * Version : v2.20.4.9 (Jul 16 2006) + * Version : v2.20.5.1 (Nov 16 2006) * * Authors: - * Atul Mukker - * Sreenivas Bagalkote - * Manoj Jose - * Seokmann Ju + * Atul Mukker + * Sreenivas Bagalkote + * Manoj Jose + * Seokmann Ju * * List of supported controllers * @@ -107,6 +107,7 @@ static int megaraid_mbox_support_random_del(adapter_t *); static int megaraid_mbox_get_max_sg(adapter_t *); static void megaraid_mbox_enum_raid_scsi(adapter_t *); static void megaraid_mbox_flush_cache(adapter_t *); +static int megaraid_mbox_fire_sync_cmd(adapter_t *); static void megaraid_mbox_display_scb(adapter_t *, scb_t *); static void megaraid_mbox_setup_device_map(adapter_t *); @@ -137,7 +138,7 @@ static int wait_till_fw_empty(adapter_t *); -MODULE_AUTHOR("sju@lsil.com"); +MODULE_AUTHOR("megaraidlinux@lsi.com"); MODULE_DESCRIPTION("LSI Logic MegaRAID Mailbox Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(MEGARAID_VERSION); @@ -146,7 +147,7 @@ MODULE_VERSION(MEGARAID_VERSION); * ### modules parameters for driver ### */ -/** +/* * Set to enable driver to expose unconfigured disk to kernel */ static int megaraid_expose_unconf_disks = 0; @@ -154,7 +155,7 @@ module_param_named(unconf_disks, megaraid_expose_unconf_disks, int, 0); MODULE_PARM_DESC(unconf_disks, "Set to expose unconfigured disks to kernel (default=0)"); -/** +/* * driver wait time if the adapter's mailbox is busy */ static unsigned int max_mbox_busy_wait = MBOX_BUSY_WAIT; @@ -162,7 +163,7 @@ module_param_named(busy_wait, max_mbox_busy_wait, int, 0); MODULE_PARM_DESC(busy_wait, "Max wait for mailbox in microseconds if busy (default=10)"); -/** +/* * number of sectors per IO command */ static unsigned int megaraid_max_sectors = MBOX_MAX_SECTORS; @@ -170,7 +171,7 @@ module_param_named(max_sectors, megaraid_max_sectors, int, 0); MODULE_PARM_DESC(max_sectors, "Maximum number of sectors per IO command (default=128)"); -/** +/* * number of commands per logical unit */ static unsigned int megaraid_cmd_per_lun = MBOX_DEF_CMD_PER_LUN; @@ -179,7 +180,7 @@ MODULE_PARM_DESC(cmd_per_lun, "Maximum number of commands per logical unit (default=64)"); -/** +/* * Fast driver load option, skip scanning for physical devices during load. * This would result in non-disk devices being skipped during driver load * time. These can be later added though, using /proc/scsi/scsi @@ -190,7 +191,7 @@ MODULE_PARM_DESC(fast_load, "Faster loading of the driver, skips physical devices! (default=0)"); -/** +/* * mraid_debug level - threshold for amount of information to be displayed by * the driver. This level can be changed through modules parameters, ioctl or * sysfs/proc interface. By default, print the announcement messages only. @@ -337,7 +338,7 @@ static struct device_attribute *megaraid_sdev_attrs[] = { * * Return value: * actual depth set - **/ + */ static int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth) { if (qdepth > MBOX_MAX_SCSI_CMDS) @@ -369,8 +370,8 @@ static struct scsi_host_template megaraid_template_g = { * megaraid_init - module load hook * * We register ourselves as hotplug enabled module and let PCI subsystem - * discover our adaters - **/ + * discover our adapters. + */ static int __init megaraid_init(void) { @@ -405,7 +406,7 @@ megaraid_init(void) /** * megaraid_exit - driver unload entry point * - * We simply unwrap the megaraid_init routine here + * We simply unwrap the megaraid_init routine here. */ static void __exit megaraid_exit(void) @@ -421,12 +422,12 @@ megaraid_exit(void) /** * megaraid_probe_one - PCI hotplug entry point - * @param pdev : handle to this controller's PCI configuration space - * @param id : pci device id of the class of controllers + * @pdev : handle to this controller's PCI configuration space + * @id : pci device id of the class of controllers * * This routine should be called whenever a new adapter is detected by the * PCI hotplug susbsytem. - **/ + */ static int __devinit megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -542,16 +543,15 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) /** - * megaraid_detach_one - release the framework resources and call LLD release - * routine - * @param pdev : handle for our PCI cofiguration space + * megaraid_detach_one - release framework resources and call LLD release routine + * @pdev : handle for our PCI cofiguration space * * This routine is called during driver unload. We free all the allocated * resources and call the corresponding LLD so that it can also release all * its resources. * - * This routine is also called from the PCI hotplug system - **/ + * This routine is also called from the PCI hotplug system. + */ static void megaraid_detach_one(struct pci_dev *pdev) { @@ -615,9 +615,9 @@ megaraid_detach_one(struct pci_dev *pdev) /** * megaraid_mbox_shutdown - PCI shutdown for megaraid HBA - * @param device : generice driver model device + * @pdev : generic driver model device * - * Shutdown notification, perform flush cache + * Shutdown notification, perform flush cache. */ static void megaraid_mbox_shutdown(struct pci_dev *pdev) @@ -643,10 +643,10 @@ megaraid_mbox_shutdown(struct pci_dev *pdev) /** * megaraid_io_attach - attach a device with the IO subsystem - * @param adapter : controller's soft state + * @adapter : controller's soft state * - * Attach this device with the IO subsystem - **/ + * Attach this device with the IO subsystem. + */ static int megaraid_io_attach(adapter_t *adapter) { @@ -695,10 +695,10 @@ megaraid_io_attach(adapter_t *adapter) /** * megaraid_io_detach - detach a device from the IO subsystem - * @param adapter : controller's soft state + * @adapter : controller's soft state * - * Detach this device from the IO subsystem - **/ + * Detach this device from the IO subsystem. + */ static void megaraid_io_detach(adapter_t *adapter) { @@ -722,13 +722,13 @@ megaraid_io_detach(adapter_t *adapter) /** * megaraid_init_mbox - initialize controller - * @param adapter - our soft state + * @adapter : our soft state * - * . Allocate 16-byte aligned mailbox memory for firmware handshake - * . Allocate controller's memory resources - * . Find out all initialization data - * . Allocate memory required for all the commands - * . Use internal library of FW routines, build up complete soft state + * - Allocate 16-byte aligned mailbox memory for firmware handshake + * - Allocate controller's memory resources + * - Find out all initialization data + * - Allocate memory required for all the commands + * - Use internal library of FW routines, build up complete soft state */ static int __devinit megaraid_init_mbox(adapter_t *adapter) @@ -779,33 +779,39 @@ megaraid_init_mbox(adapter_t *adapter) goto out_release_regions; } - // - // Setup the rest of the soft state using the library of FW routines - // + /* initialize the mutual exclusion lock for the mailbox */ + spin_lock_init(&raid_dev->mailbox_lock); - // request IRQ and register the interrupt service routine + /* allocate memory required for commands */ + if (megaraid_alloc_cmd_packets(adapter) != 0) + goto out_iounmap; + + /* + * Issue SYNC cmd to flush the pending cmds in the adapter + * and initialize its internal state + */ + + if (megaraid_mbox_fire_sync_cmd(adapter)) + con_log(CL_ANN, ("megaraid: sync cmd failed\n")); + + /* + * Setup the rest of the soft state using the library of + * FW routines + */ + + /* request IRQ and register the interrupt service routine */ if (request_irq(adapter->irq, megaraid_isr, IRQF_SHARED, "megaraid", adapter)) { con_log(CL_ANN, (KERN_WARNING "megaraid: Couldn't register IRQ %d!\n", adapter->irq)); + goto out_alloc_cmds; - goto out_iounmap; - } - - - // initialize the mutual exclusion lock for the mailbox - spin_lock_init(&raid_dev->mailbox_lock); - - // allocate memory required for commands - if (megaraid_alloc_cmd_packets(adapter) != 0) { - goto out_free_irq; } // Product info - if (megaraid_mbox_product_info(adapter) != 0) { - goto out_alloc_cmds; - } + if (megaraid_mbox_product_info(adapter) != 0) + goto out_free_irq; // Do we support extended CDBs adapter->max_cdb_sz = 10; @@ -874,9 +880,8 @@ megaraid_init_mbox(adapter_t *adapter) * Allocate resources required to issue FW calls, when sysfs is * accessed */ - if (megaraid_sysfs_alloc_resources(adapter) != 0) { - goto out_alloc_cmds; - } + if (megaraid_sysfs_alloc_resources(adapter) != 0) + goto out_free_irq; // Set the DMA mask to 64-bit. All supported controllers as capable of // DMA in this range @@ -920,10 +925,10 @@ megaraid_init_mbox(adapter_t *adapter) out_free_sysfs_res: megaraid_sysfs_free_resources(adapter); -out_alloc_cmds: - megaraid_free_cmd_packets(adapter); out_free_irq: free_irq(adapter->irq, adapter); +out_alloc_cmds: + megaraid_free_cmd_packets(adapter); out_iounmap: iounmap(raid_dev->baseaddr); out_release_regions: @@ -937,7 +942,7 @@ megaraid_init_mbox(adapter_t *adapter) /** * megaraid_fini_mbox - undo controller initialization - * @param adapter : our soft state + * @adapter : our soft state */ static void megaraid_fini_mbox(adapter_t *adapter) @@ -967,12 +972,12 @@ megaraid_fini_mbox(adapter_t *adapter) /** * megaraid_alloc_cmd_packets - allocate shared mailbox - * @param adapter : soft state of the raid controller + * @adapter : soft state of the raid controller * * Allocate and align the shared mailbox. This maibox is used to issue * all the commands. For IO based controllers, the mailbox is also regsitered * with the FW. Allocate memory for all commands as well. - * This is our big allocator + * This is our big allocator. */ static int megaraid_alloc_cmd_packets(adapter_t *adapter) @@ -1132,9 +1137,9 @@ megaraid_alloc_cmd_packets(adapter_t *adapter) /** * megaraid_free_cmd_packets - free memory - * @param adapter : soft state of the raid controller + * @adapter : soft state of the raid controller * - * Release memory resources allocated for commands + * Release memory resources allocated for commands. */ static void megaraid_free_cmd_packets(adapter_t *adapter) @@ -1156,10 +1161,10 @@ megaraid_free_cmd_packets(adapter_t *adapter) /** * megaraid_mbox_setup_dma_pools - setup dma pool for command packets - * @param adapter : HBA soft state + * @adapter : HBA soft state * - * setup the dma pools for mailbox, passthru and extended passthru structures, - * and scatter-gather lists + * Setup the dma pools for mailbox, passthru and extended passthru structures, + * and scatter-gather lists. */ static int megaraid_mbox_setup_dma_pools(adapter_t *adapter) @@ -1252,10 +1257,10 @@ megaraid_mbox_setup_dma_pools(adapter_t *adapter) /** * megaraid_mbox_teardown_dma_pools - teardown dma pools for command packets - * @param adapter : HBA soft state + * @adapter : HBA soft state * - * teardown the dma pool for mailbox, passthru and extended passthru - * structures, and scatter-gather lists + * Teardown the dma pool for mailbox, passthru and extended passthru + * structures, and scatter-gather lists. */ static void megaraid_mbox_teardown_dma_pools(adapter_t *adapter) @@ -1300,10 +1305,11 @@ megaraid_mbox_teardown_dma_pools(adapter_t *adapter) /** * megaraid_alloc_scb - detach and return a scb from the free list * @adapter : controller's soft state + * @scp : pointer to the scsi command to be executed * - * return the scb from the head of the free list. NULL if there are none - * available - **/ + * Return the scb from the head of the free list. %NULL if there are none + * available. + */ static scb_t * megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp) { @@ -1337,11 +1343,11 @@ megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp) * @adapter : controller's soft state * @scb : scb to be freed * - * return the scb back to the free list of scbs. The caller must 'flush' the + * Return the scb back to the free list of scbs. The caller must 'flush' the * SCB before calling us. E.g., performing pci_unamp and/or pci_sync etc. * NOTE NOTE: Make sure the scb is not on any list before calling this * routine. - **/ + */ static inline void megaraid_dealloc_scb(adapter_t *adapter, scb_t *scb) { @@ -1362,10 +1368,10 @@ megaraid_dealloc_scb(adapter_t *adapter, scb_t *scb) /** * megaraid_mbox_mksgl - make the scatter-gather list - * @adapter - controller's soft state - * @scb - scsi control block + * @adapter : controller's soft state + * @scb : scsi control block * - * prepare the scatter-gather list + * Prepare the scatter-gather list. */ static int megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb) @@ -1435,10 +1441,10 @@ megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb) /** * mbox_post_cmd - issue a mailbox command - * @adapter - controller's soft state - * @scb - command to be issued + * @adapter : controller's soft state + * @scb : command to be issued * - * post the command to the controller if mailbox is availble. + * Post the command to the controller if mailbox is available. */ static int mbox_post_cmd(adapter_t *adapter, scb_t *scb) @@ -1518,7 +1524,7 @@ mbox_post_cmd(adapter_t *adapter, scb_t *scb) * Queue entry point for mailbox based controllers. */ static int -megaraid_queue_command(struct scsi_cmnd *scp, void (* done)(struct scsi_cmnd *)) +megaraid_queue_command(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *)) { adapter_t *adapter; scb_t *scb; @@ -1548,15 +1554,15 @@ megaraid_queue_command(struct scsi_cmnd *scp, void (* done)(struct scsi_cmnd *)) } /** - * megaraid_mbox_build_cmd - transform the mid-layer scsi command to megaraid - * firmware lingua - * @adapter - controller's soft state - * @scp - mid-layer scsi command pointer - * @busy - set if request could not be completed because of lack of + * megaraid_mbox_build_cmd - transform the mid-layer scsi commands + * @adapter : controller's soft state + * @scp : mid-layer scsi command pointer + * @busy : set if request could not be completed because of lack of * resources * - * convert the command issued by mid-layer to format understood by megaraid - * firmware. We also complete certain command without sending them to firmware + * Transform the mid-layer scsi command to megaraid firmware lingua. + * Convert the command issued by mid-layer to format understood by megaraid + * firmware. We also complete certain commands without sending them to firmware. */ static scb_t * megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy) @@ -1937,9 +1943,9 @@ megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy) /** * megaraid_mbox_runpendq - execute commands queued in the pending queue * @adapter : controller's soft state - * @scb : SCB to be queued in the pending list + * @scb_q : SCB to be queued in the pending list * - * scan the pending list for commands which are not yet issued and try to + * Scan the pending list for commands which are not yet issued and try to * post to the controller. The SCB can be a null pointer, which would indicate * no SCB to be queue, just try to execute the ones in the pending list. * @@ -2012,11 +2018,11 @@ megaraid_mbox_runpendq(adapter_t *adapter, scb_t *scb_q) /** * megaraid_mbox_prepare_pthru - prepare a command for physical devices - * @adapter - pointer to controller's soft state - * @scb - scsi control block - * @scp - scsi command from the mid-layer + * @adapter : pointer to controller's soft state + * @scb : scsi control block + * @scp : scsi command from the mid-layer * - * prepare a command for the scsi physical devices + * Prepare a command for the scsi physical devices. */ static void megaraid_mbox_prepare_pthru(adapter_t *adapter, scb_t *scb, @@ -2060,12 +2066,12 @@ megaraid_mbox_prepare_pthru(adapter_t *adapter, scb_t *scb, /** * megaraid_mbox_prepare_epthru - prepare a command for physical devices - * @adapter - pointer to controller's soft state - * @scb - scsi control block - * @scp - scsi command from the mid-layer + * @adapter : pointer to controller's soft state + * @scb : scsi control block + * @scp : scsi command from the mid-layer * - * prepare a command for the scsi physical devices. This rountine prepares - * commands for devices which can take extended CDBs (>10 bytes) + * Prepare a command for the scsi physical devices. This rountine prepares + * commands for devices which can take extended CDBs (>10 bytes). */ static void megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb, @@ -2109,9 +2115,9 @@ megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb, /** * megaraid_ack_sequence - interrupt ack sequence for memory mapped HBAs - * @adapter - controller's soft state + * @adapter : controller's soft state * - * Interrupt ackrowledgement sequence for memory mapped HBAs. Find out the + * Interrupt acknowledgement sequence for memory mapped HBAs. Find out the * completed command and put them on the completed list for later processing. * * Returns: 1 if the interrupt is valid, 0 otherwise @@ -2224,9 +2230,8 @@ megaraid_ack_sequence(adapter_t *adapter) /** * megaraid_isr - isr for memory based mailbox based controllers - * @irq - irq - * @devp - pointer to our soft state - * @regs - unused + * @irq : irq + * @devp : pointer to our soft state * * Interrupt service routine for memory-mapped mailbox controllers. */ @@ -2671,7 +2676,7 @@ megaraid_abort_handler(struct scsi_cmnd *scp) * the FW is still live, in which case the outstanding commands counter mut go * down to 0. If that happens, also issue the reservation reset command to * relinquish (possible) reservations on the logical drives connected to this - * host + * host. **/ static int megaraid_reset_handler(struct scsi_cmnd *scp) @@ -2823,11 +2828,11 @@ megaraid_reset_handler(struct scsi_cmnd *scp) /** * mbox_post_sync_cmd() - blocking command to the mailbox based controllers - * @adapter - controller's soft state - * @raw_mbox - the mailbox + * @adapter : controller's soft state + * @raw_mbox : the mailbox * * Issue a scb in synchronous and non-interrupt mode for mailbox based - * controllers + * controllers. */ static int mbox_post_sync_cmd(adapter_t *adapter, uint8_t raw_mbox[]) @@ -2955,12 +2960,12 @@ mbox_post_sync_cmd(adapter_t *adapter, uint8_t raw_mbox[]) /** * mbox_post_sync_cmd_fast - blocking command to the mailbox based controllers - * @adapter - controller's soft state - * @raw_mbox - the mailbox + * @adapter : controller's soft state + * @raw_mbox : the mailbox * * Issue a scb in synchronous and non-interrupt mode for mailbox based * controllers. This is a faster version of the synchronous command and - * therefore can be called in interrupt-context as well + * therefore can be called in interrupt-context as well. */ static int mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[]) @@ -3008,10 +3013,10 @@ mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[]) /** * megaraid_busywait_mbox() - Wait until the controller's mailbox is available - * @raid_dev - RAID device (HBA) soft state + * @raid_dev : RAID device (HBA) soft state * - * wait until the controller's mailbox is available to accept more commands. - * wait for at most 1 second + * Wait until the controller's mailbox is available to accept more commands. + * Wait for at most 1 second. */ static int megaraid_busywait_mbox(mraid_device_t *raid_dev) @@ -3032,9 +3037,9 @@ megaraid_busywait_mbox(mraid_device_t *raid_dev) /** * megaraid_mbox_product_info - some static information about the controller - * @adapter - our soft state + * @adapter : our soft state * - * issue commands to the controller to grab some parameters required by our + * Issue commands to the controller to grab some parameters required by our * caller. */ static int @@ -3157,10 +3162,10 @@ megaraid_mbox_product_info(adapter_t *adapter) /** * megaraid_mbox_extended_cdb - check for support for extended CDBs - * @adapter - soft state for the controller + * @adapter : soft state for the controller * - * this routine check whether the controller in question supports extended - * ( > 10 bytes ) CDBs + * This routine check whether the controller in question supports extended + * ( > 10 bytes ) CDBs. */ static int megaraid_mbox_extended_cdb(adapter_t *adapter) @@ -3193,8 +3198,8 @@ megaraid_mbox_extended_cdb(adapter_t *adapter) /** * megaraid_mbox_support_ha - Do we support clustering - * @adapter - soft state for the controller - * @init_id - ID of the initiator + * @adapter : soft state for the controller + * @init_id : ID of the initiator * * Determine if the firmware supports clustering and the ID of the initiator. */ @@ -3236,9 +3241,9 @@ megaraid_mbox_support_ha(adapter_t *adapter, uint16_t *init_id) /** * megaraid_mbox_support_random_del - Do we support random deletion - * @adapter - soft state for the controller + * @adapter : soft state for the controller * - * Determine if the firmware supports random deletion + * Determine if the firmware supports random deletion. * Return: 1 is operation supported, 0 otherwise */ static int @@ -3271,10 +3276,10 @@ megaraid_mbox_support_random_del(adapter_t *adapter) /** * megaraid_mbox_get_max_sg - maximum sg elements supported by the firmware - * @adapter - soft state for the controller + * @adapter : soft state for the controller * * Find out the maximum number of scatter-gather elements supported by the - * firmware + * firmware. */ static int megaraid_mbox_get_max_sg(adapter_t *adapter) @@ -3311,10 +3316,10 @@ megaraid_mbox_get_max_sg(adapter_t *adapter) /** * megaraid_mbox_enum_raid_scsi - enumerate the RAID and SCSI channels - * @adapter - soft state for the controller + * @adapter : soft state for the controller * - * Enumerate the RAID and SCSI channels for ROMB platoforms so that channels - * can be exported as regular SCSI channels + * Enumerate the RAID and SCSI channels for ROMB platforms so that channels + * can be exported as regular SCSI channels. */ static void megaraid_mbox_enum_raid_scsi(adapter_t *adapter) @@ -3348,9 +3353,9 @@ megaraid_mbox_enum_raid_scsi(adapter_t *adapter) /** * megaraid_mbox_flush_cache - flush adapter and disks cache - * @param adapter : soft state for the controller + * @adapter : soft state for the controller * - * Flush adapter cache followed by disks cache + * Flush adapter cache followed by disks cache. */ static void megaraid_mbox_flush_cache(adapter_t *adapter) @@ -3379,14 +3384,92 @@ megaraid_mbox_flush_cache(adapter_t *adapter) } +/** + * megaraid_mbox_fire_sync_cmd - fire the sync cmd + * @adapter : soft state for the controller + * + * Clears the pending cmds in FW and reinits its RAID structs. + */ +static int +megaraid_mbox_fire_sync_cmd(adapter_t *adapter) +{ + mbox_t *mbox; + uint8_t raw_mbox[sizeof(mbox_t)]; + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + mbox64_t *mbox64; + int status = 0; + int i; + uint32_t dword; + + mbox = (mbox_t *)raw_mbox; + + memset((caddr_t)raw_mbox, 0, sizeof(mbox_t)); + + raw_mbox[0] = 0xFF; + + mbox64 = raid_dev->mbox64; + mbox = raid_dev->mbox; + + /* Wait until mailbox is free */ + if (megaraid_busywait_mbox(raid_dev) != 0) { + status = 1; + goto blocked_mailbox; + } + + /* Copy mailbox data into host structure */ + memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 16); + mbox->cmdid = 0xFE; + mbox->busy = 1; + mbox->poll = 0; + mbox->ack = 0; + mbox->numstatus = 0; + mbox->status = 0; + + wmb(); + WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1); + + /* Wait for maximum 1 min for status to post. + * If the Firmware SUPPORTS the ABOVE COMMAND, + * mbox->cmd will be set to 0 + * else + * the firmware will reject the command with + * mbox->numstatus set to 1 + */ + + i = 0; + status = 0; + while (!mbox->numstatus && mbox->cmd == 0xFF) { + rmb(); + msleep(1); + i++; + if (i > 1000 * 60) { + status = 1; + break; + } + } + if (mbox->numstatus == 1) + status = 1; /*cmd not supported*/ + + /* Check for interrupt line */ + dword = RDOUTDOOR(raid_dev); + WROUTDOOR(raid_dev, dword); + WRINDOOR(raid_dev,2); + + return status; + +blocked_mailbox: + con_log(CL_ANN, (KERN_WARNING "megaraid: blocked mailbox\n")); + return status; +} + /** * megaraid_mbox_display_scb - display SCB information, mostly debug purposes - * @param adapter : controllers' soft state - * @param scb : SCB to be displayed - * @param level : debug level for console print + * @adapter : controller's soft state + * @scb : SCB to be displayed + * @level : debug level for console print * * Diplay information about the given SCB iff the current debug level is - * verbose + * verbose. */ static void megaraid_mbox_display_scb(adapter_t *adapter, scb_t *scb) @@ -3434,7 +3517,7 @@ megaraid_mbox_display_scb(adapter_t *adapter, scb_t *scb) * scsi addresses and megaraid scsi and logical drive addresses. We export * scsi devices on their actual addresses, whereas the logical drives are * exported on a virtual scsi channel. - **/ + */ static void megaraid_mbox_setup_device_map(adapter_t *adapter) { @@ -3472,7 +3555,7 @@ megaraid_mbox_setup_device_map(adapter_t *adapter) /** * megaraid_cmm_register - register with the mangement module - * @param adapter : HBA soft state + * @adapter : HBA soft state * * Register with the management module, which allows applications to issue * ioctl calls to the drivers. This interface is used by the management module @@ -3562,11 +3645,11 @@ megaraid_cmm_register(adapter_t *adapter) /** * megaraid_cmm_unregister - un-register with the mangement module - * @param adapter : HBA soft state + * @adapter : HBA soft state * * Un-register with the management module. * FIXME: mgmt module must return failure for unregister if it has pending - * commands in LLD + * commands in LLD. */ static int megaraid_cmm_unregister(adapter_t *adapter) @@ -3579,9 +3662,9 @@ megaraid_cmm_unregister(adapter_t *adapter) /** * megaraid_mbox_mm_handler - interface for CMM to issue commands to LLD - * @param drvr_data : LLD specific data - * @param kioc : CMM interface packet - * @param action : command action + * @drvr_data : LLD specific data + * @kioc : CMM interface packet + * @action : command action * * This routine is invoked whenever the Common Mangement Module (CMM) has a * command for us. The 'action' parameter specifies if this is a new command @@ -3634,8 +3717,8 @@ megaraid_mbox_mm_handler(unsigned long drvr_data, uioc_t *kioc, uint32_t action) /** * megaraid_mbox_mm_command - issues commands routed through CMM - * @param adapter : HBA soft state - * @param kioc : management command packet + * @adapter : HBA soft state + * @kioc : management command packet * * Issues commands, which are routed through the management module. */ @@ -3804,8 +3887,8 @@ megaraid_mbox_mm_done(adapter_t *adapter, scb_t *scb) /** * gather_hbainfo - HBA characteristics for the applications - * @param adapter : HBA soft state - * @param hinfo : pointer to the caller's host info strucuture + * @adapter : HBA soft state + * @hinfo : pointer to the caller's host info strucuture */ static int gather_hbainfo(adapter_t *adapter, mraid_hba_info_t *hinfo) @@ -3839,16 +3922,15 @@ gather_hbainfo(adapter_t *adapter, mraid_hba_info_t *hinfo) /** * megaraid_sysfs_alloc_resources - allocate sysfs related resources + * @adapter : controller's soft state * * Allocate packets required to issue FW calls whenever the sysfs attributes * are read. These attributes would require up-to-date information from the * FW. Also set up resources for mutual exclusion to share these resources and * the wait queue. * - * @param adapter : controller's soft state - * - * @return 0 on success - * @return -ERROR_CODE on failure + * Return 0 on success. + * Return -ERROR_CODE on failure. */ static int megaraid_sysfs_alloc_resources(adapter_t *adapter) @@ -3885,10 +3967,9 @@ megaraid_sysfs_alloc_resources(adapter_t *adapter) /** * megaraid_sysfs_free_resources - free sysfs related resources + * @adapter : controller's soft state * * Free packets allocated for sysfs FW commands - * - * @param adapter : controller's soft state */ static void megaraid_sysfs_free_resources(adapter_t *adapter) @@ -3907,10 +3988,9 @@ megaraid_sysfs_free_resources(adapter_t *adapter) /** * megaraid_sysfs_get_ldmap_done - callback for get ldmap + * @uioc : completed packet * * Callback routine called in the ISR/tasklet context for get ldmap call - * - * @param uioc : completed packet */ static void megaraid_sysfs_get_ldmap_done(uioc_t *uioc) @@ -3926,12 +4006,11 @@ megaraid_sysfs_get_ldmap_done(uioc_t *uioc) /** * megaraid_sysfs_get_ldmap_timeout - timeout handling for get ldmap + * @data : timed out packet * * Timeout routine to recover and return to application, in case the adapter - * has stopped responding. A timeout of 60 seconds for this command seem like - * a good value - * - * @param uioc : timed out packet + * has stopped responding. A timeout of 60 seconds for this command seems like + * a good value. */ static void megaraid_sysfs_get_ldmap_timeout(unsigned long data) @@ -3948,6 +4027,7 @@ megaraid_sysfs_get_ldmap_timeout(unsigned long data) /** * megaraid_sysfs_get_ldmap - get update logical drive map + * @adapter : controller's soft state * * This routine will be called whenever user reads the logical drive * attributes, go get the current logical drive mapping table from the @@ -3959,10 +4039,8 @@ megaraid_sysfs_get_ldmap_timeout(unsigned long data) * standalone libary. For now, this should suffice since there is no other * user of this interface. * - * @param adapter : controller's soft state - * - * @return 0 on success - * @return -1 on failure + * Return 0 on success. + * Return -1 on failure. */ static int megaraid_sysfs_get_ldmap(adapter_t *adapter) @@ -4064,13 +4142,12 @@ megaraid_sysfs_get_ldmap(adapter_t *adapter) /** * megaraid_sysfs_show_app_hndl - display application handle for this adapter + * @cdev : class device object representation for the host + * @buf : buffer to send data to * * Display the handle used by the applications while executing management * tasks on the adapter. We invoke a management module API to get the adapter * handle, since we do not interface with applications directly. - * - * @param cdev : class device object representation for the host - * @param buf : buffer to send data to */ static ssize_t megaraid_sysfs_show_app_hndl(struct class_device *cdev, char *buf) @@ -4087,16 +4164,18 @@ megaraid_sysfs_show_app_hndl(struct class_device *cdev, char *buf) /** * megaraid_sysfs_show_ldnum - display the logical drive number for this device + * @dev : device object representation for the scsi device + * @attr : device attribute to show + * @buf : buffer to send data to * * Display the logical drive number for the device in question, if it a valid - * logical drive. For physical devices, "-1" is returned - * The logical drive number is displayed in following format + * logical drive. For physical devices, "-1" is returned. + * + * The logical drive number is displayed in following format: * * - * * - * @param dev : device object representation for the scsi device - * @param buf : buffer to send data to + * */ static ssize_t megaraid_sysfs_show_ldnum(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h index 2b5a3285f799829b840baf04d603e03dc8835ec9..9de803cebd4badec858161d679a0b85905b9026a 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.h +++ b/drivers/scsi/megaraid/megaraid_mbox.h @@ -21,8 +21,8 @@ #include "megaraid_ioctl.h" -#define MEGARAID_VERSION "2.20.4.9" -#define MEGARAID_EXT_VERSION "(Release Date: Sun Jul 16 12:27:22 EST 2006)" +#define MEGARAID_VERSION "2.20.5.1" +#define MEGARAID_EXT_VERSION "(Release Date: Thu Nov 16 15:32:35 EST 2006)" /* @@ -146,27 +146,27 @@ typedef struct { /** * mraid_device_t - adapter soft state structure for mailbox controllers - * @param una_mbox64 : 64-bit mbox - unaligned - * @param una_mbox64_dma : mbox dma addr - unaligned - * @param mbox : 32-bit mbox - aligned - * @param mbox64 : 64-bit mbox - aligned - * @param mbox_dma : mbox dma addr - aligned - * @param mailbox_lock : exclusion lock for the mailbox - * @param baseport : base port of hba memory - * @param baseaddr : mapped addr of hba memory - * @param mbox_pool : pool of mailboxes - * @param mbox_pool_handle : handle for the mailbox pool memory - * @param epthru_pool : a pool for extended passthru commands - * @param epthru_pool_handle : handle to the pool above - * @param sg_pool : pool of scatter-gather lists for this driver - * @param sg_pool_handle : handle to the pool above - * @param ccb_list : list of our command control blocks - * @param uccb_list : list of cmd control blocks for mgmt module - * @param umbox64 : array of mailbox for user commands (cmm) - * @param pdrv_state : array for state of each physical drive. - * @param last_disp : flag used to show device scanning - * @param hw_error : set if FW not responding - * @param fast_load : If set, skip physical device scanning + * @una_mbox64 : 64-bit mbox - unaligned + * @una_mbox64_dma : mbox dma addr - unaligned + * @mbox : 32-bit mbox - aligned + * @mbox64 : 64-bit mbox - aligned + * @mbox_dma : mbox dma addr - aligned + * @mailbox_lock : exclusion lock for the mailbox + * @baseport : base port of hba memory + * @baseaddr : mapped addr of hba memory + * @mbox_pool : pool of mailboxes + * @mbox_pool_handle : handle for the mailbox pool memory + * @epthru_pool : a pool for extended passthru commands + * @epthru_pool_handle : handle to the pool above + * @sg_pool : pool of scatter-gather lists for this driver + * @sg_pool_handle : handle to the pool above + * @ccb_list : list of our command control blocks + * @uccb_list : list of cmd control blocks for mgmt module + * @umbox64 : array of mailbox for user commands (cmm) + * @pdrv_state : array for state of each physical drive. + * @last_disp : flag used to show device scanning + * @hw_error : set if FW not responding + * @fast_load : If set, skip physical device scanning * @channel_class : channel class, RAID or SCSI * @sysfs_sem : semaphore to serialize access to sysfs res. * @sysfs_uioc : management packet to issue FW calls from sysfs diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c index d85b9a8f1b8d94e5040e598b35b957f9a90ff1a7..c1ff20c4747d960351561c8a954f46ece69cd94c 100644 --- a/drivers/scsi/megaraid/megaraid_mm.c +++ b/drivers/scsi/megaraid/megaraid_mm.c @@ -78,10 +78,10 @@ static struct file_operations lsi_fops = { /** * mraid_mm_open - open routine for char node interface - * @inod : unused + * @inode : unused * @filep : unused * - * allow ioctl operations by apps only if they superuser privilege + * Allow ioctl operations by apps only if they have superuser privilege. */ static int mraid_mm_open(struct inode *inode, struct file *filep) @@ -214,7 +214,9 @@ mraid_mm_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, /** * mraid_mm_get_adapter - Returns corresponding adapters for the mimd packet * @umimd : User space mimd_t ioctl packet - * @adapter : pointer to the adapter (OUT) + * @rval : returned success/error status + * + * The function return value is a pointer to the located @adapter. */ static mraid_mmadp_t * mraid_mm_get_adapter(mimd_t __user *umimd, int *rval) @@ -252,11 +254,11 @@ mraid_mm_get_adapter(mimd_t __user *umimd, int *rval) return adapter; } -/* - * handle_drvrcmd - This routine checks if the opcode is a driver - * cmd and if it is, handles it. +/** + * handle_drvrcmd - Checks if the opcode is a driver cmd and if it is, handles it. * @arg : packet sent by the user app * @old_ioctl : mimd if 1; uioc otherwise + * @rval : pointer for command's returned value (not function status) */ static int handle_drvrcmd(void __user *arg, uint8_t old_ioctl, int *rval) @@ -322,8 +324,8 @@ handle_drvrcmd(void __user *arg, uint8_t old_ioctl, int *rval) /** * mimd_to_kioc - Converter from old to new ioctl format - * * @umimd : user space old MIMD IOCTL + * @adp : adapter softstate * @kioc : kernel space new format IOCTL * * Routine to convert MIMD interface IOCTL to new interface IOCTL packet. The @@ -474,7 +476,6 @@ mimd_to_kioc(mimd_t __user *umimd, mraid_mmadp_t *adp, uioc_t *kioc) /** * mraid_mm_attch_buf - Attach a free dma buffer for required size - * * @adp : Adapter softstate * @kioc : kioc that the buffer needs to be attached to * @xferlen : required length for buffer @@ -607,7 +608,6 @@ mraid_mm_alloc_kioc(mraid_mmadp_t *adp) /** * mraid_mm_dealloc_kioc - Return kioc to free pool - * * @adp : Adapter softstate * @kioc : uioc_t node to be returned to free pool */ @@ -652,7 +652,6 @@ mraid_mm_dealloc_kioc(mraid_mmadp_t *adp, uioc_t *kioc) /** * lld_ioctl - Routine to issue ioctl to low level drvr - * * @adp : The adapter handle * @kioc : The ioctl packet with kernel addresses */ @@ -705,7 +704,6 @@ lld_ioctl(mraid_mmadp_t *adp, uioc_t *kioc) /** * ioctl_done - callback from the low level driver - * * @kioc : completed ioctl packet */ static void @@ -756,9 +754,8 @@ ioctl_done(uioc_t *kioc) } -/* - * lld_timedout : callback from the expired timer - * +/** + * lld_timedout - callback from the expired timer * @ptr : ioctl packet that timed out */ static void @@ -776,8 +773,7 @@ lld_timedout(unsigned long ptr) /** - * kioc_to_mimd : Converter from new back to old format - * + * kioc_to_mimd - Converter from new back to old format * @kioc : Kernel space IOCTL packet (successfully issued) * @mimd : User space MIMD packet */ @@ -855,7 +851,6 @@ kioc_to_mimd(uioc_t *kioc, mimd_t __user *mimd) /** * hinfo_to_cinfo - Convert new format hba info into old format - * * @hinfo : New format, more comprehensive adapter info * @cinfo : Old format adapter info to support mimd_t apps */ @@ -878,10 +873,9 @@ hinfo_to_cinfo(mraid_hba_info_t *hinfo, mcontroller_t *cinfo) } -/* - * mraid_mm_register_adp - Registration routine for low level drvrs - * - * @adp : Adapter objejct +/** + * mraid_mm_register_adp - Registration routine for low level drivers + * @lld_adp : Adapter objejct */ int mraid_mm_register_adp(mraid_mmadp_t *lld_adp) @@ -1007,15 +1001,14 @@ mraid_mm_register_adp(mraid_mmadp_t *lld_adp) /** * mraid_mm_adapter_app_handle - return the application handle for this adapter + * @unique_id : adapter unique identifier * - * For the given driver data, locate the adadpter in our global list and + * For the given driver data, locate the adapter in our global list and * return the corresponding handle, which is also used by applications to * uniquely identify an adapter. * - * @param unique_id : adapter unique identifier - * - * @return adapter handle if found in the list - * @return 0 if adapter could not be located, should never happen though + * Return adapter handle if found in the list. + * Return 0 if adapter could not be located, should never happen though. */ uint32_t mraid_mm_adapter_app_handle(uint32_t unique_id) @@ -1040,7 +1033,6 @@ mraid_mm_adapter_app_handle(uint32_t unique_id) /** * mraid_mm_setup_dma_pools - Set up dma buffer pools per adapter - * * @adp : Adapter softstate * * We maintain a pool of dma buffers per each adapter. Each pool has one @@ -1093,11 +1085,11 @@ mraid_mm_setup_dma_pools(mraid_mmadp_t *adp) } -/* +/** * mraid_mm_unregister_adp - Unregister routine for low level drivers - * Assume no outstanding ioctls to llds. - * * @unique_id : UID of the adpater + * + * Assumes no outstanding ioctls to llds. */ int mraid_mm_unregister_adp(uint32_t unique_id) @@ -1131,7 +1123,6 @@ mraid_mm_unregister_adp(uint32_t unique_id) /** * mraid_mm_free_adp_resources - Free adapter softstate - * * @adp : Adapter softstate */ static void @@ -1162,7 +1153,6 @@ mraid_mm_free_adp_resources(mraid_mmadp_t *adp) /** * mraid_mm_teardown_dma_pools - Free all per adapter dma buffers - * * @adp : Adapter softstate */ static void @@ -1190,7 +1180,7 @@ mraid_mm_teardown_dma_pools(mraid_mmadp_t *adp) } /** - * mraid_mm_init : Module entry point + * mraid_mm_init - Module entry point */ static int __init mraid_mm_init(void) @@ -1214,10 +1204,13 @@ mraid_mm_init(void) } +#ifdef CONFIG_COMPAT /** - * mraid_mm_compat_ioctl : 32bit to 64bit ioctl conversion routine + * mraid_mm_compat_ioctl - 32bit to 64bit ioctl conversion routine + * @filep : file operations pointer (ignored) + * @cmd : ioctl command + * @arg : user ioctl packet */ -#ifdef CONFIG_COMPAT static long mraid_mm_compat_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) @@ -1231,7 +1224,7 @@ mraid_mm_compat_ioctl(struct file *filep, unsigned int cmd, #endif /** - * mraid_mm_exit : Module exit point + * mraid_mm_exit - Module exit point */ static void __exit mraid_mm_exit(void) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 55eddcf8eb156896138d07e75ce79f362e65aadf..cacb3ad92527cd44eac2a31a7b4007fdaac4ee17 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -15,7 +15,7 @@ #ifndef LSI_MEGARAID_SAS_H #define LSI_MEGARAID_SAS_H -/** +/* * MegaRAID SAS Driver meta data */ #define MEGASAS_VERSION "00.00.03.05" @@ -40,7 +40,7 @@ * "message frames" */ -/** +/* * FW posts its state in upper 4 bits of outbound_msg_0 register */ #define MFI_STATE_MASK 0xF0000000 @@ -58,7 +58,7 @@ #define MEGAMFI_FRAME_SIZE 64 -/** +/* * During FW init, clear pending cmds & reset state using inbound_msg_0 * * ABORT : Abort all pending cmds @@ -78,7 +78,7 @@ MFI_INIT_MFIMODE| \ MFI_INIT_ABORT -/** +/* * MFI frame flags */ #define MFI_FRAME_POST_IN_REPLY_QUEUE 0x0000 @@ -92,12 +92,12 @@ #define MFI_FRAME_DIR_READ 0x0010 #define MFI_FRAME_DIR_BOTH 0x0018 -/** +/* * Definition for cmd_status */ #define MFI_CMD_STATUS_POLL_MODE 0xFF -/** +/* * MFI command opcodes */ #define MFI_CMD_INIT 0x00 @@ -128,7 +128,7 @@ #define MR_DCMD_CLUSTER_RESET_ALL 0x08010100 #define MR_DCMD_CLUSTER_RESET_LD 0x08010200 -/** +/* * MFI command completion codes */ enum MFI_STAT { diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h index 625ca97da52d526893e690a85c805b88f5d2817c..9102cbdf13594321724195fba9f80b907b4d9ca0 100644 --- a/drivers/scsi/pcmcia/nsp_cs.h +++ b/drivers/scsi/pcmcia/nsp_cs.h @@ -290,7 +290,6 @@ typedef struct _nsp_hw_data { #endif } nsp_hw_data; - /**************************************************************************** * */ @@ -302,22 +301,13 @@ static int nsp_cs_config (struct pcmcia_device *link); /* Linux SCSI subsystem specific functions */ static struct Scsi_Host *nsp_detect (struct scsi_host_template *sht); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -static int nsp_detect_old (struct scsi_host_template *sht); -static int nsp_release_old(struct Scsi_Host *shpnt); -#endif static const char *nsp_info (struct Scsi_Host *shpnt); static int nsp_proc_info ( -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) struct Scsi_Host *host, -#endif char *buffer, char **start, off_t offset, int length, -#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) - int hostno, -#endif int inout); static int nsp_queuecommand(struct scsi_cmnd *SCpnt, void (* done)(struct scsi_cmnd *SCpnt)); @@ -356,7 +346,6 @@ static struct Scsi_Host *nsp_detect(struct scsi_host_template *sht); static int __init nsp_cs_init(void); static void __exit nsp_cs_exit(void); - /* Debug */ #ifdef NSP_DEBUG static void show_command (struct scsi_cmnd *SCpnt); @@ -401,7 +390,6 @@ enum _burst_mode { BURST_MEM32 = 2, }; - /************************************************************************** * SCSI messaage */ @@ -413,62 +401,8 @@ enum _burst_mode { #define MSG_EXT_SDTR 0x01 - -/************************************************************************** - * Compatibility functions - */ - -/* for Kernel 2.4 */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) -# define scsi_register_host(template) scsi_register_module(MODULE_SCSI_HA, template) -# define scsi_unregister_host(template) scsi_unregister_module(MODULE_SCSI_HA, template) -# define scsi_host_put(host) scsi_unregister(host) - -typedef void irqreturn_t; -# define IRQ_NONE /* */ -# define IRQ_HANDLED /* */ -# define IRQ_RETVAL(x) /* */ - -/* This is ad-hoc version of scsi_host_get_next() */ -static inline struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *host) -{ - if (host == NULL) { - return scsi_hostlist; - } else { - return host->next; - } -} - -/* This is ad-hoc version of scsi_host_hn_get() */ -static inline struct Scsi_Host *scsi_host_hn_get(unsigned short hostno) -{ - struct Scsi_Host *host; - - for (host = scsi_host_get_next(NULL); host != NULL; - host = scsi_host_get_next(host)) { - if (host->host_no == hostno) { - break; - } - } - - return host; -} - -static void cs_error(struct pcmcia_device *handle, int func, int ret) -{ - error_info_t err = { func, ret }; - pcmcia_report_error(handle, &err); -} - -/* scatter-gather table */ -# define BUFFER_ADDR (SCpnt->SCp.buffer->address) -#endif - -/* for Kernel 2.6 */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) /* scatter-gather table */ # define BUFFER_ADDR ((char *)((unsigned int)(SCpnt->SCp.buffer->page) + SCpnt->SCp.buffer->offset)) -#endif #endif /*__nsp_cs__*/ /* end */ diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 7b18a6c7b7eb0de125e2cd7bfb2581c786378de5..8081b637d97e06550253eb0ddb12bfba0ef27ba5 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -140,6 +140,8 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off, ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); spin_unlock_irqrestore(&ha->hardware_lock, flags); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + return (count); } @@ -653,6 +655,43 @@ qla2x00_beacon_store(struct class_device *cdev, const char *buf, return count; } +static ssize_t +qla2x00_optrom_bios_version_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + + return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1], + ha->bios_revision[0]); +} + +static ssize_t +qla2x00_optrom_efi_version_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + + return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1], + ha->efi_revision[0]); +} + +static ssize_t +qla2x00_optrom_fcode_version_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + + return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fcode_revision[1], + ha->fcode_revision[0]); +} + +static ssize_t +qla2x00_optrom_fw_version_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + + return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d %d\n", + ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2], + ha->fw_revision[3]); +} + static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL); static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); @@ -669,6 +708,14 @@ static CLASS_DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show, qla2x00_zio_timer_store); static CLASS_DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show, qla2x00_beacon_store); +static CLASS_DEVICE_ATTR(optrom_bios_version, S_IRUGO, + qla2x00_optrom_bios_version_show, NULL); +static CLASS_DEVICE_ATTR(optrom_efi_version, S_IRUGO, + qla2x00_optrom_efi_version_show, NULL); +static CLASS_DEVICE_ATTR(optrom_fcode_version, S_IRUGO, + qla2x00_optrom_fcode_version_show, NULL); +static CLASS_DEVICE_ATTR(optrom_fw_version, S_IRUGO, + qla2x00_optrom_fw_version_show, NULL); struct class_device_attribute *qla2x00_host_attrs[] = { &class_device_attr_driver_version, @@ -683,6 +730,10 @@ struct class_device_attribute *qla2x00_host_attrs[] = { &class_device_attr_zio, &class_device_attr_zio_timer, &class_device_attr_beacon, + &class_device_attr_optrom_bios_version, + &class_device_attr_optrom_efi_version, + &class_device_attr_optrom_fcode_version, + &class_device_attr_optrom_fw_version, NULL, }; @@ -836,21 +887,24 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) link_stat_t stat_buf; struct fc_host_statistics *pfc_host_stat; + rval = QLA_FUNCTION_FAILED; pfc_host_stat = &ha->fc_host_stat; memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf, sizeof(stat_buf) / 4, mb_stat); - } else { + } else if (atomic_read(&ha->loop_state) == LOOP_READY && + !test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) && + !test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) && + !ha->dpc_active) { + /* Must be in a 'READY' state for statistics retrieval. */ rval = qla2x00_get_link_status(ha, ha->loop_id, &stat_buf, mb_stat); } - if (rval != 0) { - qla_printk(KERN_WARNING, ha, - "Unable to retrieve host statistics (%d).\n", mb_stat[0]); - return pfc_host_stat; - } + + if (rval != QLA_SUCCESS) + goto done; pfc_host_stat->link_failure_count = stat_buf.link_fail_cnt; pfc_host_stat->loss_of_sync_count = stat_buf.loss_sync_cnt; @@ -858,7 +912,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) pfc_host_stat->prim_seq_protocol_err_count = stat_buf.prim_seq_err_cnt; pfc_host_stat->invalid_tx_word_count = stat_buf.inval_xmit_word_cnt; pfc_host_stat->invalid_crc_count = stat_buf.inval_crc_cnt; - +done: return pfc_host_stat; } diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 2c10130d9e03fe2a037f361ed80ef80963aa8f8b..05f4f2a378eb6d14635f2e8e7ee5f0db904565d4 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2045,6 +2045,29 @@ struct isp_operations { uint32_t, uint32_t); int (*write_optrom) (struct scsi_qla_host *, uint8_t *, uint32_t, uint32_t); + + int (*get_flash_version) (struct scsi_qla_host *, void *); +}; + +/* MSI-X Support *************************************************************/ + +#define QLA_MSIX_CHIP_REV_24XX 3 +#define QLA_MSIX_FW_MODE(m) (((m) & (BIT_7|BIT_8|BIT_9)) >> 7) +#define QLA_MSIX_FW_MODE_1(m) (QLA_MSIX_FW_MODE(m) == 1) + +#define QLA_MSIX_DEFAULT 0x00 +#define QLA_MSIX_RSP_Q 0x01 + +#define QLA_MSIX_ENTRIES 2 +#define QLA_MIDX_DEFAULT 0 +#define QLA_MIDX_RSP_Q 1 + +struct scsi_qla_host; + +struct qla_msix_entry { + int have_irq; + uint16_t msix_vector; + uint16_t msix_entry; }; /* @@ -2077,6 +2100,7 @@ typedef struct scsi_qla_host { uint32_t enable_lip_full_login :1; uint32_t enable_target_reset :1; uint32_t enable_led_scheme :1; + uint32_t inta_enabled :1; uint32_t msi_enabled :1; uint32_t msix_enabled :1; uint32_t disable_serdes :1; @@ -2316,8 +2340,6 @@ typedef struct scsi_qla_host { #define MBX_INTR_WAIT 2 #define MBX_UPDATE_FLASH_ACTIVE 3 - spinlock_t mbx_reg_lock; /* Mbx Cmd Register Lock */ - struct semaphore mbx_cmd_sem; /* Serialialize mbx access */ struct semaphore mbx_intr_sem; /* Used for completion notification */ @@ -2358,6 +2380,7 @@ typedef struct scsi_qla_host { uint8_t host_str[16]; uint32_t pci_attr; + uint16_t chip_revision; uint16_t product_id[4]; @@ -2379,6 +2402,15 @@ typedef struct scsi_qla_host { #define QLA_SREADING 1 #define QLA_SWRITING 2 + /* PCI expansion ROM image information. */ +#define ROM_CODE_TYPE_BIOS 0 +#define ROM_CODE_TYPE_FCODE 1 +#define ROM_CODE_TYPE_EFI 3 + uint8_t bios_revision[2]; + uint8_t efi_revision[2]; + uint8_t fcode_revision[16]; + uint32_t fw_revision[4]; + /* Needed for BEACON */ uint16_t beacon_blink_led; uint8_t beacon_color_state; @@ -2391,6 +2423,8 @@ typedef struct scsi_qla_host { uint16_t zio_mode; uint16_t zio_timer; struct fc_host_statistics fc_host_stat; + + struct qla_msix_entry msix_entries[QLA_MSIX_ENTRIES]; } scsi_qla_host_t; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index e4dd12f4b80eaf014d84f9e837a9cc8c3901ab12..74544ae4b0e270128de9976c4397b31703802dad 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -224,6 +224,9 @@ extern irqreturn_t qla24xx_intr_handler(int, void *); extern void qla2x00_process_response_queue(struct scsi_qla_host *); extern void qla24xx_process_response_queue(struct scsi_qla_host *); +extern int qla2x00_request_irqs(scsi_qla_host_t *); +extern void qla2x00_free_irqs(scsi_qla_host_t *); + /* * Global Function Prototypes in qla_sup.c source file. */ @@ -259,6 +262,9 @@ extern uint8_t *qla24xx_read_optrom_data(struct scsi_qla_host *, uint8_t *, extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *, uint32_t, uint32_t); +extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *); +extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *); + /* * Global Function Prototypes in qla_dbg.c source file. */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index b3dac26ddba3e50767c852aecaf07921bf4f363a..98c01cd5e1a82a954eef3822ecde52689459d84d 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -65,7 +65,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) ha->flags.reset_active = 0; atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); atomic_set(&ha->loop_state, LOOP_DOWN); - ha->device_flags = 0; + ha->device_flags = DFLG_NO_CABLE; ha->dpc_flags = 0; ha->flags.management_server_logged_in = 0; ha->marker_needed = 0; @@ -77,16 +77,23 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) qla_printk(KERN_INFO, ha, "Configuring PCI space...\n"); rval = ha->isp_ops.pci_config(ha); if (rval) { - DEBUG2(printk("scsi(%ld): Unable to configure PCI space=n", + DEBUG2(printk("scsi(%ld): Unable to configure PCI space.\n", ha->host_no)); return (rval); } ha->isp_ops.reset_chip(ha); + ha->isp_ops.get_flash_version(ha, ha->request_ring); + qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); - ha->isp_ops.nvram_config(ha); + rval = ha->isp_ops.nvram_config(ha); + if (rval) { + DEBUG2(printk("scsi(%ld): Unable to verify NVRAM data.\n", + ha->host_no)); + return rval; + } if (ha->flags.disable_serdes) { /* Mask HBA via NVRAM settings? */ @@ -293,6 +300,8 @@ qla24xx_pci_config(scsi_qla_host_t *ha) d &= ~PCI_ROM_ADDRESS_ENABLE; pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); + pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->chip_revision); + /* Get PCI bus information. */ spin_lock_irqsave(&ha->hardware_lock, flags); ha->pci_attr = RD_REG_DWORD(®->ctrl_status); @@ -1351,6 +1360,39 @@ qla2x00_configure_hba(scsi_qla_host_t *ha) return(rval); } +static inline void +qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *def) +{ + char *st, *en; + uint16_t index; + + if (memcmp(model, BINZERO, len) != 0) { + strncpy(ha->model_number, model, len); + st = en = ha->model_number; + en += len - 1; + while (en > st) { + if (*en != 0x20 && *en != 0x00) + break; + *en-- = '\0'; + } + + index = (ha->pdev->subsystem_device & 0xff); + if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && + index < QLA_MODEL_NAMES) + ha->model_desc = qla2x00_model_name[index * 2 + 1]; + } else { + index = (ha->pdev->subsystem_device & 0xff); + if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && + index < QLA_MODEL_NAMES) { + strcpy(ha->model_number, + qla2x00_model_name[index * 2]); + ha->model_desc = qla2x00_model_name[index * 2 + 1]; + } else { + strcpy(ha->model_number, def); + } + } +} + /* * NVRAM configuration for ISP 2xxx * @@ -1367,7 +1409,6 @@ qla2x00_configure_hba(scsi_qla_host_t *ha) int qla2x00_nvram_config(scsi_qla_host_t *ha) { - int rval; uint8_t chksum = 0; uint16_t cnt; uint8_t *dptr1, *dptr2; @@ -1376,8 +1417,6 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) uint8_t *ptr = (uint8_t *)ha->request_ring; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; - rval = QLA_SUCCESS; - /* Determine NVRAM starting address. */ ha->nvram_size = sizeof(nvram_t); ha->nvram_base = 0; @@ -1401,55 +1440,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: " "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0], nv->nvram_version); - qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet " - "invalid -- WWPN) defaults.\n"); - - /* - * Set default initialization control block. - */ - memset(nv, 0, ha->nvram_size); - nv->parameter_block_version = ICB_VERSION; - - if (IS_QLA23XX(ha)) { - nv->firmware_options[0] = BIT_2 | BIT_1; - nv->firmware_options[1] = BIT_7 | BIT_5; - nv->add_firmware_options[0] = BIT_5; - nv->add_firmware_options[1] = BIT_5 | BIT_4; - nv->frame_payload_size = __constant_cpu_to_le16(2048); - nv->special_options[1] = BIT_7; - } else if (IS_QLA2200(ha)) { - nv->firmware_options[0] = BIT_2 | BIT_1; - nv->firmware_options[1] = BIT_7 | BIT_5; - nv->add_firmware_options[0] = BIT_5; - nv->add_firmware_options[1] = BIT_5 | BIT_4; - nv->frame_payload_size = __constant_cpu_to_le16(1024); - } else if (IS_QLA2100(ha)) { - nv->firmware_options[0] = BIT_3 | BIT_1; - nv->firmware_options[1] = BIT_5; - nv->frame_payload_size = __constant_cpu_to_le16(1024); - } - - nv->max_iocb_allocation = __constant_cpu_to_le16(256); - nv->execution_throttle = __constant_cpu_to_le16(16); - nv->retry_count = 8; - nv->retry_delay = 1; - - nv->port_name[0] = 33; - nv->port_name[3] = 224; - nv->port_name[4] = 139; - - nv->login_timeout = 4; - - /* - * Set default host adapter parameters - */ - nv->host_p[1] = BIT_2; - nv->reset_delay = 5; - nv->port_down_retry_count = 8; - nv->max_luns_per_target = __constant_cpu_to_le16(8); - nv->link_down_timeout = 60; - - rval = 1; + return QLA_FUNCTION_FAILED; } #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) @@ -1489,33 +1480,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) strcpy(ha->model_number, "QLA2300"); } } else { - if (rval == 0 && - memcmp(nv->model_number, BINZERO, - sizeof(nv->model_number)) != 0) { - char *st, *en; - - strncpy(ha->model_number, nv->model_number, - sizeof(nv->model_number)); - st = en = ha->model_number; - en += sizeof(nv->model_number) - 1; - while (en > st) { - if (*en != 0x20 && *en != 0x00) - break; - *en-- = '\0'; - } - } else { - uint16_t index; - - index = (ha->pdev->subsystem_device & 0xff); - if (index < QLA_MODEL_NAMES) { - strcpy(ha->model_number, - qla2x00_model_name[index * 2]); - ha->model_desc = - qla2x00_model_name[index * 2 + 1]; - } else { - strcpy(ha->model_number, "QLA23xx"); - } - } + qla2x00_set_model_info(ha, nv->model_number, + sizeof(nv->model_number), "QLA23xx"); } } else if (IS_QLA2200(ha)) { nv->firmware_options[0] |= BIT_2; @@ -1687,11 +1653,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) } } - if (rval) { - DEBUG2_3(printk(KERN_WARNING - "scsi(%ld): NVRAM configuration failed!\n", ha->host_no)); - } - return (rval); + return QLA_SUCCESS; } static void @@ -3107,7 +3069,11 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) } spin_unlock_irqrestore(&ha->hardware_lock, flags); - ha->isp_ops.nvram_config(ha); + ha->isp_ops.get_flash_version(ha, ha->request_ring); + + rval = ha->isp_ops.nvram_config(ha); + if (rval) + goto isp_abort_retry; if (!qla2x00_restart_isp(ha)) { clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); @@ -3137,6 +3103,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) } } } else { /* failed the ISP abort */ +isp_abort_retry: ha->flags.online = 1; if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) { if (ha->isp_abort_cnt == 0) { @@ -3326,7 +3293,6 @@ qla24xx_reset_adapter(scsi_qla_host_t *ha) int qla24xx_nvram_config(scsi_qla_host_t *ha) { - int rval; struct init_cb_24xx *icb; struct nvram_24xx *nv; uint32_t *dptr; @@ -3334,7 +3300,6 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) uint32_t chksum; uint16_t cnt; - rval = QLA_SUCCESS; icb = (struct init_cb_24xx *)ha->init_cb; nv = (struct nvram_24xx *)ha->request_ring; @@ -3367,51 +3332,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: " "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0], le16_to_cpu(nv->nvram_version)); - qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet " - "invalid -- WWPN) defaults.\n"); - - /* - * Set default initialization control block. - */ - memset(nv, 0, ha->nvram_size); - nv->nvram_version = __constant_cpu_to_le16(ICB_VERSION); - nv->version = __constant_cpu_to_le16(ICB_VERSION); - nv->frame_payload_size = __constant_cpu_to_le16(2048); - nv->execution_throttle = __constant_cpu_to_le16(0xFFFF); - nv->exchange_count = __constant_cpu_to_le16(0); - nv->hard_address = __constant_cpu_to_le16(124); - nv->port_name[0] = 0x21; - nv->port_name[1] = 0x00 + PCI_FUNC(ha->pdev->devfn); - nv->port_name[2] = 0x00; - nv->port_name[3] = 0xe0; - nv->port_name[4] = 0x8b; - nv->port_name[5] = 0x1c; - nv->port_name[6] = 0x55; - nv->port_name[7] = 0x86; - nv->node_name[0] = 0x20; - nv->node_name[1] = 0x00; - nv->node_name[2] = 0x00; - nv->node_name[3] = 0xe0; - nv->node_name[4] = 0x8b; - nv->node_name[5] = 0x1c; - nv->node_name[6] = 0x55; - nv->node_name[7] = 0x86; - nv->login_retry_count = __constant_cpu_to_le16(8); - nv->interrupt_delay_timer = __constant_cpu_to_le16(0); - nv->login_timeout = __constant_cpu_to_le16(0); - nv->firmware_options_1 = - __constant_cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1); - nv->firmware_options_2 = __constant_cpu_to_le32(2 << 4); - nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12); - nv->firmware_options_3 = __constant_cpu_to_le32(2 << 13); - nv->host_p = __constant_cpu_to_le32(BIT_11|BIT_10); - nv->efi_parameters = __constant_cpu_to_le32(0); - nv->reset_delay = 5; - nv->max_luns_per_target = __constant_cpu_to_le16(128); - nv->port_down_retry_count = __constant_cpu_to_le16(30); - nv->link_down_timeout = __constant_cpu_to_le16(30); - - rval = 1; + return QLA_FUNCTION_FAILED; } /* Reset Initialization control block */ @@ -3438,25 +3359,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) /* * Setup driver NVRAM options. */ - if (memcmp(nv->model_name, BINZERO, sizeof(nv->model_name)) != 0) { - char *st, *en; - uint16_t index; - - strncpy(ha->model_number, nv->model_name, - sizeof(nv->model_name)); - st = en = ha->model_number; - en += sizeof(nv->model_name) - 1; - while (en > st) { - if (*en != 0x20 && *en != 0x00) - break; - *en-- = '\0'; - } - - index = (ha->pdev->subsystem_device & 0xff); - if (index < QLA_MODEL_NAMES) - ha->model_desc = qla2x00_model_name[index * 2 + 1]; - } else - strcpy(ha->model_number, "QLA2462"); + qla2x00_set_model_info(ha, nv->model_name, sizeof(nv->model_name), + "QLA2462"); /* Use alternate WWN? */ if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { @@ -3575,11 +3479,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) ha->flags.process_response_queue = 1; } - if (rval) { - DEBUG2_3(printk(KERN_WARNING - "scsi(%ld): NVRAM configuration failed!\n", ha->host_no)); - } - return (rval); + return QLA_SUCCESS; } static int diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 39fd17b05be5ada3d3da55515c2d89bba857cd71..d4885616cd39c19077e72b2f083f563ec5cb2ad9 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -86,12 +86,8 @@ qla2100_intr_handler(int irq, void *dev_id) if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && (status & MBX_INTERRUPT) && ha->flags.mbox_int) { - spin_lock_irqsave(&ha->mbx_reg_lock, flags); - set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); up(&ha->mbx_intr_sem); - - spin_unlock_irqrestore(&ha->mbx_reg_lock, flags); } return (IRQ_HANDLED); @@ -199,12 +195,8 @@ qla2300_intr_handler(int irq, void *dev_id) if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && (status & MBX_INTERRUPT) && ha->flags.mbox_int) { - spin_lock_irqsave(&ha->mbx_reg_lock, flags); - set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); up(&ha->mbx_intr_sem); - - spin_unlock_irqrestore(&ha->mbx_reg_lock, flags); } return (IRQ_HANDLED); @@ -654,10 +646,8 @@ qla2x00_ramp_up_queue_depth(scsi_qla_host_t *ha, srb_t *sp) fcport->last_queue_full + ql2xqfullrampup * HZ)) return; - spin_unlock_irq(&ha->hardware_lock); starget_for_each_device(sdev->sdev_target, fcport, qla2x00_adjust_sdev_qdepth_up); - spin_lock_irq(&ha->hardware_lock); } /** @@ -927,10 +917,8 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) /* Adjust queue depth for all luns on the port. */ fcport->last_queue_full = jiffies; - spin_unlock_irq(&ha->hardware_lock); starget_for_each_device(cp->device->sdev_target, fcport, qla2x00_adjust_sdev_qdepth_down); - spin_lock_irq(&ha->hardware_lock); break; } if (lscsi_status != SS_CHECK_CONDITION) @@ -995,6 +983,22 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) if (lscsi_status != 0) { cp->result = DID_OK << 16 | lscsi_status; + if (lscsi_status == SAM_STAT_TASK_SET_FULL) { + DEBUG2(printk(KERN_INFO + "scsi(%ld): QUEUE FULL status detected " + "0x%x-0x%x.\n", ha->host_no, comp_status, + scsi_status)); + + /* + * Adjust queue depth for all luns on the + * port. + */ + fcport->last_queue_full = jiffies; + starget_for_each_device( + cp->device->sdev_target, fcport, + qla2x00_adjust_sdev_qdepth_down); + break; + } if (lscsi_status != SS_CHECK_CONDITION) break; @@ -1482,12 +1486,8 @@ qla24xx_intr_handler(int irq, void *dev_id) if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && (status & MBX_INTERRUPT) && ha->flags.mbox_int) { - spin_lock_irqsave(&ha->mbx_reg_lock, flags); - set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); up(&ha->mbx_intr_sem); - - spin_unlock_irqrestore(&ha->mbx_reg_lock, flags); } return IRQ_HANDLED; @@ -1536,3 +1536,216 @@ qla24xx_ms_entry(scsi_qla_host_t *ha, struct ct_entry_24xx *pkt) qla2x00_sp_compl(ha, sp); } +static irqreturn_t +qla24xx_msix_rsp_q(int irq, void *dev_id) +{ + scsi_qla_host_t *ha; + struct device_reg_24xx __iomem *reg; + unsigned long flags; + + ha = dev_id; + reg = &ha->iobase->isp24; + + spin_lock_irqsave(&ha->hardware_lock, flags); + + qla24xx_process_response_queue(ha); + + WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); + RD_REG_DWORD_RELAXED(®->hccr); + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return IRQ_HANDLED; +} + +static irqreturn_t +qla24xx_msix_default(int irq, void *dev_id) +{ + scsi_qla_host_t *ha; + struct device_reg_24xx __iomem *reg; + int status; + unsigned long flags; + unsigned long iter; + uint32_t stat; + uint32_t hccr; + uint16_t mb[4]; + + ha = dev_id; + reg = &ha->iobase->isp24; + status = 0; + + spin_lock_irqsave(&ha->hardware_lock, flags); + for (iter = 50; iter--; ) { + stat = RD_REG_DWORD(®->host_status); + if (stat & HSRX_RISC_PAUSED) { + hccr = RD_REG_DWORD(®->hccr); + + qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " + "Dumping firmware!\n", hccr); + ha->isp_ops.fw_dump(ha, 1); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + break; + } else if ((stat & HSRX_RISC_INT) == 0) + break; + + switch (stat & 0xff) { + case 0x1: + case 0x2: + case 0x10: + case 0x11: + qla24xx_mbx_completion(ha, MSW(stat)); + status |= MBX_INTERRUPT; + + break; + case 0x12: + mb[0] = MSW(stat); + mb[1] = RD_REG_WORD(®->mailbox1); + mb[2] = RD_REG_WORD(®->mailbox2); + mb[3] = RD_REG_WORD(®->mailbox3); + qla2x00_async_event(ha, mb); + break; + case 0x13: + qla24xx_process_response_queue(ha); + break; + default: + DEBUG2(printk("scsi(%ld): Unrecognized interrupt type " + "(%d).\n", + ha->host_no, stat & 0xff)); + break; + } + WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); + RD_REG_DWORD_RELAXED(®->hccr); + } + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && + (status & MBX_INTERRUPT) && ha->flags.mbox_int) { + set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + up(&ha->mbx_intr_sem); + } + + return IRQ_HANDLED; +} + +/* Interrupt handling helpers. */ + +struct qla_init_msix_entry { + uint16_t entry; + uint16_t index; + const char *name; + irqreturn_t (*handler)(int, void *); +}; + +static struct qla_init_msix_entry imsix_entries[QLA_MSIX_ENTRIES] = { + { QLA_MSIX_DEFAULT, QLA_MIDX_DEFAULT, + "qla2xxx (default)", qla24xx_msix_default }, + + { QLA_MSIX_RSP_Q, QLA_MIDX_RSP_Q, + "qla2xxx (rsp_q)", qla24xx_msix_rsp_q }, +}; + +static void +qla24xx_disable_msix(scsi_qla_host_t *ha) +{ + int i; + struct qla_msix_entry *qentry; + + for (i = 0; i < QLA_MSIX_ENTRIES; i++) { + qentry = &ha->msix_entries[imsix_entries[i].index]; + if (qentry->have_irq) + free_irq(qentry->msix_vector, ha); + } + pci_disable_msix(ha->pdev); +} + +static int +qla24xx_enable_msix(scsi_qla_host_t *ha) +{ + int i, ret; + struct msix_entry entries[QLA_MSIX_ENTRIES]; + struct qla_msix_entry *qentry; + + for (i = 0; i < QLA_MSIX_ENTRIES; i++) + entries[i].entry = imsix_entries[i].entry; + + ret = pci_enable_msix(ha->pdev, entries, ARRAY_SIZE(entries)); + if (ret) { + qla_printk(KERN_WARNING, ha, + "MSI-X: Failed to enable support -- %d/%d\n", + QLA_MSIX_ENTRIES, ret); + goto msix_out; + } + ha->flags.msix_enabled = 1; + + for (i = 0; i < QLA_MSIX_ENTRIES; i++) { + qentry = &ha->msix_entries[imsix_entries[i].index]; + qentry->msix_vector = entries[i].vector; + qentry->msix_entry = entries[i].entry; + qentry->have_irq = 0; + ret = request_irq(qentry->msix_vector, + imsix_entries[i].handler, 0, imsix_entries[i].name, ha); + if (ret) { + qla_printk(KERN_WARNING, ha, + "MSI-X: Unable to register handler -- %x/%d.\n", + imsix_entries[i].index, ret); + qla24xx_disable_msix(ha); + goto msix_out; + } + qentry->have_irq = 1; + } + +msix_out: + return ret; +} + +int +qla2x00_request_irqs(scsi_qla_host_t *ha) +{ + int ret; + + /* If possible, enable MSI-X. */ + if (!IS_QLA2432(ha)) + goto skip_msix; + + if (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX || + !QLA_MSIX_FW_MODE_1(ha->fw_attributes)) { + DEBUG2(qla_printk(KERN_WARNING, ha, + "MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n", + ha->chip_revision, ha->fw_attributes)); + + goto skip_msix; + } + + ret = qla24xx_enable_msix(ha); + if (!ret) { + DEBUG2(qla_printk(KERN_INFO, ha, + "MSI-X: Enabled (0x%X, 0x%X).\n", ha->chip_revision, + ha->fw_attributes)); + return ret; + } + qla_printk(KERN_WARNING, ha, + "MSI-X: Falling back-to INTa mode -- %d.\n", ret); +skip_msix: + ret = request_irq(ha->pdev->irq, ha->isp_ops.intr_handler, + IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha); + if (!ret) { + ha->flags.inta_enabled = 1; + ha->host->irq = ha->pdev->irq; + } else { + qla_printk(KERN_WARNING, ha, + "Failed to reserve interrupt %d already in use.\n", + ha->pdev->irq); + } + + return ret; +} + +void +qla2x00_free_irqs(scsi_qla_host_t *ha) +{ + + if (ha->flags.msix_enabled) + qla24xx_disable_msix(ha); + else if (ha->flags.inta_enabled) + free_irq(ha->host->irq, ha); +} diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 077e5789beeb0870742c5720e8d13e5a5d58c9bf..83376f6ac3dbb0c108e9ed5fd986dcc879d06739 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -55,7 +55,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) uint16_t __iomem *optr; uint32_t cnt; uint32_t mboxes; - unsigned long mbx_flags = 0; unsigned long wait_time; rval = QLA_SUCCESS; @@ -81,10 +80,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) /* Save mailbox command for debug */ ha->mcp = mcp; - /* Try to get mailbox register access */ - if (!abort_active) - spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags); - DEBUG11(printk("scsi(%ld): prepare to issue mbox cmd=0x%x.\n", ha->host_no, mcp->mb[0])); @@ -161,9 +156,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); spin_unlock_irqrestore(&ha->hardware_lock, flags); - if (!abort_active) - spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags); - /* Wait for either the timer to expire * or the mbox completion interrupt */ @@ -184,8 +176,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) else WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); spin_unlock_irqrestore(&ha->hardware_lock, flags); - if (!abort_active) - spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags); wait_time = jiffies + mcp->tov * HZ; /* wait at most tov secs */ while (!ha->flags.mbox_int) { @@ -201,9 +191,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) } /* while */ } - if (!abort_active) - spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags); - /* Check whether we timed out */ if (ha->flags.mbox_int) { uint16_t *iptr2; @@ -256,9 +243,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) rval = QLA_FUNCTION_TIMEOUT; } - if (!abort_active) - spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags); - ha->flags.mbox_busy = 0; /* Clean up */ @@ -1713,7 +1697,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain, lg->entry_count = 1; lg->nport_handle = cpu_to_le16(loop_id); lg->control_flags = - __constant_cpu_to_le16(LCF_COMMAND_LOGO|LCF_EXPL_LOGO); + __constant_cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO); lg->port_id[0] = al_pa; lg->port_id[1] = area; lg->port_id[2] = domain; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index d6445ae841ba965896c8993fce3ab38ae899f0e4..68f5d24b938b06c28ecf177c6ad6ae71a55a257a 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1485,6 +1485,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->isp_ops.fw_dump = qla2100_fw_dump; ha->isp_ops.read_optrom = qla2x00_read_optrom_data; ha->isp_ops.write_optrom = qla2x00_write_optrom_data; + ha->isp_ops.get_flash_version = qla2x00_get_flash_version; if (IS_QLA2100(ha)) { host->max_id = MAX_TARGETS_2100; ha->mbx_count = MAILBOX_REGISTER_COUNT_2100; @@ -1550,6 +1551,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->isp_ops.beacon_on = qla24xx_beacon_on; ha->isp_ops.beacon_off = qla24xx_beacon_off; ha->isp_ops.beacon_blink = qla24xx_beacon_blink; + ha->isp_ops.get_flash_version = qla24xx_get_flash_version; ha->gid_list_info_size = 8; ha->optrom_size = OPTROM_SIZE_24XX; } @@ -1564,14 +1566,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) INIT_LIST_HEAD(&ha->list); INIT_LIST_HEAD(&ha->fcports); - /* - * These locks are used to prevent more than one CPU - * from modifying the queue at the same time. The - * higher level "host_lock" will reduce most - * contention for these locks. - */ - spin_lock_init(&ha->mbx_reg_lock); - qla2x00_config_dma_addressing(ha); if (qla2x00_mem_alloc(ha)) { qla_printk(KERN_WARNING, ha, @@ -1615,15 +1609,9 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) host->max_lun = MAX_LUNS; host->transportt = qla2xxx_transport_template; - ret = request_irq(pdev->irq, ha->isp_ops.intr_handler, - IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha); - if (ret) { - qla_printk(KERN_WARNING, ha, - "Failed to reserve interrupt %d already in use.\n", - pdev->irq); + ret = qla2x00_request_irqs(ha); + if (ret) goto probe_failed; - } - host->irq = pdev->irq; /* Initialized the timer */ qla2x00_start_timer(ha, qla2x00_timer, WATCH_INTERVAL); @@ -1753,9 +1741,7 @@ qla2x00_free_device(scsi_qla_host_t *ha) qla2x00_mem_free(ha); - /* Detach interrupts */ - if (ha->host->irq) - free_irq(ha->host->irq, ha); + qla2x00_free_irqs(ha); /* release io space registers */ if (ha->iobase) diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 15390ad87456399a774ac65e25a5f519216adf15..ff1dd4175a7f1deb2a8e320e64d98055feca39ef 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -611,7 +611,6 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, flash_conf_to_access_addr(0x0339), (fdata & 0xff00) | ((fdata << 16) & 0xff0000) | ((fdata >> 16) & 0xff)); - fdata = (faddr & sec_mask) << 2; ret = qla24xx_write_flash_dword(ha, conf_addr, (fdata & 0xff00) |((fdata << 16) & 0xff0000) | ((fdata >> 16) & 0xff)); @@ -1383,6 +1382,29 @@ qla2x00_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id, qla2x00_write_flash_byte(ha, 0x5555, 0xf0); } +static void +qla2x00_read_flash_data(scsi_qla_host_t *ha, uint8_t *tmp_buf, uint32_t saddr, + uint32_t length) +{ + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + uint32_t midpoint, ilength; + uint8_t data; + + midpoint = length / 2; + + WRT_REG_WORD(®->nvram, 0); + RD_REG_WORD(®->nvram); + for (ilength = 0; ilength < length; saddr++, ilength++, tmp_buf++) { + if (ilength == midpoint) { + WRT_REG_WORD(®->nvram, NVR_SELECT); + RD_REG_WORD(®->nvram); + } + data = qla2x00_read_flash_byte(ha, saddr); + if (saddr % 100) + udelay(10); + *tmp_buf = data; + } +} static inline void qla2x00_suspend_hba(struct scsi_qla_host *ha) @@ -1722,3 +1744,327 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, return rval; } + +/** + * qla2x00_get_fcode_version() - Determine an FCODE image's version. + * @ha: HA context + * @pcids: Pointer to the FCODE PCI data structure + * + * The process of retrieving the FCODE version information is at best + * described as interesting. + * + * Within the first 100h bytes of the image an ASCII string is present + * which contains several pieces of information including the FCODE + * version. Unfortunately it seems the only reliable way to retrieve + * the version is by scanning for another sentinel within the string, + * the FCODE build date: + * + * ... 2.00.02 10/17/02 ... + * + * Returns QLA_SUCCESS on successful retrieval of version. + */ +static void +qla2x00_get_fcode_version(scsi_qla_host_t *ha, uint32_t pcids) +{ + int ret = QLA_FUNCTION_FAILED; + uint32_t istart, iend, iter, vend; + uint8_t do_next, rbyte, *vbyte; + + memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); + + /* Skip the PCI data structure. */ + istart = pcids + + ((qla2x00_read_flash_byte(ha, pcids + 0x0B) << 8) | + qla2x00_read_flash_byte(ha, pcids + 0x0A)); + iend = istart + 0x100; + do { + /* Scan for the sentinel date string...eeewww. */ + do_next = 0; + iter = istart; + while ((iter < iend) && !do_next) { + iter++; + if (qla2x00_read_flash_byte(ha, iter) == '/') { + if (qla2x00_read_flash_byte(ha, iter + 2) == + '/') + do_next++; + else if (qla2x00_read_flash_byte(ha, + iter + 3) == '/') + do_next++; + } + } + if (!do_next) + break; + + /* Backtrack to previous ' ' (space). */ + do_next = 0; + while ((iter > istart) && !do_next) { + iter--; + if (qla2x00_read_flash_byte(ha, iter) == ' ') + do_next++; + } + if (!do_next) + break; + + /* + * Mark end of version tag, and find previous ' ' (space) or + * string length (recent FCODE images -- major hack ahead!!!). + */ + vend = iter - 1; + do_next = 0; + while ((iter > istart) && !do_next) { + iter--; + rbyte = qla2x00_read_flash_byte(ha, iter); + if (rbyte == ' ' || rbyte == 0xd || rbyte == 0x10) + do_next++; + } + if (!do_next) + break; + + /* Mark beginning of version tag, and copy data. */ + iter++; + if ((vend - iter) && + ((vend - iter) < sizeof(ha->fcode_revision))) { + vbyte = ha->fcode_revision; + while (iter <= vend) { + *vbyte++ = qla2x00_read_flash_byte(ha, iter); + iter++; + } + ret = QLA_SUCCESS; + } + } while (0); + + if (ret != QLA_SUCCESS) + memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); +} + +int +qla2x00_get_flash_version(scsi_qla_host_t *ha, void *mbuf) +{ + int ret = QLA_SUCCESS; + uint8_t code_type, last_image; + uint32_t pcihdr, pcids; + uint8_t *dbyte; + uint16_t *dcode; + + if (!ha->pio_address || !mbuf) + return QLA_FUNCTION_FAILED; + + memset(ha->bios_revision, 0, sizeof(ha->bios_revision)); + memset(ha->efi_revision, 0, sizeof(ha->efi_revision)); + memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); + memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); + + qla2x00_flash_enable(ha); + + /* Begin with first PCI expansion ROM header. */ + pcihdr = 0; + last_image = 1; + do { + /* Verify PCI expansion ROM header. */ + if (qla2x00_read_flash_byte(ha, pcihdr) != 0x55 || + qla2x00_read_flash_byte(ha, pcihdr + 0x01) != 0xaa) { + /* No signature */ + DEBUG2(printk("scsi(%ld): No matching ROM " + "signature.\n", ha->host_no)); + ret = QLA_FUNCTION_FAILED; + break; + } + + /* Locate PCI data structure. */ + pcids = pcihdr + + ((qla2x00_read_flash_byte(ha, pcihdr + 0x19) << 8) | + qla2x00_read_flash_byte(ha, pcihdr + 0x18)); + + /* Validate signature of PCI data structure. */ + if (qla2x00_read_flash_byte(ha, pcids) != 'P' || + qla2x00_read_flash_byte(ha, pcids + 0x1) != 'C' || + qla2x00_read_flash_byte(ha, pcids + 0x2) != 'I' || + qla2x00_read_flash_byte(ha, pcids + 0x3) != 'R') { + /* Incorrect header. */ + DEBUG2(printk("%s(): PCI data struct not found " + "pcir_adr=%x.\n", __func__, pcids)); + ret = QLA_FUNCTION_FAILED; + break; + } + + /* Read version */ + code_type = qla2x00_read_flash_byte(ha, pcids + 0x14); + switch (code_type) { + case ROM_CODE_TYPE_BIOS: + /* Intel x86, PC-AT compatible. */ + ha->bios_revision[0] = + qla2x00_read_flash_byte(ha, pcids + 0x12); + ha->bios_revision[1] = + qla2x00_read_flash_byte(ha, pcids + 0x13); + DEBUG3(printk("%s(): read BIOS %d.%d.\n", __func__, + ha->bios_revision[1], ha->bios_revision[0])); + break; + case ROM_CODE_TYPE_FCODE: + /* Open Firmware standard for PCI (FCode). */ + /* Eeeewww... */ + qla2x00_get_fcode_version(ha, pcids); + break; + case ROM_CODE_TYPE_EFI: + /* Extensible Firmware Interface (EFI). */ + ha->efi_revision[0] = + qla2x00_read_flash_byte(ha, pcids + 0x12); + ha->efi_revision[1] = + qla2x00_read_flash_byte(ha, pcids + 0x13); + DEBUG3(printk("%s(): read EFI %d.%d.\n", __func__, + ha->efi_revision[1], ha->efi_revision[0])); + break; + default: + DEBUG2(printk("%s(): Unrecognized code type %x at " + "pcids %x.\n", __func__, code_type, pcids)); + break; + } + + last_image = qla2x00_read_flash_byte(ha, pcids + 0x15) & BIT_7; + + /* Locate next PCI expansion ROM. */ + pcihdr += ((qla2x00_read_flash_byte(ha, pcids + 0x11) << 8) | + qla2x00_read_flash_byte(ha, pcids + 0x10)) * 512; + } while (!last_image); + + if (IS_QLA2322(ha)) { + /* Read firmware image information. */ + memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); + dbyte = mbuf; + memset(dbyte, 0, 8); + dcode = (uint16_t *)dbyte; + + qla2x00_read_flash_data(ha, dbyte, FA_RISC_CODE_ADDR * 4 + 10, + 8); + DEBUG3(printk("%s(%ld): dumping fw ver from flash:\n", + __func__, ha->host_no)); + DEBUG3(qla2x00_dump_buffer((uint8_t *)dbyte, 8)); + + if ((dcode[0] == 0xffff && dcode[1] == 0xffff && + dcode[2] == 0xffff && dcode[3] == 0xffff) || + (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && + dcode[3] == 0)) { + DEBUG2(printk("%s(): Unrecognized fw revision at " + "%x.\n", __func__, FA_RISC_CODE_ADDR * 4)); + } else { + /* values are in big endian */ + ha->fw_revision[0] = dbyte[0] << 16 | dbyte[1]; + ha->fw_revision[1] = dbyte[2] << 16 | dbyte[3]; + ha->fw_revision[2] = dbyte[4] << 16 | dbyte[5]; + } + } + + qla2x00_flash_disable(ha); + + return ret; +} + +int +qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf) +{ + int ret = QLA_SUCCESS; + uint32_t pcihdr, pcids; + uint32_t *dcode; + uint8_t *bcode; + uint8_t code_type, last_image; + int i; + + if (!mbuf) + return QLA_FUNCTION_FAILED; + + memset(ha->bios_revision, 0, sizeof(ha->bios_revision)); + memset(ha->efi_revision, 0, sizeof(ha->efi_revision)); + memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); + memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); + + dcode = mbuf; + + /* Begin with first PCI expansion ROM header. */ + pcihdr = 0; + last_image = 1; + do { + /* Verify PCI expansion ROM header. */ + qla24xx_read_flash_data(ha, dcode, pcihdr >> 2, 0x20); + bcode = mbuf + (pcihdr % 4); + if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) { + /* No signature */ + DEBUG2(printk("scsi(%ld): No matching ROM " + "signature.\n", ha->host_no)); + ret = QLA_FUNCTION_FAILED; + break; + } + + /* Locate PCI data structure. */ + pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]); + + qla24xx_read_flash_data(ha, dcode, pcids >> 2, 0x20); + bcode = mbuf + (pcihdr % 4); + + /* Validate signature of PCI data structure. */ + if (bcode[0x0] != 'P' || bcode[0x1] != 'C' || + bcode[0x2] != 'I' || bcode[0x3] != 'R') { + /* Incorrect header. */ + DEBUG2(printk("%s(): PCI data struct not found " + "pcir_adr=%x.\n", __func__, pcids)); + ret = QLA_FUNCTION_FAILED; + break; + } + + /* Read version */ + code_type = bcode[0x14]; + switch (code_type) { + case ROM_CODE_TYPE_BIOS: + /* Intel x86, PC-AT compatible. */ + ha->bios_revision[0] = bcode[0x12]; + ha->bios_revision[1] = bcode[0x13]; + DEBUG3(printk("%s(): read BIOS %d.%d.\n", __func__, + ha->bios_revision[1], ha->bios_revision[0])); + break; + case ROM_CODE_TYPE_FCODE: + /* Open Firmware standard for PCI (FCode). */ + ha->fcode_revision[0] = bcode[0x12]; + ha->fcode_revision[1] = bcode[0x13]; + DEBUG3(printk("%s(): read FCODE %d.%d.\n", __func__, + ha->fcode_revision[1], ha->fcode_revision[0])); + break; + case ROM_CODE_TYPE_EFI: + /* Extensible Firmware Interface (EFI). */ + ha->efi_revision[0] = bcode[0x12]; + ha->efi_revision[1] = bcode[0x13]; + DEBUG3(printk("%s(): read EFI %d.%d.\n", __func__, + ha->efi_revision[1], ha->efi_revision[0])); + break; + default: + DEBUG2(printk("%s(): Unrecognized code type %x at " + "pcids %x.\n", __func__, code_type, pcids)); + break; + } + + last_image = bcode[0x15] & BIT_7; + + /* Locate next PCI expansion ROM. */ + pcihdr += ((bcode[0x11] << 8) | bcode[0x10]) * 512; + } while (!last_image); + + /* Read firmware image information. */ + memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); + dcode = mbuf; + + qla24xx_read_flash_data(ha, dcode, FA_RISC_CODE_ADDR + 4, 4); + for (i = 0; i < 4; i++) + dcode[i] = be32_to_cpu(dcode[i]); + + if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff && + dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) || + (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && + dcode[3] == 0)) { + DEBUG2(printk("%s(): Unrecognized fw version at %x.\n", + __func__, FA_RISC_CODE_ADDR)); + } else { + ha->fw_revision[0] = dcode[0]; + ha->fw_revision[1] = dcode[1]; + ha->fw_revision[2] = dcode[2]; + ha->fw_revision[3] = dcode[3]; + } + + return ret; +} diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 459e0d6bd2b4d67757a57abd435afa5500dfa94d..61347aee55ce3da85fb49bee3db60a11a5f706ea 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.01.07-k4" +#define QLA2XXX_VERSION "8.01.07-k5" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 1 diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 24cffd98ee63546ce716e0277812dda9bafd08d2..f33e2eb9f1b9b657ce0ea582a6007681c53f5b86 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -672,27 +672,6 @@ void __scsi_done(struct scsi_cmnd *cmd) blk_complete_request(rq); } -/* - * Function: scsi_retry_command - * - * Purpose: Send a command back to the low level to be retried. - * - * Notes: This command is always executed in the context of the - * bottom half handler, or the error handler thread. Low - * level drivers should not become re-entrant as a result of - * this. - */ -int scsi_retry_command(struct scsi_cmnd *cmd) -{ - /* - * Zero the sense information from the last time we tried - * this command. - */ - memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); - - return scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY); -} - /* * Function: scsi_finish_command * diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 30ee3d72c02151f0b56ca9b69b9c7d10aff7bbff..5adbbeedec38ce485d9f7269a4e2efb1320976f9 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -51,10 +51,10 @@ #include "scsi_logging.h" #include "scsi_debug.h" -#define SCSI_DEBUG_VERSION "1.80" -static const char * scsi_debug_version_date = "20061018"; +#define SCSI_DEBUG_VERSION "1.81" +static const char * scsi_debug_version_date = "20070104"; -/* Additional Sense Code (ASC) used */ +/* Additional Sense Code (ASC) */ #define NO_ADDITIONAL_SENSE 0x0 #define LOGICAL_UNIT_NOT_READY 0x4 #define UNRECOVERED_READ_ERR 0x11 @@ -65,9 +65,13 @@ static const char * scsi_debug_version_date = "20061018"; #define INVALID_FIELD_IN_PARAM_LIST 0x26 #define POWERON_RESET 0x29 #define SAVING_PARAMS_UNSUP 0x39 +#define TRANSPORT_PROBLEM 0x4b #define THRESHOLD_EXCEEDED 0x5d #define LOW_POWER_COND_ON 0x5e +/* Additional Sense Code Qualifier (ASCQ) */ +#define ACK_NAK_TO 0x3 + #define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */ /* Default values for driver parameters */ @@ -95,15 +99,20 @@ static const char * scsi_debug_version_date = "20061018"; #define SCSI_DEBUG_OPT_MEDIUM_ERR 2 #define SCSI_DEBUG_OPT_TIMEOUT 4 #define SCSI_DEBUG_OPT_RECOVERED_ERR 8 +#define SCSI_DEBUG_OPT_TRANSPORT_ERR 16 /* When "every_nth" > 0 then modulo "every_nth" commands: * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set * - a RECOVERED_ERROR is simulated on successful read and write * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set. + * - a TRANSPORT_ERROR is simulated on successful read and write + * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set. * * When "every_nth" < 0 then after "- every_nth" commands: * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set * - a RECOVERED_ERROR is simulated on successful read and write * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set. + * - a TRANSPORT_ERROR is simulated on successful read and write + * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set. * This will continue until some other action occurs (e.g. the user * writing a new value (other than -1 or 1) to every_nth via sysfs). */ @@ -315,6 +324,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) int target = SCpnt->device->id; struct sdebug_dev_info * devip = NULL; int inj_recovered = 0; + int inj_transport = 0; int delay_override = 0; if (done == NULL) @@ -352,6 +362,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) return 0; /* ignore command causing timeout */ else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts) inj_recovered = 1; /* to reads and writes below */ + else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts) + inj_transport = 1; /* to reads and writes below */ } if (devip->wlun) { @@ -468,7 +480,11 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) mk_sense_buffer(devip, RECOVERED_ERROR, THRESHOLD_EXCEEDED, 0); errsts = check_condition_result; - } + } else if (inj_transport && (0 == errsts)) { + mk_sense_buffer(devip, ABORTED_COMMAND, + TRANSPORT_PROBLEM, ACK_NAK_TO); + errsts = check_condition_result; + } break; case REPORT_LUNS: /* mandatory, ignore unit attention */ delay_override = 1; @@ -531,6 +547,9 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) delay_override = 1; errsts = check_readiness(SCpnt, 0, devip); break; + case WRITE_BUFFER: + errsts = check_readiness(SCpnt, 1, devip); + break; default: if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) printk(KERN_INFO "scsi_debug: Opcode: 0x%x not " @@ -954,7 +973,9 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target, int alloc_len, n, ret; alloc_len = (cmd[3] << 8) + cmd[4]; - arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_KERNEL); + arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC); + if (! arr) + return DID_REQUEUE << 16; if (devip->wlun) pq_pdt = 0x1e; /* present, wlun */ else if (scsi_debug_no_lun_0 && (0 == devip->lun)) @@ -1217,7 +1238,9 @@ static int resp_report_tgtpgs(struct scsi_cmnd * scp, alen = ((cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8) + cmd[9]); - arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_KERNEL); + arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_ATOMIC); + if (! arr) + return DID_REQUEUE << 16; /* * EVPD page 0x88 states we have two ports, one * real and a fake port with no device connected. @@ -1996,6 +2019,8 @@ static int scsi_debug_slave_configure(struct scsi_device * sdp) if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN) sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN; devip = devInfoReg(sdp); + if (NULL == devip) + return 1; /* no resources, will be marked offline */ sdp->hostdata = devip; if (sdp->host->cmd_per_lun) scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING, @@ -2044,7 +2069,7 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) } } if (NULL == open_devip) { /* try and make a new one */ - open_devip = kzalloc(sizeof(*open_devip),GFP_KERNEL); + open_devip = kzalloc(sizeof(*open_devip),GFP_ATOMIC); if (NULL == open_devip) { printk(KERN_ERR "%s: out of memory at line %d\n", __FUNCTION__, __LINE__); @@ -2388,7 +2413,7 @@ MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)"); MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)"); MODULE_PARM_DESC(num_parts, "number of partitions(def=0)"); MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)"); -MODULE_PARM_DESC(opts, "1->noise, 2->medium_error, 4->... (def=0)"); +MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)"); MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])"); MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])"); MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)"); @@ -2943,7 +2968,6 @@ static int sdebug_add_adapter(void) struct list_head *lh, *lh_sf; sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL); - if (NULL == sdbg_host) { printk(KERN_ERR "%s: out of memory at line %d\n", __FUNCTION__, __LINE__); diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 2ecb6ff42444697d9aa866de4bb00c0d707880b5..b8edcf5b54511be2f10fc9690fd01fbdd4dfb99e 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -359,6 +359,11 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) return SUCCESS; case MEDIUM_ERROR: + if (sshdr.asc == 0x11 || /* UNRECOVERED READ ERR */ + sshdr.asc == 0x13 || /* AMNF DATA FIELD */ + sshdr.asc == 0x14) { /* RECORD NOT FOUND */ + return SUCCESS; + } return NEEDS_RETRY; case HARDWARE_ERROR: @@ -452,6 +457,128 @@ static void scsi_eh_done(struct scsi_cmnd *scmd) complete(eh_action); } +/** + * scsi_try_host_reset - ask host adapter to reset itself + * @scmd: SCSI cmd to send hsot reset. + **/ +static int scsi_try_host_reset(struct scsi_cmnd *scmd) +{ + unsigned long flags; + int rtn; + + SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n", + __FUNCTION__)); + + if (!scmd->device->host->hostt->eh_host_reset_handler) + return FAILED; + + rtn = scmd->device->host->hostt->eh_host_reset_handler(scmd); + + if (rtn == SUCCESS) { + if (!scmd->device->host->hostt->skip_settle_delay) + ssleep(HOST_RESET_SETTLE_TIME); + spin_lock_irqsave(scmd->device->host->host_lock, flags); + scsi_report_bus_reset(scmd->device->host, + scmd_channel(scmd)); + spin_unlock_irqrestore(scmd->device->host->host_lock, flags); + } + + return rtn; +} + +/** + * scsi_try_bus_reset - ask host to perform a bus reset + * @scmd: SCSI cmd to send bus reset. + **/ +static int scsi_try_bus_reset(struct scsi_cmnd *scmd) +{ + unsigned long flags; + int rtn; + + SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n", + __FUNCTION__)); + + if (!scmd->device->host->hostt->eh_bus_reset_handler) + return FAILED; + + rtn = scmd->device->host->hostt->eh_bus_reset_handler(scmd); + + if (rtn == SUCCESS) { + if (!scmd->device->host->hostt->skip_settle_delay) + ssleep(BUS_RESET_SETTLE_TIME); + spin_lock_irqsave(scmd->device->host->host_lock, flags); + scsi_report_bus_reset(scmd->device->host, + scmd_channel(scmd)); + spin_unlock_irqrestore(scmd->device->host->host_lock, flags); + } + + return rtn; +} + +/** + * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev + * @scmd: SCSI cmd used to send BDR + * + * Notes: + * There is no timeout for this operation. if this operation is + * unreliable for a given host, then the host itself needs to put a + * timer on it, and set the host back to a consistent state prior to + * returning. + **/ +static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd) +{ + int rtn; + + if (!scmd->device->host->hostt->eh_device_reset_handler) + return FAILED; + + rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd); + if (rtn == SUCCESS) { + scmd->device->was_reset = 1; + scmd->device->expecting_cc_ua = 1; + } + + return rtn; +} + +static int __scsi_try_to_abort_cmd(struct scsi_cmnd *scmd) +{ + if (!scmd->device->host->hostt->eh_abort_handler) + return FAILED; + + return scmd->device->host->hostt->eh_abort_handler(scmd); +} + +/** + * scsi_try_to_abort_cmd - Ask host to abort a running command. + * @scmd: SCSI cmd to abort from Lower Level. + * + * Notes: + * This function will not return until the user's completion function + * has been called. there is no timeout on this operation. if the + * author of the low-level driver wishes this operation to be timed, + * they can provide this facility themselves. helper functions in + * scsi_error.c can be supplied to make this easier to do. + **/ +static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd) +{ + /* + * scsi_done was called just after the command timed out and before + * we had a chance to process it. (db) + */ + if (scmd->serial_number == 0) + return SUCCESS; + return __scsi_try_to_abort_cmd(scmd); +} + +static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd) +{ + if (__scsi_try_to_abort_cmd(scmd) != SUCCESS) + if (scsi_try_bus_device_reset(scmd) != SUCCESS) + if (scsi_try_bus_reset(scmd) != SUCCESS) + scsi_try_host_reset(scmd); +} + /** * scsi_send_eh_cmnd - submit a scsi command as part of error recory * @scmd: SCSI command structure to hijack @@ -579,13 +706,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, break; } } else { - /* - * FIXME(eric) - we are not tracking whether we could - * abort a timed out command or not. not sure how - * we should treat them differently anyways. - */ - if (shost->hostt->eh_abort_handler) - shost->hostt->eh_abort_handler(scmd); + scsi_abort_eh_cmnd(scmd); rtn = FAILED; } @@ -672,8 +793,8 @@ EXPORT_SYMBOL(scsi_eh_finish_cmd); * XXX: Long term this code should go away, but that needs an audit of * all LLDDs first. **/ -static int scsi_eh_get_sense(struct list_head *work_q, - struct list_head *done_q) +int scsi_eh_get_sense(struct list_head *work_q, + struct list_head *done_q) { struct scsi_cmnd *scmd, *next; int rtn; @@ -715,31 +836,7 @@ static int scsi_eh_get_sense(struct list_head *work_q, return list_empty(work_q); } - -/** - * scsi_try_to_abort_cmd - Ask host to abort a running command. - * @scmd: SCSI cmd to abort from Lower Level. - * - * Notes: - * This function will not return until the user's completion function - * has been called. there is no timeout on this operation. if the - * author of the low-level driver wishes this operation to be timed, - * they can provide this facility themselves. helper functions in - * scsi_error.c can be supplied to make this easier to do. - **/ -static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd) -{ - if (!scmd->device->host->hostt->eh_abort_handler) - return FAILED; - - /* - * scsi_done was called just after the command timed out and before - * we had a chance to process it. (db) - */ - if (scmd->serial_number == 0) - return SUCCESS; - return scmd->device->host->hostt->eh_abort_handler(scmd); -} +EXPORT_SYMBOL_GPL(scsi_eh_get_sense); /** * scsi_eh_tur - Send TUR to device. @@ -814,32 +911,6 @@ static int scsi_eh_abort_cmds(struct list_head *work_q, return list_empty(work_q); } -/** - * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev - * @scmd: SCSI cmd used to send BDR - * - * Notes: - * There is no timeout for this operation. if this operation is - * unreliable for a given host, then the host itself needs to put a - * timer on it, and set the host back to a consistent state prior to - * returning. - **/ -static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd) -{ - int rtn; - - if (!scmd->device->host->hostt->eh_device_reset_handler) - return FAILED; - - rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd); - if (rtn == SUCCESS) { - scmd->device->was_reset = 1; - scmd->device->expecting_cc_ua = 1; - } - - return rtn; -} - /** * scsi_eh_try_stu - Send START_UNIT to device. * @scmd: Scsi cmd to send START_UNIT @@ -970,64 +1041,6 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost, return list_empty(work_q); } -/** - * scsi_try_bus_reset - ask host to perform a bus reset - * @scmd: SCSI cmd to send bus reset. - **/ -static int scsi_try_bus_reset(struct scsi_cmnd *scmd) -{ - unsigned long flags; - int rtn; - - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n", - __FUNCTION__)); - - if (!scmd->device->host->hostt->eh_bus_reset_handler) - return FAILED; - - rtn = scmd->device->host->hostt->eh_bus_reset_handler(scmd); - - if (rtn == SUCCESS) { - if (!scmd->device->host->hostt->skip_settle_delay) - ssleep(BUS_RESET_SETTLE_TIME); - spin_lock_irqsave(scmd->device->host->host_lock, flags); - scsi_report_bus_reset(scmd->device->host, - scmd_channel(scmd)); - spin_unlock_irqrestore(scmd->device->host->host_lock, flags); - } - - return rtn; -} - -/** - * scsi_try_host_reset - ask host adapter to reset itself - * @scmd: SCSI cmd to send hsot reset. - **/ -static int scsi_try_host_reset(struct scsi_cmnd *scmd) -{ - unsigned long flags; - int rtn; - - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n", - __FUNCTION__)); - - if (!scmd->device->host->hostt->eh_host_reset_handler) - return FAILED; - - rtn = scmd->device->host->hostt->eh_host_reset_handler(scmd); - - if (rtn == SUCCESS) { - if (!scmd->device->host->hostt->skip_settle_delay) - ssleep(HOST_RESET_SETTLE_TIME); - spin_lock_irqsave(scmd->device->host->host_lock, flags); - scsi_report_bus_reset(scmd->device->host, - scmd_channel(scmd)); - spin_unlock_irqrestore(scmd->device->host->host_lock, flags); - } - - return rtn; -} - /** * scsi_eh_bus_reset - send a bus reset * @shost: scsi host being recovered. @@ -1411,9 +1424,9 @@ static void scsi_restart_operations(struct Scsi_Host *shost) * @eh_done_q: list_head for processed commands. * **/ -static void scsi_eh_ready_devs(struct Scsi_Host *shost, - struct list_head *work_q, - struct list_head *done_q) +void scsi_eh_ready_devs(struct Scsi_Host *shost, + struct list_head *work_q, + struct list_head *done_q) { if (!scsi_eh_stu(shost, work_q, done_q)) if (!scsi_eh_bus_device_reset(shost, work_q, done_q)) @@ -1421,6 +1434,7 @@ static void scsi_eh_ready_devs(struct Scsi_Host *shost, if (!scsi_eh_host_reset(work_q, done_q)) scsi_eh_offline_sdevs(work_q, done_q); } +EXPORT_SYMBOL_GPL(scsi_eh_ready_devs); /** * scsi_eh_flush_done_q - finish processed commands or retry them. diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index a1cd6e6a292aa887216837b77b6f2dc744b1a12f..9f7482d0b59489e7efccc347a8b7ce33208b4cdb 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1399,7 +1399,7 @@ static void scsi_softirq_done(struct request *rq) scsi_finish_command(cmd); break; case NEEDS_RETRY: - scsi_retry_command(cmd); + scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY); break; case ADD_TO_MLQUEUE: scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); @@ -2249,6 +2249,8 @@ void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, size_t sg_len = 0, len_complete = 0; struct page *page; + WARN_ON(!irqs_disabled()); + for (i = 0; i < sg_count; i++) { len_complete = sg_len; /* Complete sg-entries */ sg_len += sg[i].length; diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index f458c2f686d2364d4387ea0bc8b4d0afec6f8d4c..ee8efe849bf41c0c906c5a9f0769e9a054d483a2 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -28,7 +28,6 @@ extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd); extern int scsi_setup_command_freelist(struct Scsi_Host *shost); extern void scsi_destroy_command_freelist(struct Scsi_Host *shost); extern void __scsi_done(struct scsi_cmnd *cmd); -extern int scsi_retry_command(struct scsi_cmnd *cmd); #ifdef CONFIG_SCSI_LOGGING void scsi_log_send(struct scsi_cmnd *cmd); void scsi_log_completion(struct scsi_cmnd *cmd, int disposition); @@ -58,6 +57,11 @@ extern int scsi_error_handler(void *host); extern int scsi_decide_disposition(struct scsi_cmnd *cmd); extern void scsi_eh_wakeup(struct Scsi_Host *shost); extern int scsi_eh_scmd_add(struct scsi_cmnd *, int); +void scsi_eh_ready_devs(struct Scsi_Host *shost, + struct list_head *work_q, + struct list_head *done_q); +int scsi_eh_get_sense(struct list_head *work_q, + struct list_head *done_q); /* scsi_lib.c */ extern int scsi_maybe_unblock_host(struct scsi_device *sdev); diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 96b7cbd746a84ac323d92bf6c72d0333515b3fd3..a43b9ec3aefd66f2953841c964cb2fd2c5746106 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1029,7 +1029,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, sdev_printk(KERN_INFO, sdev, "scsi scan: consider passing scsi_mod." - "dev_flags=%s:%s:0x240 or 0x800240\n", + "dev_flags=%s:%s:0x240 or 0x1000240\n", scsi_inq_str(vend, result, 8, 16), scsi_inq_str(mod, result, 16, 32)); }); diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 5c0b75bbfa10c9a78e2a9536ce3d12b83f789441..6d39150e205be19593e71406f672bee539ca9368 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -336,6 +336,51 @@ show_sas_device_type(struct class_device *cdev, char *buf) } static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL); +static ssize_t do_sas_phy_enable(struct class_device *cdev, + size_t count, int enable) +{ + struct sas_phy *phy = transport_class_to_phy(cdev); + struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); + struct sas_internal *i = to_sas_internal(shost->transportt); + int error; + + error = i->f->phy_enable(phy, enable); + if (error) + return error; + phy->enabled = enable; + return count; +}; + +static ssize_t store_sas_phy_enable(struct class_device *cdev, + const char *buf, size_t count) +{ + if (count < 1) + return -EINVAL; + + switch (buf[0]) { + case '0': + do_sas_phy_enable(cdev, count, 0); + break; + case '1': + do_sas_phy_enable(cdev, count, 1); + break; + default: + return -EINVAL; + } + + return count; +} + +static ssize_t show_sas_phy_enable(struct class_device *cdev, char *buf) +{ + struct sas_phy *phy = transport_class_to_phy(cdev); + + return snprintf(buf, 20, "%d", phy->enabled); +} + +static CLASS_DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable, + store_sas_phy_enable); + static ssize_t do_sas_phy_reset(struct class_device *cdev, size_t count, int hard_reset) { @@ -435,6 +480,7 @@ struct sas_phy *sas_phy_alloc(struct device *parent, int number) return NULL; phy->number = number; + phy->enabled = 1; device_initialize(&phy->dev); phy->dev.parent = get_device(parent); @@ -579,8 +625,19 @@ static void sas_port_release(struct device *dev) static void sas_port_create_link(struct sas_port *port, struct sas_phy *phy) { - sysfs_create_link(&port->dev.kobj, &phy->dev.kobj, phy->dev.bus_id); - sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port"); + int res; + + res = sysfs_create_link(&port->dev.kobj, &phy->dev.kobj, + phy->dev.bus_id); + if (res) + goto err; + res = sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port"); + if (res) + goto err; + return; +err: + printk(KERN_ERR "%s: Cannot create port links, err=%d\n", + __FUNCTION__, res); } static void sas_port_delete_link(struct sas_port *port, @@ -818,13 +875,20 @@ EXPORT_SYMBOL(sas_port_delete_phy); void sas_port_mark_backlink(struct sas_port *port) { + int res; struct device *parent = port->dev.parent->parent->parent; if (port->is_backlink) return; port->is_backlink = 1; - sysfs_create_link(&port->dev.kobj, &parent->kobj, - parent->bus_id); + res = sysfs_create_link(&port->dev.kobj, &parent->kobj, + parent->bus_id); + if (res) + goto err; + return; +err: + printk(KERN_ERR "%s: Cannot create port backlink, err=%d\n", + __FUNCTION__, res); } EXPORT_SYMBOL(sas_port_mark_backlink); @@ -1237,7 +1301,7 @@ int sas_rphy_add(struct sas_rphy *rphy) if (identify->device_type == SAS_END_DEVICE && rphy->scsi_target_id != -1) { scsi_scan_target(&rphy->dev, 0, - rphy->scsi_target_id, ~0, 0); + rphy->scsi_target_id, SCAN_WILD_CARD, 0); } return 0; @@ -1253,7 +1317,7 @@ EXPORT_SYMBOL(sas_rphy_add); * Note: * This function must only be called on a remote * PHY that has not sucessfully been added using - * sas_rphy_add(). + * sas_rphy_add() (or has been sas_rphy_remove()'d) */ void sas_rphy_free(struct sas_rphy *rphy) { @@ -1272,18 +1336,30 @@ void sas_rphy_free(struct sas_rphy *rphy) EXPORT_SYMBOL(sas_rphy_free); /** - * sas_rphy_delete -- remove SAS remote PHY - * @rphy: SAS remote PHY to remove + * sas_rphy_delete -- remove and free SAS remote PHY + * @rphy: SAS remote PHY to remove and free * - * Removes the specified SAS remote PHY. + * Removes the specified SAS remote PHY and frees it. */ void sas_rphy_delete(struct sas_rphy *rphy) +{ + sas_rphy_remove(rphy); + sas_rphy_free(rphy); +} +EXPORT_SYMBOL(sas_rphy_delete); + +/** + * sas_rphy_remove -- remove SAS remote PHY + * @rphy: SAS remote phy to remove + * + * Removes the specified SAS remote PHY. + */ +void +sas_rphy_remove(struct sas_rphy *rphy) { struct device *dev = &rphy->dev; struct sas_port *parent = dev_to_sas_port(dev->parent); - struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); - struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); switch (rphy->identify.device_type) { case SAS_END_DEVICE: @@ -1299,17 +1375,10 @@ sas_rphy_delete(struct sas_rphy *rphy) transport_remove_device(dev); device_del(dev); - transport_destroy_device(dev); - - mutex_lock(&sas_host->lock); - list_del(&rphy->list); - mutex_unlock(&sas_host->lock); parent->rphy = NULL; - - put_device(dev); } -EXPORT_SYMBOL(sas_rphy_delete); +EXPORT_SYMBOL(sas_rphy_remove); /** * scsi_is_sas_rphy -- check if a struct device represents a SAS remote PHY @@ -1389,6 +1458,10 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel, SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1, \ !i->f->set_phy_speed, S_IRUGO) +#define SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(field, func) \ + SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1, \ + !i->f->func, S_IRUGO) + #define SETUP_PORT_ATTRIBUTE(field) \ SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1) @@ -1396,10 +1469,10 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel, SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func) #define SETUP_PHY_ATTRIBUTE_WRONLY(field) \ - SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, 1) + SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, 1) #define SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(field, func) \ - SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, i->f->func) + SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, i->f->func) #define SETUP_END_DEV_ATTRIBUTE(field) \ SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1) @@ -1479,6 +1552,7 @@ sas_attach_transport(struct sas_function_template *ft) SETUP_PHY_ATTRIBUTE(phy_reset_problem_count); SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(link_reset, phy_reset); SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(hard_reset, phy_reset); + SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(enable, phy_enable); i->phy_attrs[count] = NULL; count = 0; @@ -1587,7 +1661,7 @@ static void __exit sas_transport_exit(void) } MODULE_AUTHOR("Christoph Hellwig"); -MODULE_DESCRIPTION("SAS Transphy Attributes"); +MODULE_DESCRIPTION("SAS Transport Attributes"); MODULE_LICENSE("GPL"); module_init(sas_transport_init); diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 014d7fea1ff375d5a5c982c8d5c2f2d67d3be28b..6f56f8750635eca0e44ec6af2914a40f54b7c123 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -46,7 +46,6 @@ * two cc/ua clears */ /* Private data accessors (keep these out of the header file) */ -#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending) #define spi_dv_in_progress(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_in_progress) #define spi_dv_mutex(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_mutex) diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c index 551baccec5230c57ec2fb3bcdf714d7969fe1fab..018c65f73ac48e8fef3350e17f346fab8cfff2d1 100644 --- a/drivers/scsi/sim710.c +++ b/drivers/scsi/sim710.c @@ -123,6 +123,7 @@ sim710_probe_common(struct device *dev, unsigned long base_addr, hostdata->differential = differential; hostdata->clock = clock; hostdata->chip710 = 1; + hostdata->burst_length = 8; /* and register the chip */ if((host = NCR_700_detect(&sim710_driver_template, hostdata, dev)) diff --git a/drivers/scsi/sni_53c710.c b/drivers/scsi/sni_53c710.c new file mode 100644 index 0000000000000000000000000000000000000000..6bc505115841cd2ee5652e25a5354bd8ea6eab77 --- /dev/null +++ b/drivers/scsi/sni_53c710.c @@ -0,0 +1,159 @@ +/* -*- mode: c; c-basic-offset: 8 -*- */ + +/* SNI RM driver + * + * Copyright (C) 2001 by James.Bottomley@HansenPartnership.com +**----------------------------------------------------------------------------- +** +** 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; either version 2 of the License, or +** (at your option) any later version. +** +** 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. +** +** 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., 675 Mass Ave, Cambridge, MA 02139, USA. +** +**----------------------------------------------------------------------------- + */ + +/* + * Based on lasi700.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "53c700.h" + +MODULE_AUTHOR("Thomas Bogendörfer"); +MODULE_DESCRIPTION("SNI RM 53c710 SCSI Driver"); +MODULE_LICENSE("GPL"); + +#define SNIRM710_CLOCK 32 + +static struct scsi_host_template snirm710_template = { + .name = "SNI RM SCSI 53c710", + .proc_name = "snirm_53c710", + .this_id = 7, + .module = THIS_MODULE, +}; + +static int __init snirm710_probe(struct platform_device *dev) +{ + unsigned long base; + struct NCR_700_Host_Parameters *hostdata; + struct Scsi_Host *host; + struct resource *res; + + res = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + base = res->start; + hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL); + if (!hostdata) { + printk(KERN_ERR "%s: Failed to allocate host data\n", + dev->dev.bus_id); + return -ENOMEM; + } + + hostdata->dev = &dev->dev; + dma_set_mask(&dev->dev, DMA_32BIT_MASK); + hostdata->base = ioremap_nocache(CPHYSADDR(base), 0x100); + hostdata->differential = 0; + + hostdata->clock = SNIRM710_CLOCK; + hostdata->force_le_on_be = 1; + hostdata->chip710 = 1; + hostdata->burst_length = 4; + + host = NCR_700_detect(&snirm710_template, hostdata, &dev->dev); + if (!host) + goto out_kfree; + host->this_id = 7; + host->base = base; + host->irq = platform_get_irq(dev, 0); + if(request_irq(host->irq, NCR_700_intr, SA_SHIRQ, "snirm710", host)) { + printk(KERN_ERR "snirm710: request_irq failed!\n"); + goto out_put_host; + } + + dev_set_drvdata(&dev->dev, host); + scsi_scan_host(host); + + return 0; + + out_put_host: + scsi_host_put(host); + out_kfree: + iounmap(hostdata->base); + kfree(hostdata); + return -ENODEV; +} + +static int __exit snirm710_driver_remove(struct platform_device *dev) +{ + struct Scsi_Host *host = dev_get_drvdata(&dev->dev); + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)host->hostdata[0]; + + scsi_remove_host(host); + NCR_700_release(host); + free_irq(host->irq, host); + iounmap(hostdata->base); + kfree(hostdata); + + return 0; +} + +static struct platform_driver snirm710_driver = { + .probe = snirm710_probe, + .remove = __devexit_p(snirm710_driver_remove), + .driver = { + .name = "snirm_53c710", + }, +}; + +static int __init snirm710_init(void) +{ + int err; + + if ((err = platform_driver_register(&snirm710_driver))) { + printk(KERN_ERR "Driver registration failed\n"); + return err; + } + return 0; +} + +static void __exit snirm710_exit(void) +{ + platform_driver_unregister(&snirm710_driver); +} + +module_init(snirm710_init); +module_exit(snirm710_exit); diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 488ec7948a570766856436970a40aa2fd3813528..16e279be4a3e17dd4422192ffa473b9b285d15a1 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -9,7 +9,7 @@ Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky, Michael Schaefer, J"org Weule, and Eric Youngdale. - Copyright 1992 - 2006 Kai Makisara + Copyright 1992 - 2007 Kai Makisara email Kai.Makisara@kolumbus.fi Some small formal changes - aeb, 950809 @@ -17,7 +17,7 @@ Last modified: 18-JAN-1998 Richard Gooch Devfs support */ -static const char *verstr = "20061107"; +static const char *verstr = "20070203"; #include @@ -1168,6 +1168,7 @@ static int st_open(struct inode *inode, struct file *filp) STps = &(STp->ps[i]); STps->rw = ST_IDLE; } + STp->try_dio_now = STp->try_dio; STp->recover_count = 0; DEB( STp->nbr_waits = STp->nbr_finished = 0; STp->nbr_requests = STp->nbr_dio = STp->nbr_pages = STp->nbr_combinable = 0; ) @@ -1400,9 +1401,9 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf, struct st_buffer *STbp = STp->buffer; if (is_read) - i = STp->try_dio && try_rdio; + i = STp->try_dio_now && try_rdio; else - i = STp->try_dio && try_wdio; + i = STp->try_dio_now && try_wdio; if (i && ((unsigned long)buf & queue_dma_alignment( STp->device->request_queue)) == 0) { @@ -1599,7 +1600,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) STm->do_async_writes && STps->eof < ST_EOM_OK; if (STp->block_size != 0 && STm->do_buffer_writes && - !(STp->try_dio && try_wdio) && STps->eof < ST_EOM_OK && + !(STp->try_dio_now && try_wdio) && STps->eof < ST_EOM_OK && STbp->buffer_bytes < STbp->buffer_size) { STp->dirty = 1; /* Don't write a buffer that is not full enough. */ @@ -1769,7 +1770,7 @@ static long read_tape(struct scsi_tape *STp, long count, if (STp->block_size == 0) blks = bytes = count; else { - if (!(STp->try_dio && try_rdio) && STm->do_read_ahead) { + if (!(STp->try_dio_now && try_rdio) && STm->do_read_ahead) { blks = (STp->buffer)->buffer_blocks; bytes = blks * STp->block_size; } else { @@ -1948,10 +1949,12 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) goto out; STm = &(STp->modes[STp->current_mode]); - if (!(STm->do_read_ahead) && STp->block_size != 0 && - (count % STp->block_size) != 0) { - retval = (-EINVAL); /* Read must be integral number of blocks */ - goto out; + if (STp->block_size != 0 && (count % STp->block_size) != 0) { + if (!STm->do_read_ahead) { + retval = (-EINVAL); /* Read must be integral number of blocks */ + goto out; + } + STp->try_dio_now = 0; /* Direct i/o can't handle split blocks */ } STps = &(STp->ps[STp->partition]); diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h index 05a5cae126ec06e8c75c632821f8a6d8548236eb..50f3deb1f9ed92fcaf06bcc8c62329e966db8750 100644 --- a/drivers/scsi/st.h +++ b/drivers/scsi/st.h @@ -117,7 +117,8 @@ struct scsi_tape { unsigned char cln_sense_value; unsigned char cln_sense_mask; unsigned char use_pf; /* Set Page Format bit in all mode selects? */ - unsigned char try_dio; /* try direct i/o? */ + unsigned char try_dio; /* try direct i/o in general? */ + unsigned char try_dio_now; /* try direct i/o before next close? */ unsigned char c_algo; /* compression algorithm */ unsigned char pos_unknown; /* after reset position unknown */ int tape_type; diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 0689e004a281e3b2fdcc7f8e1d5d6770b9b63180..ad0182ef7809bba62450e4788dfb658fd601ce8d 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -323,12 +323,20 @@ struct sas_ha_event { struct sas_ha_struct *ha; }; +enum sas_ha_state { + SAS_HA_REGISTERED, + SAS_HA_UNREGISTERED +}; + struct sas_ha_struct { /* private: */ spinlock_t event_lock; struct sas_ha_event ha_events[HA_NUM_EVENTS]; unsigned long pending; + enum sas_ha_state state; + spinlock_t state_lock; + struct scsi_core core; /* public: */ @@ -553,7 +561,8 @@ struct sas_task { #define SAS_TASK_STATE_PENDING 1 #define SAS_TASK_STATE_DONE 2 #define SAS_TASK_STATE_ABORTED 4 -#define SAS_TASK_INITIATOR_ABORTED 8 +#define SAS_TASK_NEED_DEV_RESET 8 +#define SAS_TASK_AT_INITIATOR 16 static inline struct sas_task *sas_alloc_task(gfp_t flags) { @@ -612,6 +621,9 @@ struct sas_domain_function_template { extern int sas_register_ha(struct sas_ha_struct *); extern int sas_unregister_ha(struct sas_ha_struct *); +int sas_set_phy_speed(struct sas_phy *phy, + struct sas_phy_linkrates *rates); +int sas_phy_enable(struct sas_phy *phy, int enabled); int sas_phy_reset(struct sas_phy *phy, int hard_reset); extern int sas_queuecommand(struct scsi_cmnd *, void (*scsi_done)(struct scsi_cmnd *)); @@ -645,6 +657,9 @@ void sas_unregister_dev(struct domain_device *); void sas_init_dev(struct domain_device *); -void sas_task_abort(struct work_struct *); +void sas_task_abort(struct sas_task *); +int __sas_task_abort(struct sas_task *); +int sas_eh_device_reset_handler(struct scsi_cmnd *cmd); +int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd); #endif /* _SASLIB_H_ */ diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 59633a82de47cd54dc6fa2cb6fcf09b9a1e270d4..9aedc19820b0df1d007b0d8e7150de5e3c07e5fd 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -54,6 +54,7 @@ struct sas_identify { struct sas_phy { struct device dev; int number; + int enabled; /* phy identification */ struct sas_identify identify; @@ -163,6 +164,7 @@ struct sas_function_template { int (*get_enclosure_identifier)(struct sas_rphy *, u64 *); int (*get_bay_identifier)(struct sas_rphy *); int (*phy_reset)(struct sas_phy *, int); + int (*phy_enable)(struct sas_phy *, int); int (*set_phy_speed)(struct sas_phy *, struct sas_phy_linkrates *); }; @@ -180,6 +182,7 @@ extern struct sas_rphy *sas_end_device_alloc(struct sas_port *); extern struct sas_rphy *sas_expander_alloc(struct sas_port *, enum sas_device_type); void sas_rphy_free(struct sas_rphy *); extern int sas_rphy_add(struct sas_rphy *); +extern void sas_rphy_remove(struct sas_rphy *); extern void sas_rphy_delete(struct sas_rphy *); extern int scsi_is_sas_rphy(const struct device *); diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h index da180f738477ef23040d68549c953969e7c524ff..286e9628ed8ba077f997e4105f6954e10d0d6c13 100644 --- a/include/scsi/scsi_transport_spi.h +++ b/include/scsi/scsi_transport_spi.h @@ -85,6 +85,7 @@ struct spi_host_attrs { #define spi_pcomp_en(x) (((struct spi_transport_attrs *)&(x)->starget_data)->pcomp_en) #define spi_hold_mcs(x) (((struct spi_transport_attrs *)&(x)->starget_data)->hold_mcs) #define spi_initial_dv(x) (((struct spi_transport_attrs *)&(x)->starget_data)->initial_dv) +#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending) #define spi_support_sync(x) (((struct spi_transport_attrs *)&(x)->starget_data)->support_sync) #define spi_support_wide(x) (((struct spi_transport_attrs *)&(x)->starget_data)->support_wide)