summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mpt2sas
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/mpt2sas')
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2.h12
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h74
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_init.h6
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_ioc.h4
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c84
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h77
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.c12
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_debug.h2
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c283
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_transport.c24
10 files changed, 424 insertions, 154 deletions
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h
index a3e60385787..3105d5e8d90 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2.h
@@ -8,7 +8,7 @@
* scatter/gather formats.
* Creation Date: June 21, 2006
*
- * mpi2.h Version: 02.00.17
+ * mpi2.h Version: 02.00.18
*
* Version History
* ---------------
@@ -64,6 +64,8 @@
* 05-12-10 02.00.16 Bumped MPI2_HEADER_VERSION_UNIT.
* Added alternative defines for the SGE Direction bit.
* 08-11-10 02.00.17 Bumped MPI2_HEADER_VERSION_UNIT.
+ * 11-10-10 02.00.18 Bumped MPI2_HEADER_VERSION_UNIT.
+ * Added MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR define.
* --------------------------------------------------------------------------
*/
@@ -89,7 +91,7 @@
#define MPI2_VERSION_02_00 (0x0200)
/* versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT (0x11)
+#define MPI2_HEADER_VERSION_UNIT (0x12)
#define MPI2_HEADER_VERSION_DEV (0x00)
#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
@@ -1060,10 +1062,14 @@ typedef struct _MPI2_IEEE_SGE_UNION
#define MPI2_IEEE_SGE_FLAGS_ADDR_MASK (0x03)
#define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00)
+ /* IEEE Simple Element only */
#define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01)
+ /* IEEE Simple Element only */
#define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02)
#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03)
-
+ /* IEEE Simple Element only */
+#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR (0x03)
+ /* IEEE Chain Element only */
/****************************************************************************
* IEEE SGE operation Macros
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
index f5b9c766e28..61475a6480e 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
@@ -6,7 +6,7 @@
* Title: MPI Configuration messages and pages
* Creation Date: November 10, 2006
*
- * mpi2_cnfg.h Version: 02.00.16
+ * mpi2_cnfg.h Version: 02.00.17
*
* Version History
* ---------------
@@ -127,6 +127,13 @@
* Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define.
* 08-11-10 02.00.16 Removed IO Unit Page 1 device path (multi-pathing)
* defines.
+ * 11-10-10 02.00.17 Added ReceptacleID field (replacing Reserved1) to
+ * MPI2_MANPAGE7_CONNECTOR_INFO and reworked defines for
+ * the Pinout field.
+ * Added BoardTemperature and BoardTemperatureUnits fields
+ * to MPI2_CONFIG_PAGE_IO_UNIT_7.
+ * Added MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING define
+ * and MPI2_CONFIG_PAGE_EXT_MAN_PS structure.
* --------------------------------------------------------------------------
*/
@@ -210,6 +217,7 @@ typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION
#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING (0x17)
#define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT (0x18)
#define MPI2_CONFIG_EXTPAGETYPE_ETHERNET (0x19)
+#define MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING (0x1A)
/*****************************************************************************
@@ -612,23 +620,31 @@ typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO
U32 Pinout; /* 0x00 */
U8 Connector[16]; /* 0x04 */
U8 Location; /* 0x14 */
- U8 Reserved1; /* 0x15 */
+ U8 ReceptacleID; /* 0x15 */
U16 Slot; /* 0x16 */
U32 Reserved2; /* 0x18 */
} MPI2_MANPAGE7_CONNECTOR_INFO, MPI2_POINTER PTR_MPI2_MANPAGE7_CONNECTOR_INFO,
Mpi2ManPage7ConnectorInfo_t, MPI2_POINTER pMpi2ManPage7ConnectorInfo_t;
/* defines for the Pinout field */
-#define MPI2_MANPAGE7_PINOUT_SFF_8484_L4 (0x00080000)
-#define MPI2_MANPAGE7_PINOUT_SFF_8484_L3 (0x00040000)
-#define MPI2_MANPAGE7_PINOUT_SFF_8484_L2 (0x00020000)
-#define MPI2_MANPAGE7_PINOUT_SFF_8484_L1 (0x00010000)
-#define MPI2_MANPAGE7_PINOUT_SFF_8470_L4 (0x00000800)
-#define MPI2_MANPAGE7_PINOUT_SFF_8470_L3 (0x00000400)
-#define MPI2_MANPAGE7_PINOUT_SFF_8470_L2 (0x00000200)
-#define MPI2_MANPAGE7_PINOUT_SFF_8470_L1 (0x00000100)
-#define MPI2_MANPAGE7_PINOUT_SFF_8482 (0x00000002)
-#define MPI2_MANPAGE7_PINOUT_CONNECTION_UNKNOWN (0x00000001)
+#define MPI2_MANPAGE7_PINOUT_LANE_MASK (0x0000FF00)
+#define MPI2_MANPAGE7_PINOUT_LANE_SHIFT (8)
+
+#define MPI2_MANPAGE7_PINOUT_TYPE_MASK (0x000000FF)
+#define MPI2_MANPAGE7_PINOUT_TYPE_UNKNOWN (0x00)
+#define MPI2_MANPAGE7_PINOUT_SATA_SINGLE (0x01)
+#define MPI2_MANPAGE7_PINOUT_SFF_8482 (0x02)
+#define MPI2_MANPAGE7_PINOUT_SFF_8486 (0x03)
+#define MPI2_MANPAGE7_PINOUT_SFF_8484 (0x04)
+#define MPI2_MANPAGE7_PINOUT_SFF_8087 (0x05)
+#define MPI2_MANPAGE7_PINOUT_SFF_8643_4I (0x06)
+#define MPI2_MANPAGE7_PINOUT_SFF_8643_8I (0x07)
+#define MPI2_MANPAGE7_PINOUT_SFF_8470 (0x08)
+#define MPI2_MANPAGE7_PINOUT_SFF_8088 (0x09)
+#define MPI2_MANPAGE7_PINOUT_SFF_8644_4X (0x0A)
+#define MPI2_MANPAGE7_PINOUT_SFF_8644_8X (0x0B)
+#define MPI2_MANPAGE7_PINOUT_SFF_8644_16X (0x0C)
+#define MPI2_MANPAGE7_PINOUT_SFF_8436 (0x0D)
/* defines for the Location field */
#define MPI2_MANPAGE7_LOCATION_UNKNOWN (0x01)
@@ -662,7 +678,7 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_7
MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_7,
Mpi2ManufacturingPage7_t, MPI2_POINTER pMpi2ManufacturingPage7_t;
-#define MPI2_MANUFACTURING7_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING7_PAGEVERSION (0x01)
/* defines for the Flags field */
#define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001)
@@ -849,11 +865,13 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
U16 IOCTemperature; /* 0x10 */
U8 IOCTemperatureUnits; /* 0x12 */
U8 IOCSpeed; /* 0x13 */
- U32 Reserved3; /* 0x14 */
+ U16 BoardTemperature; /* 0x14 */
+ U8 BoardTemperatureUnits; /* 0x16 */
+ U8 Reserved3; /* 0x17 */
} MPI2_CONFIG_PAGE_IO_UNIT_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_7,
Mpi2IOUnitPage7_t, MPI2_POINTER pMpi2IOUnitPage7_t;
-#define MPI2_IOUNITPAGE7_PAGEVERSION (0x01)
+#define MPI2_IOUNITPAGE7_PAGEVERSION (0x02)
/* defines for IO Unit Page 7 PCIeWidth field */
#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X1 (0x01)
@@ -881,7 +899,6 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
#define MPI2_IOUNITPAGE7_PMCAP_PCIE_WIDTH_CHANGE (0x00000008)
#define MPI2_IOUNITPAGE7_PMCAP_PCIE_SPEED_CHANGE (0x00000004)
-
/* defines for IO Unit Page 7 IOCTemperatureUnits field */
#define MPI2_IOUNITPAGE7_IOC_TEMP_NOT_PRESENT (0x00)
#define MPI2_IOUNITPAGE7_IOC_TEMP_FAHRENHEIT (0x01)
@@ -893,6 +910,11 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
#define MPI2_IOUNITPAGE7_IOC_SPEED_QUARTER (0x04)
#define MPI2_IOUNITPAGE7_IOC_SPEED_EIGHTH (0x08)
+/* defines for IO Unit Page 7 BoardTemperatureUnits field */
+#define MPI2_IOUNITPAGE7_BOARD_TEMP_NOT_PRESENT (0x00)
+#define MPI2_IOUNITPAGE7_BOARD_TEMP_FAHRENHEIT (0x01)
+#define MPI2_IOUNITPAGE7_BOARD_TEMP_CELSIUS (0x02)
+
/****************************************************************************
@@ -2799,5 +2821,25 @@ typedef struct _MPI2_CONFIG_PAGE_ETHERNET_1 {
#define MPI2_ETHPG1_MS_DATA_RATE_1GBIT (0x03)
+/****************************************************************************
+* Extended Manufacturing Config Pages
+****************************************************************************/
+
+/*
+ * Generic structure to use for product-specific extended manufacturing pages
+ * (currently Extended Manufacturing Page 40 through Extended Manufacturing
+ * Page 60).
+ */
+
+typedef struct _MPI2_CONFIG_PAGE_EXT_MAN_PS {
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
+ U32 ProductSpecificInfo; /* 0x08 */
+} MPI2_CONFIG_PAGE_EXT_MAN_PS,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXT_MAN_PS,
+ Mpi2ExtManufacturingPagePS_t,
+ MPI2_POINTER pMpi2ExtManufacturingPagePS_t;
+
+/* PageVersion should be provided by product-specific code */
+
#endif
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_init.h b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
index 165454d5259..de90162413c 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_init.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
@@ -6,7 +6,7 @@
* Title: MPI SCSI initiator mode messages and structures
* Creation Date: June 23, 2006
*
- * mpi2_init.h Version: 02.00.10
+ * mpi2_init.h Version: 02.00.11
*
* Version History
* ---------------
@@ -33,6 +33,7 @@
* Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define.
* 02-10-10 02.00.09 Removed unused structure that had "#if 0" around it.
* 05-12-10 02.00.10 Added optional vendor-unique region to SCSI IO Request.
+ * 11-10-10 02.00.11 Added MPI2_SCSIIO_NUM_SGLOFFSETS define.
* --------------------------------------------------------------------------
*/
@@ -139,6 +140,9 @@ typedef struct _MPI2_SCSI_IO_REQUEST
#define MPI2_SCSIIO_SGLFLAGS_SGL1_SHIFT (4)
#define MPI2_SCSIIO_SGLFLAGS_SGL0_SHIFT (0)
+/* number of SGLOffset fields */
+#define MPI2_SCSIIO_NUM_SGLOFFSETS (4)
+
/* SCSI IO IoFlags bits */
/* Large CDB Address Space */
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
index 761cbdb8a03..1f0c190d336 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
@@ -6,7 +6,7 @@
* Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
* Creation Date: October 11, 2006
*
- * mpi2_ioc.h Version: 02.00.15
+ * mpi2_ioc.h Version: 02.00.16
*
* Version History
* ---------------
@@ -103,6 +103,7 @@
* defines.
* 05-12-10 02.00.15 Marked Task Set Full Event as obsolete.
* Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define.
+ * 11-10-10 02.00.16 Added MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC.
* --------------------------------------------------------------------------
*/
@@ -1032,6 +1033,7 @@ typedef struct _MPI2_FW_DOWNLOAD_REQUEST
#define MPI2_FW_DOWNLOAD_ITYPE_MEGARAID (0x09)
#define MPI2_FW_DOWNLOAD_ITYPE_COMPLETE (0x0A)
#define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
+#define MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC (0xF0)
/* FWDownload TransactionContext Element */
typedef struct _MPI2_FW_DOWNLOAD_TCSGE
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index efa0255491c..83035bd1c48 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -94,7 +94,7 @@ module_param(diag_buffer_enable, int, 0);
MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers "
"(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
-int mpt2sas_fwfault_debug;
+static int mpt2sas_fwfault_debug;
MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
"and halt firmware - (default=0)");
@@ -857,7 +857,7 @@ _base_interrupt(int irq, void *bus_id)
completed_cmds = 0;
cb_idx = 0xFF;
do {
- rd.word = rpf->Words;
+ rd.word = le64_to_cpu(rpf->Words);
if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
goto out;
reply = 0;
@@ -906,7 +906,7 @@ _base_interrupt(int irq, void *bus_id)
next:
- rpf->Words = ULLONG_MAX;
+ rpf->Words = cpu_to_le64(ULLONG_MAX);
ioc->reply_post_host_index = (ioc->reply_post_host_index ==
(ioc->reply_post_queue_depth - 1)) ? 0 :
ioc->reply_post_host_index + 1;
@@ -1740,9 +1740,11 @@ _base_display_dell_branding(struct MPT2SAS_ADAPTER *ioc)
static void
_base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc)
{
- if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_INTEL &&
- ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008) {
+ if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL)
+ return;
+ switch (ioc->pdev->device) {
+ case MPI2_MFGPAGE_DEVID_SAS2008:
switch (ioc->pdev->subsystem_device) {
case MPT2SAS_INTEL_RMS2LL080_SSDID:
printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
@@ -1752,7 +1754,20 @@ _base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc)
printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
MPT2SAS_INTEL_RMS2LL040_BRANDING);
break;
+ default:
+ break;
+ }
+ case MPI2_MFGPAGE_DEVID_SAS2308_2:
+ switch (ioc->pdev->subsystem_device) {
+ case MPT2SAS_INTEL_RS25GB008_SSDID:
+ printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
+ MPT2SAS_INTEL_RS25GB008_BRANDING);
+ break;
+ default:
+ break;
}
+ default:
+ break;
}
}
@@ -1817,7 +1832,9 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
char desc[16];
u8 revision;
u32 iounit_pg1_flags;
+ u32 bios_version;
+ bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
pci_read_config_byte(ioc->pdev, PCI_CLASS_REVISION, &revision);
strncpy(desc, ioc->manu_pg0.ChipName, 16);
printk(MPT2SAS_INFO_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), "
@@ -1828,10 +1845,10 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
(ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
ioc->facts.FWVersion.Word & 0x000000FF,
revision,
- (ioc->bios_pg3.BiosVersion & 0xFF000000) >> 24,
- (ioc->bios_pg3.BiosVersion & 0x00FF0000) >> 16,
- (ioc->bios_pg3.BiosVersion & 0x0000FF00) >> 8,
- ioc->bios_pg3.BiosVersion & 0x000000FF);
+ (bios_version & 0xFF000000) >> 24,
+ (bios_version & 0x00FF0000) >> 16,
+ (bios_version & 0x0000FF00) >> 8,
+ bios_version & 0x000000FF);
_base_display_dell_branding(ioc);
_base_display_intel_branding(ioc);
@@ -2150,7 +2167,7 @@ _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
static int
_base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
{
- Mpi2IOCFactsReply_t *facts;
+ struct mpt2sas_facts *facts;
u32 queue_size, queue_diff;
u16 max_sge_elements;
u16 num_of_reply_frames;
@@ -2783,7 +2800,7 @@ _base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes,
int i;
u8 failed;
u16 dummy;
- u32 *mfp;
+ __le32 *mfp;
/* make sure doorbell is not in use */
if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) {
@@ -2871,7 +2888,7 @@ _base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes,
writel(0, &ioc->chip->HostInterruptStatus);
if (ioc->logging_level & MPT_DEBUG_INIT) {
- mfp = (u32 *)reply;
+ mfp = (__le32 *)reply;
printk(KERN_INFO "\toffset:data\n");
for (i = 0; i < reply_bytes/4; i++)
printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,
@@ -3097,7 +3114,8 @@ static int
_base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag)
{
Mpi2PortFactsRequest_t mpi_request;
- Mpi2PortFactsReply_t mpi_reply, *pfacts;
+ Mpi2PortFactsReply_t mpi_reply;
+ struct mpt2sas_port_facts *pfacts;
int mpi_reply_sz, mpi_request_sz, r;
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
@@ -3139,7 +3157,8 @@ static int
_base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
{
Mpi2IOCFactsRequest_t mpi_request;
- Mpi2IOCFactsReply_t mpi_reply, *facts;
+ Mpi2IOCFactsReply_t mpi_reply;
+ struct mpt2sas_facts *facts;
int mpi_reply_sz, mpi_request_sz, r;
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
@@ -3225,17 +3244,6 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION);
mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
- /* In MPI Revision I (0xA), the SystemReplyFrameSize(offset 0x18) was
- * removed and made reserved. For those with older firmware will need
- * this fix. It was decided that the Reply and Request frame sizes are
- * the same.
- */
- if ((ioc->facts.HeaderVersion >> 8) < 0xA) {
- mpi_request.Reserved7 = cpu_to_le16(ioc->reply_sz);
-/* mpi_request.SystemReplyFrameSize =
- * cpu_to_le16(ioc->reply_sz);
- */
- }
mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4);
mpi_request.ReplyDescriptorPostQueueDepth =
@@ -3243,25 +3251,17 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
mpi_request.ReplyFreeQueueDepth =
cpu_to_le16(ioc->reply_free_queue_depth);
-#if BITS_PER_LONG > 32
mpi_request.SenseBufferAddressHigh =
- cpu_to_le32(ioc->sense_dma >> 32);
+ cpu_to_le32((u64)ioc->sense_dma >> 32);
mpi_request.SystemReplyAddressHigh =
- cpu_to_le32(ioc->reply_dma >> 32);
+ cpu_to_le32((u64)ioc->reply_dma >> 32);
mpi_request.SystemRequestFrameBaseAddress =
- cpu_to_le64(ioc->request_dma);
+ cpu_to_le64((u64)ioc->request_dma);
mpi_request.ReplyFreeQueueAddress =
- cpu_to_le64(ioc->reply_free_dma);
+ cpu_to_le64((u64)ioc->reply_free_dma);
mpi_request.ReplyDescriptorPostQueueAddress =
- cpu_to_le64(ioc->reply_post_free_dma);
-#else
- mpi_request.SystemRequestFrameBaseAddress =
- cpu_to_le32(ioc->request_dma);
- mpi_request.ReplyFreeQueueAddress =
- cpu_to_le32(ioc->reply_free_dma);
- mpi_request.ReplyDescriptorPostQueueAddress =
- cpu_to_le32(ioc->reply_post_free_dma);
-#endif
+ cpu_to_le64((u64)ioc->reply_post_free_dma);
+
/* This time stamp specifies number of milliseconds
* since epoch ~ midnight January 1, 1970.
@@ -3271,10 +3271,10 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
(current_time.tv_usec / 1000));
if (ioc->logging_level & MPT_DEBUG_INIT) {
- u32 *mfp;
+ __le32 *mfp;
int i;
- mfp = (u32 *)&mpi_request;
+ mfp = (__le32 *)&mpi_request;
printk(KERN_INFO "\toffset:data\n");
for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++)
printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,
@@ -3759,7 +3759,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
/* initialize Reply Post Free Queue */
for (i = 0; i < ioc->reply_post_queue_depth; i++)
- ioc->reply_post_free[i].Words = ULLONG_MAX;
+ ioc->reply_post_free[i].Words = cpu_to_le64(ULLONG_MAX);
r = _base_send_ioc_init(ioc, sleep_flag);
if (r)
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index dcc289c2545..8d5be2120c6 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -69,11 +69,11 @@
#define MPT2SAS_DRIVER_NAME "mpt2sas"
#define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>"
#define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver"
-#define MPT2SAS_DRIVER_VERSION "08.100.00.02"
-#define MPT2SAS_MAJOR_VERSION 08
+#define MPT2SAS_DRIVER_VERSION "09.100.00.00"
+#define MPT2SAS_MAJOR_VERSION 09
#define MPT2SAS_MINOR_VERSION 100
#define MPT2SAS_BUILD_VERSION 00
-#define MPT2SAS_RELEASE_VERSION 02
+#define MPT2SAS_RELEASE_VERSION 00
/*
* Set MPT2SAS_SG_DEPTH value based on user input.
@@ -161,12 +161,15 @@
"Intel Integrated RAID Module RMS2LL080"
#define MPT2SAS_INTEL_RMS2LL040_BRANDING \
"Intel Integrated RAID Module RMS2LL040"
+#define MPT2SAS_INTEL_RS25GB008_BRANDING \
+ "Intel(R) RAID Controller RS25GB008"
/*
* Intel HBA SSDIDs
*/
#define MPT2SAS_INTEL_RMS2LL080_SSDID 0x350E
#define MPT2SAS_INTEL_RMS2LL040_SSDID 0x350F
+#define MPT2SAS_INTEL_RS25GB008_SSDID 0x3000
/*
@@ -541,6 +544,63 @@ struct _tr_list {
typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
+/* IOC Facts and Port Facts converted from little endian to cpu */
+union mpi2_version_union {
+ MPI2_VERSION_STRUCT Struct;
+ u32 Word;
+};
+
+struct mpt2sas_facts {
+ u16 MsgVersion;
+ u16 HeaderVersion;
+ u8 IOCNumber;
+ u8 VP_ID;
+ u8 VF_ID;
+ u16 IOCExceptions;
+ u16 IOCStatus;
+ u32 IOCLogInfo;
+ u8 MaxChainDepth;
+ u8 WhoInit;
+ u8 NumberOfPorts;
+ u8 MaxMSIxVectors;
+ u16 RequestCredit;
+ u16 ProductID;
+ u32 IOCCapabilities;
+ union mpi2_version_union FWVersion;
+ u16 IOCRequestFrameSize;
+ u16 Reserved3;
+ u16 MaxInitiators;
+ u16 MaxTargets;
+ u16 MaxSasExpanders;
+ u16 MaxEnclosures;
+ u16 ProtocolFlags;
+ u16 HighPriorityCredit;
+ u16 MaxReplyDescriptorPostQueueDepth;
+ u8 ReplyFrameSize;
+ u8 MaxVolumes;
+ u16 MaxDevHandle;
+ u16 MaxPersistentEntries;
+ u16 MinDevHandle;
+};
+
+struct mpt2sas_port_facts {
+ u8 PortNumber;
+ u8 VP_ID;
+ u8 VF_ID;
+ u8 PortType;
+ u16 MaxPostedCmdBuffers;
+};
+
+/**
+ * enum mutex_type - task management mutex type
+ * @TM_MUTEX_OFF: mutex is not required becuase calling function is acquiring it
+ * @TM_MUTEX_ON: mutex is required
+ */
+enum mutex_type {
+ TM_MUTEX_OFF = 0,
+ TM_MUTEX_ON = 1,
+};
+
/**
* struct MPT2SAS_ADAPTER - per adapter struct
* @list: ioc_list
@@ -703,6 +763,7 @@ struct MPT2SAS_ADAPTER {
/* misc flags */
int aen_event_read_flag;
u8 broadcast_aen_busy;
+ u16 broadcast_aen_pending;
u8 shost_recovery;
struct mutex reset_in_progress_mutex;
@@ -749,8 +810,8 @@ struct MPT2SAS_ADAPTER {
u32 event_masks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
/* static config pages */
- Mpi2IOCFactsReply_t facts;
- Mpi2PortFactsReply_t *pfacts;
+ struct mpt2sas_facts facts;
+ struct mpt2sas_port_facts *pfacts;
Mpi2ManufacturingPage0_t manu_pg0;
Mpi2BiosPage2_t bios_pg2;
Mpi2BiosPage3_t bios_pg3;
@@ -840,7 +901,7 @@ struct MPT2SAS_ADAPTER {
/* reply free queue */
u16 reply_free_queue_depth;
- u32 *reply_free;
+ __le32 *reply_free;
dma_addr_t reply_free_dma;
struct dma_pool *reply_free_dma_pool;
u32 reply_free_host_index;
@@ -932,8 +993,8 @@ void mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc);
u8 mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
u32 reply);
int mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle,
- uint channel, uint id, uint lun, u8 type, u16 smid_task,
- ulong timeout, struct scsi_cmnd *scmd);
+ uint channel, uint id, uint lun, u8 type, u16 smid_task,
+ ulong timeout, unsigned long serial_number, enum mutex_type m_type);
void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
void mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
void mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index 437c2d94c45..38ed0260959 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -994,7 +994,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
mpt2sas_scsih_issue_tm(ioc,
le16_to_cpu(mpi_request->FunctionDependent1), 0, 0,
0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 10,
- NULL);
+ 0, TM_MUTEX_ON);
ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
} else
mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
@@ -2706,13 +2706,13 @@ static DEVICE_ATTR(ioc_reset_count, S_IRUGO,
_ctl_ioc_reset_count_show, NULL);
struct DIAG_BUFFER_START {
- u32 Size;
- u32 DiagVersion;
+ __le32 Size;
+ __le32 DiagVersion;
u8 BufferType;
u8 Reserved[3];
- u32 Reserved1;
- u32 Reserved2;
- u32 Reserved3;
+ __le32 Reserved1;
+ __le32 Reserved2;
+ __le32 Reserved3;
};
/**
* _ctl_host_trace_buffer_size_show - host buffer size (trace only)
diff --git a/drivers/scsi/mpt2sas/mpt2sas_debug.h b/drivers/scsi/mpt2sas/mpt2sas_debug.h
index 3dcddfeb6f4..9731f8e661b 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_debug.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_debug.h
@@ -164,7 +164,7 @@ static inline void
_debug_dump_mf(void *mpi_request, int sz)
{
int i;
- u32 *mfp = (u32 *)mpi_request;
+ __le32 *mfp = (__le32 *)mpi_request;
printk(KERN_INFO "mf:\n\t");
for (i = 0; i < sz; i++) {
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index a7dbc6825f5..6abd2fcc43e 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -94,6 +94,10 @@ static u32 logging_level;
MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info "
"(default=0)");
+static ushort max_sectors = 0xFFFF;
+module_param(max_sectors, ushort, 0);
+MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 8192 default=8192");
+
/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
#define MPT2SAS_MAX_LUN (16895)
static int max_lun = MPT2SAS_MAX_LUN;
@@ -1956,7 +1960,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
case MPI2_RAID_VOL_TYPE_RAID1E:
qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
if (ioc->manu_pg10.OEMIdentifier &&
- (ioc->manu_pg10.GenericFlags0 &
+ (le32_to_cpu(ioc->manu_pg10.GenericFlags0) &
MFG10_GF0_R10_DISPLAY) &&
!(raid_device->num_pds % 2))
r_level = "RAID10";
@@ -2236,6 +2240,8 @@ mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
* @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
* @smid_task: smid assigned to the task
* @timeout: timeout in seconds
+ * @serial_number: the serial_number from scmd
+ * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF
* Context: user
*
* A generic API for sending task management requests to firmware.
@@ -2247,17 +2253,18 @@ mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
int
mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
uint id, uint lun, u8 type, u16 smid_task, ulong timeout,
- struct scsi_cmnd *scmd)
+ unsigned long serial_number, enum mutex_type m_type)
{
Mpi2SCSITaskManagementRequest_t *mpi_request;
Mpi2SCSITaskManagementReply_t *mpi_reply;
u16 smid = 0;
u32 ioc_state;
unsigned long timeleft;
- struct scsi_cmnd *scmd_lookup;
+ struct scsiio_tracker *scsi_lookup = NULL;
int rc;
- mutex_lock(&ioc->tm_cmds.mutex);
+ if (m_type == TM_MUTEX_ON)
+ mutex_lock(&ioc->tm_cmds.mutex);
if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) {
printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n",
__func__, ioc->name);
@@ -2277,18 +2284,18 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
if (ioc_state & MPI2_DOORBELL_USED) {
dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell "
"active!\n", ioc->name));
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
FORCE_BIG_HAMMER);
- rc = SUCCESS;
+ rc = (!rc) ? SUCCESS : FAILED;
goto err_out;
}
if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
mpt2sas_base_fault_info(ioc, ioc_state &
MPI2_DOORBELL_DATA_MASK);
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
FORCE_BIG_HAMMER);
- rc = SUCCESS;
+ rc = (!rc) ? SUCCESS : FAILED;
goto err_out;
}
@@ -2300,6 +2307,9 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
goto err_out;
}
+ if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
+ scsi_lookup = &ioc->scsi_lookup[smid_task - 1];
+
dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x),"
" task_type(0x%02x), smid(%d)\n", ioc->name, handle, type,
smid_task));
@@ -2307,6 +2317,7 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
ioc->tm_cmds.smid = smid;
memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
+ memset(ioc->tm_cmds.reply, 0, sizeof(Mpi2SCSITaskManagementReply_t));
mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
mpi_request->DevHandle = cpu_to_le16(handle);
mpi_request->TaskType = type;
@@ -2322,9 +2333,9 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
_debug_dump_mf(mpi_request,
sizeof(Mpi2SCSITaskManagementRequest_t)/4);
if (!(ioc->tm_cmds.status & MPT2_CMD_RESET)) {
- mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
FORCE_BIG_HAMMER);
- rc = SUCCESS;
+ rc = (!rc) ? SUCCESS : FAILED;
ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
mpt2sas_scsih_clear_tm_flag(ioc, handle);
goto err_out;
@@ -2346,20 +2357,12 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
}
}
- /* sanity check:
- * Check to see the commands were terminated.
- * This is only needed for eh callbacks, hence the scmd check.
- */
- rc = FAILED;
- if (scmd == NULL)
- goto bypass_sanity_checks;
switch (type) {
case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
- scmd_lookup = _scsih_scsi_lookup_get(ioc, smid_task);
- if (scmd_lookup)
- rc = FAILED;
- else
- rc = SUCCESS;
+ rc = SUCCESS;
+ if (scsi_lookup->scmd == NULL)
+ break;
+ rc = FAILED;
break;
case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
@@ -2369,24 +2372,31 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
rc = SUCCESS;
break;
+ case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel))
rc = FAILED;
else
rc = SUCCESS;
break;
+ case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
+ rc = SUCCESS;
+ break;
+ default:
+ rc = FAILED;
+ break;
}
- bypass_sanity_checks:
-
mpt2sas_scsih_clear_tm_flag(ioc, handle);
ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
- mutex_unlock(&ioc->tm_cmds.mutex);
+ if (m_type == TM_MUTEX_ON)
+ mutex_unlock(&ioc->tm_cmds.mutex);
return rc;
err_out:
- mutex_unlock(&ioc->tm_cmds.mutex);
+ if (m_type == TM_MUTEX_ON)
+ mutex_unlock(&ioc->tm_cmds.mutex);
return rc;
}
@@ -2496,7 +2506,8 @@ _scsih_abort(struct scsi_cmnd *scmd)
handle = sas_device_priv_data->sas_target->handle;
r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
scmd->device->id, scmd->device->lun,
- MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, scmd);
+ MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
+ scmd->serial_number, TM_MUTEX_ON);
out:
sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
@@ -2557,7 +2568,8 @@ _scsih_dev_reset(struct scsi_cmnd *scmd)
r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
scmd->device->id, scmd->device->lun,
- MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, scmd);
+ MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, 0,
+ TM_MUTEX_ON);
out:
sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
@@ -2617,7 +2629,7 @@ _scsih_target_reset(struct scsi_cmnd *scmd)
r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
- 30, scmd);
+ 30, 0, TM_MUTEX_ON);
out:
starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
@@ -2750,6 +2762,31 @@ _scsih_fw_event_cleanup_queue(struct MPT2SAS_ADAPTER *ioc)
}
/**
+ * _scsih_ublock_io_all_device - unblock every device
+ * @ioc: per adapter object
+ *
+ * change the device state from block to running
+ */
+static void
+_scsih_ublock_io_all_device(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct MPT2SAS_DEVICE *sas_device_priv_data;
+ struct scsi_device *sdev;
+
+ shost_for_each_device(sdev, ioc->shost) {
+ sas_device_priv_data = sdev->hostdata;
+ if (!sas_device_priv_data)
+ continue;
+ if (!sas_device_priv_data->block)
+ continue;
+ sas_device_priv_data->block = 0;
+ dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_running, "
+ "handle(0x%04x)\n",
+ sas_device_priv_data->sas_target->handle));
+ scsi_internal_device_unblock(sdev);
+ }
+}
+/**
* _scsih_ublock_io_device - set the device state to SDEV_RUNNING
* @ioc: per adapter object
* @handle: device handle
@@ -2779,6 +2816,34 @@ _scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
}
/**
+ * _scsih_block_io_all_device - set the device state to SDEV_BLOCK
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * During device pull we need to appropiately set the sdev state.
+ */
+static void
+_scsih_block_io_all_device(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct MPT2SAS_DEVICE *sas_device_priv_data;
+ struct scsi_device *sdev;
+
+ shost_for_each_device(sdev, ioc->shost) {
+ sas_device_priv_data = sdev->hostdata;
+ if (!sas_device_priv_data)
+ continue;
+ if (sas_device_priv_data->block)
+ continue;
+ sas_device_priv_data->block = 1;
+ dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_blocked, "
+ "handle(0x%04x)\n",
+ sas_device_priv_data->sas_target->handle));
+ scsi_internal_device_block(sdev);
+ }
+}
+
+
+/**
* _scsih_block_io_device - set the device state to SDEV_BLOCK
* @ioc: per adapter object
* @handle: device handle
@@ -3698,7 +3763,7 @@ _scsih_qcmd_lck(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
return 0;
}
- if (ioc->pci_error_recovery) {
+ if (ioc->pci_error_recovery || ioc->remove_host) {
scmd->result = DID_NO_CONNECT << 16;
scmd->scsi_done(scmd);
return 0;
@@ -4193,6 +4258,7 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
u32 log_info;
struct MPT2SAS_DEVICE *sas_device_priv_data;
u32 response_code = 0;
+ unsigned long flags;
mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
@@ -4217,6 +4283,9 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
* the failed direct I/O should be redirected to volume
*/
if (_scsih_scsi_direct_io_get(ioc, smid)) {
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ ioc->scsi_lookup[smid - 1].scmd = scmd;
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
_scsih_scsi_direct_io_set(ioc, smid, 0);
memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
mpi_request->DevHandle =
@@ -4598,7 +4667,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
Mpi2SasEnclosurePage0_t enclosure_pg0;
u32 ioc_status;
u16 parent_handle;
- __le64 sas_address, sas_address_parent = 0;
+ u64 sas_address, sas_address_parent = 0;
int i;
unsigned long flags;
struct _sas_port *mpt2sas_port = NULL;
@@ -5380,9 +5449,10 @@ _scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
break;
}
printk(MPT2SAS_INFO_FMT "device status change: (%s)\n"
- "\thandle(0x%04x), sas address(0x%016llx)", ioc->name,
- reason_str, le16_to_cpu(event_data->DevHandle),
- (unsigned long long)le64_to_cpu(event_data->SASAddress));
+ "\thandle(0x%04x), sas address(0x%016llx), tag(%d)",
+ ioc->name, reason_str, le16_to_cpu(event_data->DevHandle),
+ (unsigned long long)le64_to_cpu(event_data->SASAddress),
+ le16_to_cpu(event_data->TaskTag));
if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA)
printk(MPT2SAS_INFO_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name,
event_data->ASC, event_data->ASCQ);
@@ -5404,7 +5474,7 @@ _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc,
{
struct MPT2SAS_TARGET *target_priv_data;
struct _sas_device *sas_device;
- __le64 sas_address;
+ u64 sas_address;
unsigned long flags;
Mpi2EventDataSasDeviceStatusChange_t *event_data =
fw_event->event_data;
@@ -5522,25 +5592,38 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
u32 termination_count;
u32 query_count;
Mpi2SCSITaskManagementReply_t *mpi_reply;
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data;
-#endif
u16 ioc_status;
unsigned long flags;
int r;
+ u8 max_retries = 0;
+ u8 task_abort_retries;
+
+ mutex_lock(&ioc->tm_cmds.mutex);
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: phy number(%d), "
+ "width(%d)\n", ioc->name, __func__, event_data->PhyNum,
+ event_data->PortWidth));
- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "broadcast primitive: "
- "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum,
- event_data->PortWidth));
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
- __func__));
+ _scsih_block_io_all_device(ioc);
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- ioc->broadcast_aen_busy = 0;
+ mpi_reply = ioc->tm_cmds.reply;
+broadcast_aen_retry:
+
+ /* sanity checks for retrying this loop */
+ if (max_retries++ == 5) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: giving up\n",
+ ioc->name, __func__));
+ goto out;
+ } else if (max_retries > 1)
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: %d retry\n",
+ ioc->name, __func__, max_retries - 1));
+
termination_count = 0;
query_count = 0;
- mpi_reply = ioc->tm_cmds.reply;
for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
+ if (ioc->ioc_reset_in_progress_status)
+ goto out;
scmd = _scsih_scsi_lookup_get(ioc, smid);
if (!scmd)
continue;
@@ -5561,34 +5644,90 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
lun = sas_device_priv_data->lun;
query_count++;
+ if (ioc->ioc_reset_in_progress_status)
+ goto out;
+
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
- MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, NULL);
- ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
+ r = mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
+ MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, 0,
+ TM_MUTEX_OFF);
+ if (r == FAILED) {
+ sdev_printk(KERN_WARNING, sdev,
+ "mpt2sas_scsih_issue_tm: FAILED when sending "
+ "QUERY_TASK: scmd(%p)\n", scmd);
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ goto broadcast_aen_retry;
+ }
ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
& MPI2_IOCSTATUS_MASK;
- if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) &&
- (mpi_reply->ResponseCode ==
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ sdev_printk(KERN_WARNING, sdev, "query task: FAILED "
+ "with IOCSTATUS(0x%04x), scmd(%p)\n", ioc_status,
+ scmd);
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ goto broadcast_aen_retry;
+ }
+
+ /* see if IO is still owned by IOC and target */
+ if (mpi_reply->ResponseCode ==
MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
mpi_reply->ResponseCode ==
- MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC)) {
+ MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) {
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
continue;
}
+ task_abort_retries = 0;
+ tm_retry:
+ if (task_abort_retries++ == 60) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
+ "%s: ABORT_TASK: giving up\n", ioc->name,
+ __func__));
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ goto broadcast_aen_retry;
+ }
+
+ if (ioc->ioc_reset_in_progress_status)
+ goto out_no_lock;
+
r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
- scmd);
- if (r == FAILED)
- sdev_printk(KERN_WARNING, sdev, "task abort: FAILED "
+ scmd->serial_number, TM_MUTEX_OFF);
+ if (r == FAILED) {
+ sdev_printk(KERN_WARNING, sdev,
+ "mpt2sas_scsih_issue_tm: ABORT_TASK: FAILED : "
"scmd(%p)\n", scmd);
+ goto tm_retry;
+ }
+
+ if (task_abort_retries > 1)
+ sdev_printk(KERN_WARNING, sdev,
+ "mpt2sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):"
+ " scmd(%p)\n",
+ task_abort_retries - 1, scmd);
+
termination_count += le32_to_cpu(mpi_reply->TerminationCount);
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
}
+
+ if (ioc->broadcast_aen_pending) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: loop back due to"
+ " pending AEN\n", ioc->name, __func__));
+ ioc->broadcast_aen_pending = 0;
+ goto broadcast_aen_retry;
+ }
+
+ out:
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+ out_no_lock:
- dtmprintk(ioc, printk(MPT2SAS_INFO_FMT
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
"%s - exit, query_count = %d termination_count = %d\n",
ioc->name, __func__, query_count, termination_count));
+
+ ioc->broadcast_aen_busy = 0;
+ if (!ioc->ioc_reset_in_progress_status)
+ _scsih_ublock_io_all_device(ioc);
+ mutex_unlock(&ioc->tm_cmds.mutex);
}
/**
@@ -6566,7 +6705,7 @@ _scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc)
Mpi2ExpanderPage0_t expander_pg0;
Mpi2ConfigReply_t mpi_reply;
u16 ioc_status;
- __le64 sas_address;
+ u64 sas_address;
u16 handle;
printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__);
@@ -6862,10 +7001,14 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
mpi_reply->EventData;
if (baen_data->Primitive !=
- MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT ||
- ioc->broadcast_aen_busy)
+ MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
return 1;
- ioc->broadcast_aen_busy = 1;
+
+ if (ioc->broadcast_aen_busy) {
+ ioc->broadcast_aen_pending++;
+ return 1;
+ } else
+ ioc->broadcast_aen_busy = 1;
break;
}
@@ -7211,7 +7354,6 @@ _scsih_remove(struct pci_dev *pdev)
}
sas_remove_host(shost);
- _scsih_shutdown(pdev);
list_del(&ioc->list);
scsi_remove_host(shost);
scsi_host_put(shost);
@@ -7436,6 +7578,25 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
shost->transportt = mpt2sas_transport_template;
shost->unique_id = ioc->id;
+ if (max_sectors != 0xFFFF) {
+ if (max_sectors < 64) {
+ shost->max_sectors = 64;
+ printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
+ "for max_sectors, range is 64 to 8192. Assigning "
+ "value of 64.\n", ioc->name, max_sectors);
+ } else if (max_sectors > 8192) {
+ shost->max_sectors = 8192;
+ printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
+ "for max_sectors, range is 64 to 8192. Assigning "
+ "default value of 8192.\n", ioc->name,
+ max_sectors);
+ } else {
+ shost->max_sectors = max_sectors & 0xFFFE;
+ printk(MPT2SAS_INFO_FMT "The max_sectors value is "
+ "set to %d\n", ioc->name, shost->max_sectors);
+ }
+ }
+
if ((scsi_add_host(shost, &pdev->dev))) {
printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
@@ -7505,7 +7666,7 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- u32 device_state;
+ pci_power_t device_state;
mpt2sas_base_stop_watchdog(ioc);
scsi_block_requests(shost);
@@ -7532,7 +7693,7 @@ _scsih_resume(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- u32 device_state = pdev->current_state;
+ pci_power_t device_state = pdev->current_state;
int r;
printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, previous "
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
index cb1cdecbe0f..15c79802621 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -299,7 +299,6 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
void *data_out = NULL;
dma_addr_t data_out_dma;
u32 sz;
- u64 *sas_address_le;
u16 wait_state_count;
if (ioc->shost_recovery || ioc->pci_error_recovery) {
@@ -372,8 +371,7 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
mpi_request->PhysicalPort = 0xFF;
mpi_request->VF_ID = 0; /* TODO */
mpi_request->VP_ID = 0;
- sas_address_le = (u64 *)&mpi_request->SASAddress;
- *sas_address_le = cpu_to_le64(sas_address);
+ mpi_request->SASAddress = cpu_to_le64(sas_address);
mpi_request->RequestDataLength =
cpu_to_le16(sizeof(struct rep_manu_request));
psge = &mpi_request->SGL;
@@ -1049,14 +1047,14 @@ struct phy_error_log_reply{
u8 function; /* 0x11 */
u8 function_result;
u8 response_length;
- u16 expander_change_count;
+ __be16 expander_change_count;
u8 reserved_1[3];
u8 phy_identifier;
u8 reserved_2[2];
- u32 invalid_dword;
- u32 running_disparity_error;
- u32 loss_of_dword_sync;
- u32 phy_reset_problem;
+ __be32 invalid_dword;
+ __be32 running_disparity_error;
+ __be32 loss_of_dword_sync;
+ __be32 phy_reset_problem;
};
/**
@@ -1085,7 +1083,6 @@ _transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc,
void *data_out = NULL;
dma_addr_t data_out_dma;
u32 sz;
- u64 *sas_address_le;
u16 wait_state_count;
if (ioc->shost_recovery || ioc->pci_error_recovery) {
@@ -1160,8 +1157,7 @@ _transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc,
mpi_request->PhysicalPort = 0xFF;
mpi_request->VF_ID = 0; /* TODO */
mpi_request->VP_ID = 0;
- sas_address_le = (u64 *)&mpi_request->SASAddress;
- *sas_address_le = cpu_to_le64(phy->identify.sas_address);
+ mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
mpi_request->RequestDataLength =
cpu_to_le16(sizeof(struct phy_error_log_request));
psge = &mpi_request->SGL;
@@ -1406,7 +1402,6 @@ _transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc,
void *data_out = NULL;
dma_addr_t data_out_dma;
u32 sz;
- u64 *sas_address_le;
u16 wait_state_count;
if (ioc->shost_recovery) {
@@ -1486,8 +1481,7 @@ _transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc,
mpi_request->PhysicalPort = 0xFF;
mpi_request->VF_ID = 0; /* TODO */
mpi_request->VP_ID = 0;
- sas_address_le = (u64 *)&mpi_request->SASAddress;
- *sas_address_le = cpu_to_le64(phy->identify.sas_address);
+ mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
mpi_request->RequestDataLength =
cpu_to_le16(sizeof(struct phy_error_log_request));
psge = &mpi_request->SGL;
@@ -1914,7 +1908,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
mpi_request->PhysicalPort = 0xFF;
mpi_request->VF_ID = 0; /* TODO */
mpi_request->VP_ID = 0;
- *((u64 *)&mpi_request->SASAddress) = (rphy) ?
+ mpi_request->SASAddress = (rphy) ?
cpu_to_le64(rphy->identify.sas_address) :
cpu_to_le64(ioc->sas_hba.sas_address);
mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);