summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth D. Merry <ken@FreeBSD.org>2012-06-28 03:48:54 +0000
committerKenneth D. Merry <ken@FreeBSD.org>2012-06-28 03:48:54 +0000
commitbe4aa869c136dacfdab172324f174bb7f8ecd1b7 (patch)
tree382707df0635d8ea8fe8e1c5446a9b0e2f6cb21b
parent905cb85d78f63676a2f391fe03bbfcc64af03412 (diff)
Notes
-rw-r--r--sys/dev/mps/mpi/mpi2.h4
-rw-r--r--sys/dev/mps/mpi/mpi2_cnfg.h4
-rw-r--r--sys/dev/mps/mpi/mpi2_hbd.h4
-rw-r--r--sys/dev/mps/mpi/mpi2_history.txt4
-rw-r--r--sys/dev/mps/mpi/mpi2_init.h4
-rw-r--r--sys/dev/mps/mpi/mpi2_ioc.h4
-rw-r--r--sys/dev/mps/mpi/mpi2_ra.h4
-rw-r--r--sys/dev/mps/mpi/mpi2_raid.h4
-rw-r--r--sys/dev/mps/mpi/mpi2_sas.h4
-rw-r--r--sys/dev/mps/mpi/mpi2_targ.h4
-rw-r--r--sys/dev/mps/mpi/mpi2_tool.h4
-rw-r--r--sys/dev/mps/mpi/mpi2_type.h4
-rw-r--r--sys/dev/mps/mps.c405
-rw-r--r--sys/dev/mps/mps_config.c3
-rw-r--r--sys/dev/mps/mps_ioctl.h2
-rw-r--r--sys/dev/mps/mps_mapping.c2
-rw-r--r--sys/dev/mps/mps_mapping.h2
-rw-r--r--sys/dev/mps/mps_sas.c319
-rw-r--r--sys/dev/mps/mps_sas.h2
-rw-r--r--sys/dev/mps/mps_sas_lsi.c147
-rw-r--r--sys/dev/mps/mps_user.c48
-rw-r--r--sys/dev/mps/mpsvar.h68
22 files changed, 668 insertions, 378 deletions
diff --git a/sys/dev/mps/mpi/mpi2.h b/sys/dev/mps/mpi/mpi2.h
index b9e46adea049..45fb7d9b73c1 100644
--- a/sys/dev/mps/mpi/mpi2.h
+++ b/sys/dev/mps/mpi/mpi2.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,7 @@
*/
/*
- * Copyright (c) 2000-2011 LSI Corporation.
+ * Copyright (c) 2000-2012 LSI Corporation.
*
*
* Name: mpi2.h
diff --git a/sys/dev/mps/mpi/mpi2_cnfg.h b/sys/dev/mps/mpi/mpi2_cnfg.h
index ef3334f0f505..4db5f099d339 100644
--- a/sys/dev/mps/mpi/mpi2_cnfg.h
+++ b/sys/dev/mps/mpi/mpi2_cnfg.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,7 @@
*/
/*
- * Copyright (c) 2000-2011 LSI Corporation.
+ * Copyright (c) 2000-2012 LSI Corporation.
*
*
* Name: mpi2_cnfg.h
diff --git a/sys/dev/mps/mpi/mpi2_hbd.h b/sys/dev/mps/mpi/mpi2_hbd.h
index e31fc5ec4323..d8645e688e1c 100644
--- a/sys/dev/mps/mpi/mpi2_hbd.h
+++ b/sys/dev/mps/mpi/mpi2_hbd.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,7 @@
*/
/*
- * Copyright (c) 2009-2011 LSI Corporation.
+ * Copyright (c) 2009-2012 LSI Corporation.
*
*
* Name: mpi2_hbd.h
diff --git a/sys/dev/mps/mpi/mpi2_history.txt b/sys/dev/mps/mpi/mpi2_history.txt
index 01dc3b6ee948..e6bb5b00817a 100644
--- a/sys/dev/mps/mpi/mpi2_history.txt
+++ b/sys/dev/mps/mpi/mpi2_history.txt
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,7 +32,7 @@
Fusion-MPT MPI 2.0 Header File Change History
==============================
- Copyright (c) 2000-2011 LSI Corporation.
+ Copyright (c) 2000-2012 LSI Corporation.
---------------------------------------
Header Set Release Version: 02.00.18
diff --git a/sys/dev/mps/mpi/mpi2_init.h b/sys/dev/mps/mpi/mpi2_init.h
index ca4a685d6553..0f0a1927eac5 100644
--- a/sys/dev/mps/mpi/mpi2_init.h
+++ b/sys/dev/mps/mpi/mpi2_init.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,7 @@
*/
/*
- * Copyright (c) 2000-2011 LSI Corporation.
+ * Copyright (c) 2000-2012 LSI Corporation.
*
*
* Name: mpi2_init.h
diff --git a/sys/dev/mps/mpi/mpi2_ioc.h b/sys/dev/mps/mpi/mpi2_ioc.h
index ca19a5c32f3a..fd4df2b271ff 100644
--- a/sys/dev/mps/mpi/mpi2_ioc.h
+++ b/sys/dev/mps/mpi/mpi2_ioc.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,7 @@
*/
/*
- * Copyright (c) 2000-2011 LSI Corporation.
+ * Copyright (c) 2000-2012 LSI Corporation.
*
*
* Name: mpi2_ioc.h
diff --git a/sys/dev/mps/mpi/mpi2_ra.h b/sys/dev/mps/mpi/mpi2_ra.h
index 0f012269bc4f..2847fa9ddc05 100644
--- a/sys/dev/mps/mpi/mpi2_ra.h
+++ b/sys/dev/mps/mpi/mpi2_ra.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,7 @@
*/
/*
- * Copyright (c) 2011 LSI Corporation.
+ * Copyright (c) 2012 LSI Corporation.
*
*
* Name: mpi2_ra.h
diff --git a/sys/dev/mps/mpi/mpi2_raid.h b/sys/dev/mps/mpi/mpi2_raid.h
index 557468a4b2a2..2d497ee5de5a 100644
--- a/sys/dev/mps/mpi/mpi2_raid.h
+++ b/sys/dev/mps/mpi/mpi2_raid.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,7 @@
*/
/*
- * Copyright (c) 2000-2011 LSI Corporation.
+ * Copyright (c) 2000-2012 LSI Corporation.
*
*
* Name: mpi2_raid.h
diff --git a/sys/dev/mps/mpi/mpi2_sas.h b/sys/dev/mps/mpi/mpi2_sas.h
index 1f3341f24b6a..54a995b79380 100644
--- a/sys/dev/mps/mpi/mpi2_sas.h
+++ b/sys/dev/mps/mpi/mpi2_sas.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,7 @@
*/
/*
- * Copyright (c) 2000-2011 LSI Corporation.
+ * Copyright (c) 2000-2012 LSI Corporation.
*
*
* Name: mpi2_sas.h
diff --git a/sys/dev/mps/mpi/mpi2_targ.h b/sys/dev/mps/mpi/mpi2_targ.h
index fcd694cb0b6b..179ca537dc85 100644
--- a/sys/dev/mps/mpi/mpi2_targ.h
+++ b/sys/dev/mps/mpi/mpi2_targ.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,7 @@
*/
/*
- * Copyright (c) 2000-2011 LSI Corporation.
+ * Copyright (c) 2000-2012 LSI Corporation.
*
*
* Name: mpi2_targ.h
diff --git a/sys/dev/mps/mpi/mpi2_tool.h b/sys/dev/mps/mpi/mpi2_tool.h
index 16c0ffc6fb0e..73ece21fe1d2 100644
--- a/sys/dev/mps/mpi/mpi2_tool.h
+++ b/sys/dev/mps/mpi/mpi2_tool.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,7 @@
*/
/*
- * Copyright (c) 2000-2011 LSI Corporation.
+ * Copyright (c) 2000-2012 LSI Corporation.
*
*
* Name: mpi2_tool.h
diff --git a/sys/dev/mps/mpi/mpi2_type.h b/sys/dev/mps/mpi/mpi2_type.h
index fa4ecd9b7ff4..0ea541a48cb7 100644
--- a/sys/dev/mps/mpi/mpi2_type.h
+++ b/sys/dev/mps/mpi/mpi2_type.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,7 @@
*/
/*
- * Copyright (c) 2000-2011 LSI Corporation.
+ * Copyright (c) 2000-2012 LSI Corporation.
*
*
* Name: mpi2_type.h
diff --git a/sys/dev/mps/mps.c b/sys/dev/mps/mps.c
index e11e9a62243f..1d935be1f0f0 100644
--- a/sys/dev/mps/mps.c
+++ b/sys/dev/mps/mps.c
@@ -1,31 +1,6 @@
/*-
* Copyright (c) 2009 Yahoo! Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -82,6 +57,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
+#include <sys/proc.h>
#include <dev/pci/pcivar.h>
@@ -98,9 +74,9 @@ __FBSDID("$FreeBSD$");
#include <dev/mps/mpsvar.h>
#include <dev/mps/mps_table.h>
-static int mps_diag_reset(struct mps_softc *sc);
+static int mps_diag_reset(struct mps_softc *sc, int sleep_flag);
static int mps_init_queues(struct mps_softc *sc);
-static int mps_message_unit_reset(struct mps_softc *sc);
+static int mps_message_unit_reset(struct mps_softc *sc, int sleep_flag);
static int mps_transition_operational(struct mps_softc *sc);
static void mps_startup(void *arg);
static int mps_send_iocinit(struct mps_softc *sc);
@@ -112,7 +88,7 @@ static void mps_config_complete(struct mps_softc *sc, struct mps_command *cm);
static void mps_periodic(void *);
static int mps_reregister_events(struct mps_softc *sc);
static void mps_enqueue_request(struct mps_softc *sc, struct mps_command *cm);
-
+static int mps_wait_db_ack(struct mps_softc *sc, int timeout, int sleep_flag);
SYSCTL_NODE(_hw, OID_AUTO, mps, CTLFLAG_RD, 0, "MPS Driver Parameters");
MALLOC_DEFINE(M_MPT2, "mps", "mpt2 driver memory");
@@ -123,8 +99,32 @@ MALLOC_DEFINE(M_MPT2, "mps", "mpt2 driver memory");
*/
static char mpt2_reset_magic[] = { 0x00, 0x0f, 0x04, 0x0b, 0x02, 0x07, 0x0d };
+/* Added this union to smoothly convert le64toh cm->cm_desc.Words.
+ * Compiler only support unint64_t to be passed as argument.
+ * Otherwise it will through below error
+ * "aggregate value used where an integer was expected"
+ */
+
+typedef union _reply_descriptor {
+ u64 word;
+ struct {
+ u32 low;
+ u32 high;
+ } u;
+}reply_descriptor,address_descriptor;
+
+/*
+ * sleep_flag can be either CAN_SLEEP or NO_SLEEP.
+ * If this function is called from process context, it can sleep
+ * and there is no harm to sleep, in case if this fuction is called
+ * from Interrupt handler, we can not sleep and need NO_SLEEP flag set.
+ * based on sleep flags driver will call either msleep, pause or DELAY.
+ * msleep and pause are of same variant, but pause is used when mps_mtx
+ * is not hold by driver.
+ *
+ */
static int
-mps_diag_reset(struct mps_softc *sc)
+mps_diag_reset(struct mps_softc *sc,int sleep_flag)
{
uint32_t reg;
int i, error, tries = 0;
@@ -134,14 +134,25 @@ mps_diag_reset(struct mps_softc *sc)
/* Clear any pending interrupts */
mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
+ /*Force NO_SLEEP for threads prohibited to sleep
+ * e.a Thread from interrupt handler are prohibited to sleep.
+ */
+ if(curthread->td_pflags & TDP_NOSLEEPING)
+ sleep_flag = NO_SLEEP;
+
/* Push the magic sequence */
error = ETIMEDOUT;
while (tries++ < 20) {
for (i = 0; i < sizeof(mpt2_reset_magic); i++)
mps_regwrite(sc, MPI2_WRITE_SEQUENCE_OFFSET,
mpt2_reset_magic[i]);
-
- DELAY(100 * 1000);
+ /* wait 100 msec */
+ if (mtx_owned(&sc->mps_mtx) && sleep_flag == CAN_SLEEP)
+ msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0, "mpsdiag", hz/10);
+ else if (sleep_flag == CAN_SLEEP)
+ pause("mpsdiag", hz/10);
+ else
+ DELAY(100 * 1000);
reg = mps_regread(sc, MPI2_HOST_DIAGNOSTIC_OFFSET);
if (reg & MPI2_DIAG_DIAG_WRITE_ENABLE) {
@@ -159,7 +170,13 @@ mps_diag_reset(struct mps_softc *sc)
/* Wait up to 300 seconds in 50ms intervals */
error = ETIMEDOUT;
for (i = 0; i < 60000; i++) {
- DELAY(50000);
+ /* wait 50 msec */
+ if (mtx_owned(&sc->mps_mtx) && sleep_flag == CAN_SLEEP)
+ msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0, "mpsdiag", hz/20);
+ else if (sleep_flag == CAN_SLEEP)
+ pause("mpsdiag", hz/20);
+ else
+ DELAY(50 * 1000);
reg = mps_regread(sc, MPI2_DOORBELL_OFFSET);
if ((reg & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_RESET) {
error = 0;
@@ -175,7 +192,7 @@ mps_diag_reset(struct mps_softc *sc)
}
static int
-mps_message_unit_reset(struct mps_softc *sc)
+mps_message_unit_reset(struct mps_softc *sc, int sleep_flag)
{
mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
@@ -183,7 +200,12 @@ mps_message_unit_reset(struct mps_softc *sc)
mps_regwrite(sc, MPI2_DOORBELL_OFFSET,
MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET <<
MPI2_DOORBELL_FUNCTION_SHIFT);
- DELAY(50000);
+
+ if (mps_wait_db_ack(sc, 5, sleep_flag) != 0) {
+ mps_dprint(sc, MPS_FAULT, "Doorbell handshake failed : <%s>\n",
+ __func__);
+ return (ETIMEDOUT);
+ }
return (0);
}
@@ -193,9 +215,12 @@ mps_transition_ready(struct mps_softc *sc)
{
uint32_t reg, state;
int error, tries = 0;
+ int sleep_flags;
mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
-
+ /* If we are in attach call, do not sleep */
+ sleep_flags = (sc->mps_flags & MPS_FLAGS_ATTACH_DONE)
+ ? CAN_SLEEP:NO_SLEEP;
error = 0;
while (tries++ < 5) {
reg = mps_regread(sc, MPI2_DOORBELL_OFFSET);
@@ -206,7 +231,7 @@ mps_transition_ready(struct mps_softc *sc)
* resetting it.
*/
if (reg & MPI2_DOORBELL_USED) {
- mps_diag_reset(sc);
+ mps_diag_reset(sc, sleep_flags);
DELAY(50000);
continue;
}
@@ -227,10 +252,10 @@ mps_transition_ready(struct mps_softc *sc)
} else if (state == MPI2_IOC_STATE_FAULT) {
mps_dprint(sc, MPS_INFO, "IOC in fault state 0x%x\n",
state & MPI2_DOORBELL_FAULT_CODE_MASK);
- mps_diag_reset(sc);
+ mps_diag_reset(sc, sleep_flags);
} else if (state == MPI2_IOC_STATE_OPERATIONAL) {
/* Need to take ownership */
- mps_message_unit_reset(sc);
+ mps_message_unit_reset(sc, sleep_flags);
} else if (state == MPI2_IOC_STATE_RESET) {
/* Wait a bit, IOC might be in transition */
mps_dprint(sc, MPS_FAULT,
@@ -310,7 +335,7 @@ mps_reinit(struct mps_softc *sc)
mps_printf(sc, "%s mask interrupts\n", __func__);
mps_mask_intr(sc);
- error = mps_diag_reset(sc);
+ error = mps_diag_reset(sc, CAN_SLEEP);
if (error != 0) {
panic("%s hard reset failed with error %d\n",
__func__, error);
@@ -368,19 +393,56 @@ mps_reinit(struct mps_softc *sc)
return 0;
}
-/* Wait for the chip to ACK a word that we've put into its FIFO */
+/* Wait for the chip to ACK a word that we've put into its FIFO
+ * Wait for <timeout> seconds. In single loop wait for busy loop
+ * for 500 microseconds.
+ * Total is [ 0.5 * (2000 * <timeout>) ] in miliseconds.
+ * */
static int
-mps_wait_db_ack(struct mps_softc *sc)
+mps_wait_db_ack(struct mps_softc *sc, int timeout, int sleep_flag)
{
- int retry;
- for (retry = 0; retry < MPS_DB_MAX_WAIT; retry++) {
- if ((mps_regread(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET) &
- MPI2_HIS_SYS2IOC_DB_STATUS) == 0)
- return (0);
- DELAY(2000);
- }
+ u32 cntdn, count;
+ u32 int_status;
+ u32 doorbell;
+
+ count = 0;
+ cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
+ do {
+ int_status = mps_regread(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET);
+ if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) {
+ mps_dprint(sc, MPS_INFO,
+ "%s: successfull count(%d), timeout(%d)\n",
+ __func__, count, timeout);
+ return 0;
+ } else if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
+ doorbell = mps_regread(sc, MPI2_DOORBELL_OFFSET);
+ if ((doorbell & MPI2_IOC_STATE_MASK) ==
+ MPI2_IOC_STATE_FAULT) {
+ mps_dprint(sc, MPS_FAULT,
+ "fault_state(0x%04x)!\n", doorbell);
+ return (EFAULT);
+ }
+ } else if (int_status == 0xFFFFFFFF)
+ goto out;
+
+ /* If it can sleep, sleep for 1 milisecond, else busy loop for
+ * 0.5 milisecond */
+ if (mtx_owned(&sc->mps_mtx) && sleep_flag == CAN_SLEEP)
+ msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0,
+ "mpsdba", hz/1000);
+ else if (sleep_flag == CAN_SLEEP)
+ pause("mpsdba", hz/1000);
+ else
+ DELAY(500);
+ count++;
+ } while (--cntdn);
+
+ out:
+ mps_dprint(sc, MPS_FAULT, "%s: failed due to timeout count(%d), "
+ "int_status(%x)!\n", __func__, count, int_status);
return (ETIMEDOUT);
+
}
/* Wait for the chip to signal that the next word in its FIFO can be fetched */
@@ -406,6 +468,10 @@ mps_request_sync(struct mps_softc *sc, void *req, MPI2_DEFAULT_REPLY *reply,
uint32_t *data32;
uint16_t *data16;
int i, count, ioc_sz, residual;
+ int sleep_flags = CAN_SLEEP;
+
+ if(curthread->td_pflags & TDP_NOSLEEPING)
+ sleep_flags = NO_SLEEP;
/* Step 1 */
mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
@@ -430,7 +496,7 @@ mps_request_sync(struct mps_softc *sc, void *req, MPI2_DEFAULT_REPLY *reply,
return (ENXIO);
}
mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
- if (mps_wait_db_ack(sc) != 0) {
+ if (mps_wait_db_ack(sc, 5, sleep_flags) != 0) {
mps_dprint(sc, MPS_FAULT, "Doorbell handshake failed\n");
return (ENXIO);
}
@@ -439,8 +505,8 @@ mps_request_sync(struct mps_softc *sc, void *req, MPI2_DEFAULT_REPLY *reply,
/* Clock out the message data synchronously in 32-bit dwords*/
data32 = (uint32_t *)req;
for (i = 0; i < count; i++) {
- mps_regwrite(sc, MPI2_DOORBELL_OFFSET, data32[i]);
- if (mps_wait_db_ack(sc) != 0) {
+ mps_regwrite(sc, MPI2_DOORBELL_OFFSET, htole32(data32[i]));
+ if (mps_wait_db_ack(sc, 5, sleep_flags) != 0) {
mps_dprint(sc, MPS_FAULT,
"Timeout while writing doorbell\n");
return (ENXIO);
@@ -525,7 +591,7 @@ mps_request_sync(struct mps_softc *sc, void *req, MPI2_DEFAULT_REPLY *reply,
static void
mps_enqueue_request(struct mps_softc *sc, struct mps_command *cm)
{
-
+ reply_descriptor rd;
mps_dprint(sc, MPS_TRACE, "%s SMID %u cm %p ccb %p\n", __func__,
cm->cm_desc.Default.SMID, cm, cm->cm_ccb);
@@ -534,11 +600,14 @@ mps_enqueue_request(struct mps_softc *sc, struct mps_command *cm)
if (++sc->io_cmds_active > sc->io_cmds_highwater)
sc->io_cmds_highwater++;
-
+ rd.u.low = cm->cm_desc.Words.Low;
+ rd.u.high = cm->cm_desc.Words.High;
+ rd.word = htole64(rd.word);
+ /* TODO-We may need to make below regwrite atomic */
mps_regwrite(sc, MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET,
- cm->cm_desc.Words.Low);
+ rd.u.low);
mps_regwrite(sc, MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET,
- cm->cm_desc.Words.High);
+ rd.u.high);
}
/*
@@ -622,21 +691,21 @@ mps_send_iocinit(struct mps_softc *sc)
*/
init.Function = MPI2_FUNCTION_IOC_INIT;
init.WhoInit = MPI2_WHOINIT_HOST_DRIVER;
- init.MsgVersion = MPI2_VERSION;
- init.HeaderVersion = MPI2_HEADER_VERSION;
- init.SystemRequestFrameSize = sc->facts->IOCRequestFrameSize;
- init.ReplyDescriptorPostQueueDepth = sc->pqdepth;
- init.ReplyFreeQueueDepth = sc->fqdepth;
+ init.MsgVersion = htole16(MPI2_VERSION);
+ init.HeaderVersion = htole16(MPI2_HEADER_VERSION);
+ init.SystemRequestFrameSize = htole16(sc->facts->IOCRequestFrameSize);
+ init.ReplyDescriptorPostQueueDepth = htole16(sc->pqdepth);
+ init.ReplyFreeQueueDepth = htole16(sc->fqdepth);
init.SenseBufferAddressHigh = 0;
init.SystemReplyAddressHigh = 0;
init.SystemRequestFrameBaseAddress.High = 0;
- init.SystemRequestFrameBaseAddress.Low = (uint32_t)sc->req_busaddr;
+ init.SystemRequestFrameBaseAddress.Low = htole32((uint32_t)sc->req_busaddr);
init.ReplyDescriptorPostQueueAddress.High = 0;
- init.ReplyDescriptorPostQueueAddress.Low = (uint32_t)sc->post_busaddr;
+ init.ReplyDescriptorPostQueueAddress.Low = htole32((uint32_t)sc->post_busaddr);
init.ReplyFreeQueueAddress.High = 0;
- init.ReplyFreeQueueAddress.Low = (uint32_t)sc->free_busaddr;
+ init.ReplyFreeQueueAddress.Low = htole32((uint32_t)sc->free_busaddr);
init.TimeStamp.High = 0;
- init.TimeStamp.Low = (uint32_t)time_uptime;
+ init.TimeStamp.Low = htole32((uint32_t)time_uptime);
error = mps_request_sync(sc, &init, &reply, req_sz, reply_sz, 5);
if ((reply.IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
@@ -830,6 +899,12 @@ mps_alloc_requests(struct mps_softc *sc)
sc->chains = malloc(sizeof(struct mps_chain) * sc->max_chains, M_MPT2,
M_WAITOK | M_ZERO);
+ if(!sc->chains) {
+ device_printf(sc->mps_dev,
+ "Cannot allocate chains memory %s %d\n",
+ __func__, __LINE__);
+ return (ENOMEM);
+ }
for (i = 0; i < sc->max_chains; i++) {
chain = &sc->chains[i];
chain->chain = (MPI2_SGE_IO_UNION *)(sc->chain_frames +
@@ -864,6 +939,11 @@ mps_alloc_requests(struct mps_softc *sc)
*/
sc->commands = malloc(sizeof(struct mps_command) * sc->num_reqs,
M_MPT2, M_WAITOK | M_ZERO);
+ if(!sc->commands) {
+ device_printf(sc->mps_dev, "Cannot allocate memory %s %d\n",
+ __func__, __LINE__);
+ return (ENOMEM);
+ }
for (i = 1; i < sc->num_reqs; i++) {
cm = &sc->commands[i];
cm->cm_req = sc->req_frames +
@@ -1056,6 +1136,11 @@ mps_attach(struct mps_softc *sc)
sc->facts = malloc(sizeof(MPI2_IOC_FACTS_REPLY), M_MPT2,
M_ZERO|M_NOWAIT);
+ if(!sc->facts) {
+ device_printf(sc->mps_dev, "Cannot allocate memory %s %d\n",
+ __func__, __LINE__);
+ return (ENOMEM);
+ }
if ((error = mps_get_iocfacts(sc, sc->facts)) != 0)
return (error);
@@ -1083,7 +1168,7 @@ mps_attach(struct mps_softc *sc)
*/
if ((sc->facts->IOCCapabilities &
MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY) == 0) {
- mps_diag_reset(sc);
+ mps_diag_reset(sc, NO_SLEEP);
if ((error = mps_transition_ready(sc)) != 0)
return (error);
}
@@ -1163,6 +1248,11 @@ mps_attach(struct mps_softc *sc)
sc->pfacts = malloc(sizeof(MPI2_PORT_FACTS_REPLY) *
sc->facts->NumberOfPorts, M_MPT2, M_ZERO|M_WAITOK);
+ if(!sc->pfacts) {
+ device_printf(sc->mps_dev, "Cannot allocate memory %s %d\n",
+ __func__, __LINE__);
+ return (ENOMEM);
+ }
for (i = 0; i < sc->facts->NumberOfPorts; i++) {
if ((error = mps_get_portfacts(sc, &sc->pfacts[i], i)) != 0) {
mps_printf(sc, "%s failed to get portfacts for port %d\n",
@@ -1293,7 +1383,7 @@ mps_log_evt_handler(struct mps_softc *sc, uintptr_t data,
static int
mps_attach_log(struct mps_softc *sc)
{
- uint8_t events[16];
+ u32 events[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
bzero(events, 16);
setbit(events, MPI2_EVENT_LOG_DATA);
@@ -1441,6 +1531,64 @@ mps_complete_command(struct mps_command *cm)
}
}
+
+static void
+mps_sas_log_info(struct mps_softc *sc , u32 log_info)
+{
+ union loginfo_type {
+ u32 loginfo;
+ struct {
+ u32 subcode:16;
+ u32 code:8;
+ u32 originator:4;
+ u32 bus_type:4;
+ } dw;
+ };
+ union loginfo_type sas_loginfo;
+ char *originator_str = NULL;
+
+ sas_loginfo.loginfo = log_info;
+ if (sas_loginfo.dw.bus_type != 3 /*SAS*/)
+ return;
+
+ /* each nexus loss loginfo */
+ if (log_info == 0x31170000)
+ return;
+
+ /* eat the loginfos associated with task aborts */
+ if ((log_info == 30050000 || log_info ==
+ 0x31140000 || log_info == 0x31130000))
+ return;
+
+ switch (sas_loginfo.dw.originator) {
+ case 0:
+ originator_str = "IOP";
+ break;
+ case 1:
+ originator_str = "PL";
+ break;
+ case 2:
+ originator_str = "IR";
+ break;
+}
+
+ mps_dprint(sc, MPS_INFO, "log_info(0x%08x): originator(%s), "
+ "code(0x%02x), sub_code(0x%04x)\n", log_info,
+ originator_str, sas_loginfo.dw.code,
+ sas_loginfo.dw.subcode);
+}
+
+static void
+mps_display_reply_info(struct mps_softc *sc, uint8_t *reply)
+{
+ MPI2DefaultReply_t *mpi_reply;
+ u16 sc_status;
+
+ mpi_reply = (MPI2DefaultReply_t*)reply;
+ sc_status = le16toh(mpi_reply->IOCStatus);
+ if (sc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
+ mps_sas_log_info(sc, le32toh(mpi_reply->IOCLogInfo));
+}
void
mps_intr(void *data)
{
@@ -1508,7 +1656,7 @@ mps_intr_locked(void *data)
flags = desc->Default.ReplyFlags &
MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
if ((flags == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
- || (desc->Words.High == 0xffffffff))
+ || (le32toh(desc->Words.High) == 0xffffffff))
break;
/* increment the replypostindex now, so that event handlers
@@ -1523,7 +1671,7 @@ mps_intr_locked(void *data)
switch (flags) {
case MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS:
- cm = &sc->commands[desc->SCSIIOSuccess.SMID];
+ cm = &sc->commands[le16toh(desc->SCSIIOSuccess.SMID)];
cm->cm_reply = NULL;
break;
case MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY:
@@ -1559,9 +1707,10 @@ mps_intr_locked(void *data)
sc->reply_frames, sc->fqdepth,
sc->facts->ReplyFrameSize * 4);
printf("%s: baddr %#x,\n", __func__, baddr);
+ /* LSI-TODO. See Linux Code. Need Gracefull exit*/
panic("Reply address out of range");
}
- if (desc->AddressReply.SMID == 0) {
+ if (le16toh(desc->AddressReply.SMID) == 0) {
if (((MPI2_DEFAULT_REPLY *)reply)->Function ==
MPI2_FUNCTION_DIAG_BUFFER_POST) {
/*
@@ -1573,7 +1722,7 @@ mps_intr_locked(void *data)
*/
rel_rep =
(MPI2_DIAG_RELEASE_REPLY *)reply;
- if (rel_rep->IOCStatus ==
+ if (le16toh(rel_rep->IOCStatus) ==
MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED)
{
pBuffer =
@@ -1589,10 +1738,10 @@ mps_intr_locked(void *data)
(MPI2_EVENT_NOTIFICATION_REPLY *)
reply);
} else {
- cm = &sc->commands[desc->AddressReply.SMID];
+ cm = &sc->commands[le16toh(desc->AddressReply.SMID)];
cm->cm_reply = reply;
cm->cm_reply_data =
- desc->AddressReply.ReplyFrameAddress;
+ le32toh(desc->AddressReply.ReplyFrameAddress);
}
break;
}
@@ -1606,9 +1755,14 @@ mps_intr_locked(void *data)
cm = NULL;
break;
}
+
- if (cm != NULL)
+ if (cm != NULL) {
+ // Print Error reply frame
+ if (cm->cm_reply)
+ mps_display_reply_info(sc,cm->cm_reply);
mps_complete_command(cm);
+ }
desc->Words.Low = 0xffffffff;
desc->Words.High = 0xffffffff;
@@ -1631,7 +1785,7 @@ mps_dispatch_event(struct mps_softc *sc, uintptr_t data,
struct mps_event_handle *eh;
int event, handled = 0;
- event = reply->Event;
+ event = le16toh(reply->Event);
TAILQ_FOREACH(eh, &sc->event_list, eh_list) {
if (isset(eh->mask, event)) {
eh->callback(sc, data, reply);
@@ -1640,7 +1794,7 @@ mps_dispatch_event(struct mps_softc *sc, uintptr_t data,
}
if (handled == 0)
- device_printf(sc->mps_dev, "Unhandled event 0x%x\n", event);
+ device_printf(sc->mps_dev, "Unhandled event 0x%x\n", le16toh(event));
/*
* This is the only place that the event/reply should be freed.
@@ -1671,13 +1825,18 @@ mps_reregister_events_complete(struct mps_softc *sc, struct mps_command *cm)
* suitable for the controller.
*/
int
-mps_register_events(struct mps_softc *sc, uint8_t *mask,
+mps_register_events(struct mps_softc *sc, u32 *mask,
mps_evt_callback_t *cb, void *data, struct mps_event_handle **handle)
{
struct mps_event_handle *eh;
int error = 0;
eh = malloc(sizeof(struct mps_event_handle), M_MPT2, M_WAITOK|M_ZERO);
+ if(!eh) {
+ device_printf(sc->mps_dev, "Cannot allocate memory %s %d\n",
+ __func__, __LINE__);
+ return (ENOMEM);
+ }
eh->callback = cb;
eh->data = data;
TAILQ_INSERT_TAIL(&sc->event_list, eh, eh_list);
@@ -1690,24 +1849,25 @@ mps_register_events(struct mps_softc *sc, uint8_t *mask,
int
mps_update_events(struct mps_softc *sc, struct mps_event_handle *handle,
- uint8_t *mask)
+ u32 *mask)
{
MPI2_EVENT_NOTIFICATION_REQUEST *evtreq;
MPI2_EVENT_NOTIFICATION_REPLY *reply;
struct mps_command *cm;
- struct mps_event_handle *eh;
int error, i;
mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
if ((mask != NULL) && (handle != NULL))
- bcopy(mask, &handle->mask[0], 16);
- memset(sc->event_mask, 0xff, 16);
+ bcopy(mask, &handle->mask[0], sizeof(u32) *
+ MPI2_EVENT_NOTIFY_EVENTMASK_WORDS);
+
+ for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
+ sc->event_mask[i] = -1;
+
+ for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
+ sc->event_mask[i] &= ~handle->mask[i];
- TAILQ_FOREACH(eh, &sc->event_list, eh_list) {
- for (i = 0; i < 16; i++)
- sc->event_mask[i] &= ~eh->mask[i];
- }
if ((cm = mps_alloc_command(sc)) == NULL)
return (EBUSY);
@@ -1719,10 +1879,13 @@ mps_update_events(struct mps_softc *sc, struct mps_event_handle *handle,
{
u_char fullmask[16];
memset(fullmask, 0x00, 16);
- bcopy(fullmask, (uint8_t *)&evtreq->EventMasks, 16);
+ bcopy(fullmask, &evtreq->EventMasks[0], sizeof(u32) *
+ MPI2_EVENT_NOTIFY_EVENTMASK_WORDS);
}
#else
- bcopy(sc->event_mask, (uint8_t *)&evtreq->EventMasks, 16);
+ for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
+ evtreq->EventMasks[i] =
+ htole32(sc->event_mask[i]);
#endif
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_data = NULL;
@@ -1751,10 +1914,11 @@ mps_reregister_events(struct mps_softc *sc)
/* first, reregister events */
- memset(sc->event_mask, 0xff, 16);
+ for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
+ sc->event_mask[i] = -1;
TAILQ_FOREACH(eh, &sc->event_list, eh_list) {
- for (i = 0; i < 16; i++)
+ for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
sc->event_mask[i] &= ~eh->mask[i];
}
@@ -1768,10 +1932,13 @@ mps_reregister_events(struct mps_softc *sc)
{
u_char fullmask[16];
memset(fullmask, 0x00, 16);
- bcopy(fullmask, (uint8_t *)&evtreq->EventMasks, 16);
+ bcopy(fullmask, &evtreq->EventMasks[0], sizeof(u32) *
+ MPI2_EVENT_NOTIFY_EVENTMASK_WORDS);
}
#else
- bcopy(sc->event_mask, (uint8_t *)&evtreq->EventMasks, 16);
+ for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
+ evtreq->EventMasks[i] =
+ htole32(sc->event_mask[i]);
#endif
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_data = NULL;
@@ -1783,13 +1950,12 @@ mps_reregister_events(struct mps_softc *sc)
return (error);
}
-int
+void
mps_deregister_events(struct mps_softc *sc, struct mps_event_handle *handle)
{
TAILQ_REMOVE(&sc->event_list, handle, eh_list);
free(handle, M_MPT2);
- return (mps_update_events(sc, NULL, NULL));
}
/*
@@ -1819,10 +1985,16 @@ mps_add_chain(struct mps_command *cm)
TAILQ_INSERT_TAIL(&cm->cm_chain_list, chain, chain_link);
sgc = (MPI2_SGE_CHAIN32 *)&cm->cm_sge->MpiChain;
- sgc->Length = space;
+ sgc->Length = htole16(space);
sgc->NextChainOffset = 0;
+ /* TODO Looks like bug in Setting sgc->Flags.
+ * sgc->Flags = ( MPI2_SGE_FLAGS_CHAIN_ELEMENT | MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
+ * MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT
+ * This is fine.. because we are not using simple element. In case of
+ * MPI2_SGE_CHAIN32, we have seperate Length and Flags feild.
+ */
sgc->Flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT;
- sgc->Address = chain->chain_busaddr;
+ sgc->Address = htole32(chain->chain_busaddr);
cm->cm_sge = (MPI2_SGE_IO_UNION *)&chain->chain->MpiSimple;
cm->cm_sglsize = space;
@@ -1842,6 +2014,7 @@ mps_push_sge(struct mps_command *cm, void *sgep, size_t len, int segsleft)
MPI2_SGE_SIMPLE64 *sge = sgep;
int error, type;
uint32_t saved_buf_len, saved_address_low, saved_address_high;
+ u32 sge_flags;
type = (tc->Flags & MPI2_SGE_FLAGS_ELEMENT_MASK);
@@ -1910,6 +2083,11 @@ mps_push_sge(struct mps_command *cm, void *sgep, size_t len, int segsleft)
* understanding the code.
*/
cm->cm_sglsize -= len;
+ /* Endian Safe code */
+ sge_flags = sge->FlagsLength;
+ sge->FlagsLength = htole32(sge_flags);
+ sge->Address.High = htole32(sge->Address.High);
+ sge->Address.Low = htole32(sge->Address.Low);
bcopy(sgep, cm->cm_sge, len);
cm->cm_sge = (MPI2_SGE_IO_UNION *)((uintptr_t)cm->cm_sge + len);
return (mps_add_chain(cm));
@@ -1960,6 +2138,11 @@ mps_push_sge(struct mps_command *cm, void *sgep, size_t len, int segsleft)
MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
MPI2_SGE_FLAGS_SHIFT);
cm->cm_sglsize -= len;
+ /* Endian Safe code */
+ sge_flags = sge->FlagsLength;
+ sge->FlagsLength = htole32(sge_flags);
+ sge->Address.High = htole32(sge->Address.High);
+ sge->Address.Low = htole32(sge->Address.Low);
bcopy(sgep, cm->cm_sge, len);
cm->cm_sge = (MPI2_SGE_IO_UNION *)((uintptr_t)cm->cm_sge
+ len);
@@ -1985,6 +2168,11 @@ mps_push_sge(struct mps_command *cm, void *sgep, size_t len, int segsleft)
}
cm->cm_sglsize -= len;
+ /* Endian Safe code */
+ sge_flags = sge->FlagsLength;
+ sge->FlagsLength = htole32(sge_flags);
+ sge->Address.High = htole32(sge->Address.High);
+ sge->Address.Low = htole32(sge->Address.Low);
bcopy(sgep, cm->cm_sge, len);
cm->cm_sge = (MPI2_SGE_IO_UNION *)((uintptr_t)cm->cm_sge + len);
return (0);
@@ -2004,6 +2192,7 @@ mps_add_dmaseg(struct mps_command *cm, vm_paddr_t pa, size_t len, u_int flags,
*/
flags |= MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
MPI2_SGE_FLAGS_64_BIT_ADDRESSING;
+ /* Set Endian safe macro in mps_push_sge */
sge.FlagsLength = len | (flags << MPI2_SGE_FLAGS_SHIFT);
mps_from_u64(pa, &sge.Address);
@@ -2114,11 +2303,11 @@ mps_map_command(struct mps_softc *sc, struct mps_command *cm)
/* Add a zero-length element as needed */
if (cm->cm_sge != NULL) {
sge = (MPI2_SGE_SIMPLE32 *)cm->cm_sge;
- sge->FlagsLength = (MPI2_SGE_FLAGS_LAST_ELEMENT |
+ sge->FlagsLength = htole32((MPI2_SGE_FLAGS_LAST_ELEMENT |
MPI2_SGE_FLAGS_END_OF_BUFFER |
MPI2_SGE_FLAGS_END_OF_LIST |
MPI2_SGE_FLAGS_SIMPLE_ELEMENT) <<
- MPI2_SGE_FLAGS_SHIFT;
+ MPI2_SGE_FLAGS_SHIFT);
sge->Address = 0;
}
mps_enqueue_request(sc, cm);
@@ -2135,9 +2324,12 @@ mps_map_command(struct mps_softc *sc, struct mps_command *cm)
int
mps_wait_command(struct mps_softc *sc, struct mps_command *cm, int timeout)
{
- int error;
+ int error, rc;
mtx_assert(&sc->mps_mtx, MA_OWNED);
+
+ if(sc->mps_flags & MPS_FLAGS_DIAGRESET)
+ return EBUSY;
cm->cm_complete = NULL;
cm->cm_flags |= MPS_CM_FLAGS_WAKEUP;
@@ -2145,8 +2337,13 @@ mps_wait_command(struct mps_softc *sc, struct mps_command *cm, int timeout)
if ((error != 0) && (error != EINPROGRESS))
return (error);
error = msleep(cm, &sc->mps_mtx, 0, "mpswait", timeout*hz);
- if (error == EWOULDBLOCK)
+ if (error == EWOULDBLOCK) {
+ mps_dprint(sc, MPS_FAULT, "Calling Reinit from %s\n", __func__);
+ rc = mps_reinit(sc);
+ mps_dprint(sc, MPS_FAULT, "Reinit %s\n",
+ (rc == 0) ? "success" : "failed");
error = ETIMEDOUT;
+ }
return (error);
}
@@ -2157,7 +2354,7 @@ mps_wait_command(struct mps_softc *sc, struct mps_command *cm, int timeout)
int
mps_request_polled(struct mps_softc *sc, struct mps_command *cm)
{
- int error, timeout = 0;
+ int error, timeout = 0, rc;
error = 0;
@@ -2167,6 +2364,7 @@ mps_request_polled(struct mps_softc *sc, struct mps_command *cm)
while ((cm->cm_flags & MPS_CM_FLAGS_COMPLETE) == 0) {
mps_intr_locked(sc);
+
DELAY(50 * 1000);
if (timeout++ > 1000) {
mps_dprint(sc, MPS_FAULT, "polling failed\n");
@@ -2174,6 +2372,13 @@ mps_request_polled(struct mps_softc *sc, struct mps_command *cm)
break;
}
}
+
+ if (error) {
+ mps_dprint(sc, MPS_FAULT, "Calling Reinit from %s\n", __func__);
+ rc = mps_reinit(sc);
+ mps_dprint(sc, MPS_FAULT, "Reinit %s\n",
+ (rc == 0) ? "success" : "failed");
+ }
return (error);
}
diff --git a/sys/dev/mps/mps_config.c b/sys/dev/mps/mps_config.c
index da1f3fd288da..939872e8faa5 100644
--- a/sys/dev/mps/mps_config.c
+++ b/sys/dev/mps/mps_config.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -680,6 +680,7 @@ int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
request->Header.PageNumber = 0;
request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
+ /* We can remove below two lines ????*/
request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
request->PageAddress |= htole16(entry_idx);
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
diff --git a/sys/dev/mps/mps_ioctl.h b/sys/dev/mps/mps_ioctl.h
index cc2833722935..a52f80ed1b56 100644
--- a/sys/dev/mps/mps_ioctl.h
+++ b/sys/dev/mps/mps_ioctl.h
@@ -32,7 +32,7 @@
* $FreeBSD$
*/
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/mps/mps_mapping.c b/sys/dev/mps/mps_mapping.c
index e897dd3f2602..870535eb6d9a 100644
--- a/sys/dev/mps/mps_mapping.c
+++ b/sys/dev/mps/mps_mapping.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/mps/mps_mapping.h b/sys/dev/mps/mps_mapping.h
index 5e1877b0e30a..e188d8f38c9d 100644
--- a/sys/dev/mps/mps_mapping.h
+++ b/sys/dev/mps/mps_mapping.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c
index 01af9fb007cf..c0c55b249469 100644
--- a/sys/dev/mps/mps_sas.c
+++ b/sys/dev/mps/mps_sas.c
@@ -1,30 +1,6 @@
/*-
* Copyright (c) 2009 Yahoo! Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -488,16 +464,7 @@ mpssas_prepare_remove(struct mpssas_softc *sassc, uint16_t handle)
mps_dprint(sassc->sc, MPS_INFO, "%s\n", __func__);
- /*
- * If this is a WD controller, determine if the disk should be exposed
- * to the OS or not. If disk should be exposed, return from this
- * function without doing anything.
- */
sc = sassc->sc;
- if ((sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) && (sc->WD_hide_expose ==
- MPS_WD_EXPOSE_ALWAYS)) {
- return;
- }
targ = mpssas_find_target_by_handle(sassc, 0, handle);
if (targ == NULL) {
@@ -519,7 +486,7 @@ mpssas_prepare_remove(struct mpssas_softc *sassc, uint16_t handle)
req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req;
memset(req, 0, sizeof(*req));
- req->DevHandle = targ->handle;
+ req->DevHandle = htole16(targ->handle);
req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
@@ -570,15 +537,15 @@ mpssas_remove_device(struct mps_softc *sc, struct mps_command *tm)
return;
}
- if (reply->IOCStatus != MPI2_IOCSTATUS_SUCCESS) {
+ if (le16toh(reply->IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
mps_printf(sc, "IOCStatus = 0x%x while resetting device 0x%x\n",
- reply->IOCStatus, handle);
+ le16toh(reply->IOCStatus), handle);
mpssas_free_tm(sc, tm);
return;
}
mps_dprint(sc, MPS_INFO, "Reset aborted %u commands\n",
- reply->TerminationCount);
+ le32toh(reply->TerminationCount));
mps_free_reply(sc, tm->cm_reply_data);
tm->cm_reply = NULL; /* Ensures the the reply won't get re-freed */
@@ -587,7 +554,7 @@ mpssas_remove_device(struct mps_softc *sc, struct mps_command *tm)
memset(req, 0, sizeof(*req));
req->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
req->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
- req->DevHandle = handle;
+ req->DevHandle = htole16(handle);
tm->cm_data = NULL;
tm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
tm->cm_complete = mpssas_remove_complete;
@@ -613,6 +580,7 @@ mpssas_remove_complete(struct mps_softc *sc, struct mps_command *tm)
MPI2_SAS_IOUNIT_CONTROL_REPLY *reply;
uint16_t handle;
struct mpssas_target *targ;
+ struct mpssas_lun *lun;
mps_dprint(sc, MPS_INFO, "%s\n", __func__);
@@ -641,7 +609,7 @@ mpssas_remove_complete(struct mps_softc *sc, struct mps_command *tm)
}
mps_printf(sc, "%s on handle 0x%04x, IOCStatus= 0x%x\n", __func__,
- handle, reply->IOCStatus);
+ handle, le16toh(reply->IOCStatus));
/*
* Don't clear target if remove fails because things will get confusing.
@@ -649,7 +617,7 @@ mpssas_remove_complete(struct mps_softc *sc, struct mps_command *tm)
* this target id if possible, and so we can assign the same target id
* to this device if it comes back in the future.
*/
- if (reply->IOCStatus == MPI2_IOCSTATUS_SUCCESS) {
+ if (le16toh(reply->IOCStatus) == MPI2_IOCSTATUS_SUCCESS) {
targ = tm->cm_targ;
targ->handle = 0x0;
targ->encl_handle = 0x0;
@@ -659,7 +627,14 @@ mpssas_remove_complete(struct mps_softc *sc, struct mps_command *tm)
targ->linkrate = 0x0;
targ->devinfo = 0x0;
targ->flags = 0x0;
+
+ while(!SLIST_EMPTY(&targ->luns)) {
+ lun = SLIST_FIRST(&targ->luns);
+ SLIST_REMOVE_HEAD(&targ->luns, lun_link);
+ free(lun, M_MPT2);
+ }
}
+
mpssas_free_tm(sc, tm);
}
@@ -667,7 +642,7 @@ mpssas_remove_complete(struct mps_softc *sc, struct mps_command *tm)
static int
mpssas_register_events(struct mps_softc *sc)
{
- uint8_t events[16];
+ u32 events[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
bzero(events, 16);
setbit(events, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
@@ -701,8 +676,19 @@ mps_attach_sas(struct mps_softc *sc)
mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
sassc = malloc(sizeof(struct mpssas_softc), M_MPT2, M_WAITOK|M_ZERO);
+ if(!sassc) {
+ device_printf(sc->mps_dev, "Cannot allocate memory %s %d\n",
+ __func__, __LINE__);
+ return (ENOMEM);
+ }
sassc->targets = malloc(sizeof(struct mpssas_target) *
sc->facts->MaxTargets, M_MPT2, M_WAITOK|M_ZERO);
+ if(!sassc->targets) {
+ device_printf(sc->mps_dev, "Cannot allocate memory %s %d\n",
+ __func__, __LINE__);
+ free(sassc, M_MPT2);
+ return (ENOMEM);
+ }
sc->sassc = sassc;
sassc->sc = sc;
@@ -790,6 +776,9 @@ int
mps_detach_sas(struct mps_softc *sc)
{
struct mpssas_softc *sassc;
+ struct mpssas_lun *lun, *lun_tmp;
+ struct mpssas_target *targ;
+ int i;
mps_dprint(sc, MPS_INFO, "%s\n", __func__);
@@ -838,6 +827,12 @@ mps_detach_sas(struct mps_softc *sc)
if (sassc->devq != NULL)
cam_simq_free(sassc->devq);
+ for(i=0; i< sc->facts->MaxTargets ;i++) {
+ targ = &sassc->targets[i];
+ SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, lun_tmp) {
+ free(lun, M_MPT2);
+ }
+ }
free(sassc->targets, M_MPT2);
free(sassc, M_MPT2);
sc->sassc = NULL;
@@ -919,7 +914,7 @@ mpssas_action(struct cam_sim *sim, union ccb *ccb)
cpi->hba_misc = PIM_NOBUSRESET;
cpi->hba_eng_cnt = 0;
cpi->max_target = sassc->sc->facts->MaxTargets - 1;
- cpi->max_lun = 8;
+ cpi->max_lun = 255;
cpi->initiator_id = 255;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "LSILogic", HBA_IDLEN);
@@ -953,7 +948,7 @@ mpssas_action(struct cam_sim *sim, union ccb *ccb)
targ = &sassc->targets[cts->ccb_h.target_id];
if (targ->handle == 0x0) {
- cts->ccb_h.status = CAM_TID_INVALID;
+ cts->ccb_h.status = CAM_SEL_TIMEOUT;
break;
}
@@ -1185,8 +1180,8 @@ mpssas_logical_unit_reset_complete(struct mps_softc *sc, struct mps_command *tm)
mpssas_log_command(tm,
"logical unit reset status 0x%x code 0x%x count %u\n",
- reply->IOCStatus, reply->ResponseCode,
- reply->TerminationCount);
+ le16toh(reply->IOCStatus), le32toh(reply->ResponseCode),
+ le32toh(reply->TerminationCount));
/* See if there are any outstanding commands for this LUN.
* This could be made more efficient by using a per-LU data
@@ -1273,8 +1268,8 @@ mpssas_target_reset_complete(struct mps_softc *sc, struct mps_command *tm)
mpssas_log_command(tm,
"target reset status 0x%x code 0x%x count %u\n",
- reply->IOCStatus, reply->ResponseCode,
- reply->TerminationCount);
+ le16toh(reply->IOCStatus), le32toh(reply->ResponseCode),
+ le32toh(reply->TerminationCount));
targ->flags &= ~MPSSAS_TARGET_INRESET;
@@ -1320,7 +1315,7 @@ mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type)
}
req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req;
- req->DevHandle = target->handle;
+ req->DevHandle = htole16(target->handle);
req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
req->TaskType = type;
@@ -1383,7 +1378,7 @@ mpssas_abort_complete(struct mps_softc *sc, struct mps_command *tm)
if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) {
mpssas_log_command(tm,
"cm_flags = %#x for abort %p TaskMID %u!\n",
- tm->cm_flags, tm, req->TaskMID);
+ tm->cm_flags, tm, le16toh(req->TaskMID));
mpssas_free_tm(sc, tm);
return;
}
@@ -1391,7 +1386,7 @@ mpssas_abort_complete(struct mps_softc *sc, struct mps_command *tm)
if (reply == NULL) {
mpssas_log_command(tm,
"NULL abort reply for tm %p TaskMID %u\n",
- tm, req->TaskMID);
+ tm, le16toh(req->TaskMID));
if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) {
/* this completion was due to a reset, just cleanup */
targ->tm = NULL;
@@ -1406,9 +1401,9 @@ mpssas_abort_complete(struct mps_softc *sc, struct mps_command *tm)
mpssas_log_command(tm,
"abort TaskMID %u status 0x%x code 0x%x count %u\n",
- req->TaskMID,
- reply->IOCStatus, reply->ResponseCode,
- reply->TerminationCount);
+ le16toh(req->TaskMID),
+ le16toh(reply->IOCStatus), le32toh(reply->ResponseCode),
+ le32toh(reply->TerminationCount));
cm = TAILQ_FIRST(&tm->cm_targ->timedout_commands);
if (cm == NULL) {
@@ -1417,16 +1412,16 @@ mpssas_abort_complete(struct mps_softc *sc, struct mps_command *tm)
*/
mpssas_log_command(tm,
"finished recovery after aborting TaskMID %u\n",
- req->TaskMID);
+ le16toh(req->TaskMID));
targ->tm = NULL;
mpssas_free_tm(sc, tm);
}
- else if (req->TaskMID != cm->cm_desc.Default.SMID) {
+ else if (le16toh(req->TaskMID) != cm->cm_desc.Default.SMID) {
/* abort success, but we have more timedout commands to abort */
mpssas_log_command(tm,
"continuing recovery after aborting TaskMID %u\n",
- req->TaskMID);
+ le16toh(req->TaskMID));
mpssas_send_abort(sc, tm, cm);
}
@@ -1436,7 +1431,7 @@ mpssas_abort_complete(struct mps_softc *sc, struct mps_command *tm)
*/
mpssas_log_command(tm,
"abort failed for TaskMID %u tm %p\n",
- req->TaskMID, tm);
+ le16toh(req->TaskMID), tm);
mpssas_send_reset(sc, tm,
MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET);
@@ -1460,14 +1455,14 @@ mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_comma
}
req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req;
- req->DevHandle = targ->handle;
+ req->DevHandle = htole16(targ->handle);
req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
/* XXX Need to handle invalid LUNs */
MPS_SET_LUN(req->LUN, cm->cm_ccb->ccb_h.target_lun);
- req->TaskMID = cm->cm_desc.Default.SMID;
+ req->TaskMID = htole16(cm->cm_desc.Default.SMID);
tm->cm_data = NULL;
tm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
@@ -1575,6 +1570,7 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
struct mps_command *cm;
uint8_t i, lba_byte, *ref_tag_addr;
uint16_t eedp_flags;
+ uint32_t mpi_control;
sc = sassc->sc;
mtx_assert(&sc->mps_mtx, MA_OWNED);
@@ -1585,7 +1581,7 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
if (targ->handle == 0x0) {
mps_dprint(sc, MPS_TRACE, "%s NULL handle for target %u\n",
__func__, csio->ccb_h.target_id);
- csio->ccb_h.status = CAM_TID_INVALID;
+ csio->ccb_h.status = CAM_SEL_TIMEOUT;
xpt_done(ccb);
return;
}
@@ -1631,10 +1627,10 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
req = (MPI2_SCSI_IO_REQUEST *)cm->cm_req;
bzero(req, sizeof(*req));
- req->DevHandle = targ->handle;
+ req->DevHandle = htole16(targ->handle);
req->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
req->MsgFlags = 0;
- req->SenseBufferLowAddress = cm->cm_sense_busaddr;
+ req->SenseBufferLowAddress = htole32(cm->cm_sense_busaddr);
req->SenseBufferLength = MPS_SENSE_LEN;
req->SGLFlags = 0;
req->ChainOffset = 0;
@@ -1643,27 +1639,29 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
req->SGLOffset2= 0;
req->SGLOffset3= 0;
req->SkipCount = 0;
- req->DataLength = csio->dxfer_len;
+ req->DataLength = htole32(csio->dxfer_len);
req->BidirectionalDataLength = 0;
- req->IoFlags = csio->cdb_len;
+ req->IoFlags = htole16(csio->cdb_len);
req->EEDPFlags = 0;
/* Note: BiDirectional transfers are not supported */
switch (csio->ccb_h.flags & CAM_DIR_MASK) {
case CAM_DIR_IN:
- req->Control = MPI2_SCSIIO_CONTROL_READ;
+ mpi_control = MPI2_SCSIIO_CONTROL_READ;
cm->cm_flags |= MPS_CM_FLAGS_DATAIN;
break;
case CAM_DIR_OUT:
- req->Control = MPI2_SCSIIO_CONTROL_WRITE;
+ mpi_control = MPI2_SCSIIO_CONTROL_WRITE;
cm->cm_flags |= MPS_CM_FLAGS_DATAOUT;
break;
case CAM_DIR_NONE:
default:
- req->Control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
+ mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
break;
}
-
+
+ if (csio->cdb_len == 32)
+ mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT;
/*
* It looks like the hardware doesn't require an explicit tag
* number for each transaction. SAM Task Management not supported
@@ -1671,22 +1669,22 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
*/
switch (csio->tag_action) {
case MSG_HEAD_OF_Q_TAG:
- req->Control |= MPI2_SCSIIO_CONTROL_HEADOFQ;
+ mpi_control |= MPI2_SCSIIO_CONTROL_HEADOFQ;
break;
case MSG_ORDERED_Q_TAG:
- req->Control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
+ mpi_control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
break;
case MSG_ACA_TASK:
- req->Control |= MPI2_SCSIIO_CONTROL_ACAQ;
+ mpi_control |= MPI2_SCSIIO_CONTROL_ACAQ;
break;
case CAM_TAG_ACTION_NONE:
case MSG_SIMPLE_Q_TAG:
default:
- req->Control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
+ mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
break;
}
- req->Control |= sc->mapping_table[csio->ccb_h.target_id].TLR_bits;
-
+ mpi_control |= sc->mapping_table[csio->ccb_h.target_id].TLR_bits;
+ req->Control = htole32(mpi_control);
if (MPS_SET_LUN(req->LUN, csio->ccb_h.target_lun) != 0) {
mps_free_command(sc, cm);
ccb->ccb_h.status = CAM_LUN_INVALID;
@@ -1698,7 +1696,7 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
bcopy(csio->cdb_io.cdb_ptr, &req->CDB.CDB32[0], csio->cdb_len);
else
bcopy(csio->cdb_io.cdb_bytes, &req->CDB.CDB32[0],csio->cdb_len);
- req->IoFlags = csio->cdb_len;
+ req->IoFlags = htole16(csio->cdb_len);
/*
* Check if EEDP is supported and enabled. If it is then check if the
@@ -1715,11 +1713,11 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
}
if ((lun != NULL) && (lun->eedp_formatted)) {
- req->EEDPBlockSize = lun->eedp_block_size;
+ req->EEDPBlockSize = htole16(lun->eedp_block_size);
eedp_flags |= (MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD);
- req->EEDPFlags = eedp_flags;
+ req->EEDPFlags = htole16(eedp_flags);
/*
* If CDB less than 32, fill in Primary Ref Tag with
@@ -1738,6 +1736,8 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
req->CDB.CDB32[lba_byte + i];
ref_tag_addr++;
}
+ req->CDB.EEDP32.PrimaryReferenceTag =
+ htole32(req->CDB.EEDP32.PrimaryReferenceTag);
req->CDB.EEDP32.PrimaryApplicationTagMask =
0xFFFF;
req->CDB.CDB32[1] = (req->CDB.CDB32[1] & 0x1F) |
@@ -1745,7 +1745,7 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
} else {
eedp_flags |=
MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG;
- req->EEDPFlags = eedp_flags;
+ req->EEDPFlags = htole16(eedp_flags);
req->CDB.CDB32[10] = (req->CDB.CDB32[10] &
0x1F) | 0x20;
}
@@ -1757,7 +1757,7 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
cm->cm_sge = &req->SGL;
cm->cm_sglsize = (32 - 24) * 4;
cm->cm_desc.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
- cm->cm_desc.SCSIIO.DevHandle = targ->handle;
+ cm->cm_desc.SCSIIO.DevHandle = htole16(targ->handle);
cm->cm_complete = mpssas_scsiio_complete;
cm->cm_complete_data = ccb;
cm->cm_targ = targ;
@@ -2033,8 +2033,8 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
"completed timedout cm %p ccb %p during recovery "
"ioc %x scsi %x state %x xfer %u\n",
cm, cm->cm_ccb,
- rep->IOCStatus, rep->SCSIStatus, rep->SCSIState,
- rep->TransferCount);
+ le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState,
+ le32toh(rep->TransferCount));
else
mpssas_log_command(cm,
"completed timedout cm %p ccb %p during recovery\n",
@@ -2045,8 +2045,8 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
"completed cm %p ccb %p during recovery "
"ioc %x scsi %x state %x xfer %u\n",
cm, cm->cm_ccb,
- rep->IOCStatus, rep->SCSIStatus, rep->SCSIState,
- rep->TransferCount);
+ le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState,
+ le32toh(rep->TransferCount));
else
mpssas_log_command(cm,
"completed cm %p ccb %p during recovery\n",
@@ -2126,8 +2126,8 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
if (sc->mps_debug & MPS_TRACE)
mpssas_log_command(cm,
"ioc %x scsi %x state %x xfer %u\n",
- rep->IOCStatus, rep->SCSIStatus,
- rep->SCSIState, rep->TransferCount);
+ le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState,
+ le32toh(rep->TransferCount));
/*
* If this is a Direct Drive I/O, reissue the I/O to the original IR
@@ -2142,14 +2142,14 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
return;
}
- switch (rep->IOCStatus & MPI2_IOCSTATUS_MASK) {
+ switch (le16toh(rep->IOCStatus) & MPI2_IOCSTATUS_MASK) {
case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
- csio->resid = cm->cm_length - rep->TransferCount;
+ csio->resid = cm->cm_length - le32toh(rep->TransferCount);
/* FALLTHROUGH */
case MPI2_IOCSTATUS_SUCCESS:
case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
- if ((rep->IOCStatus & MPI2_IOCSTATUS_MASK) ==
+ if ((le16toh(rep->IOCStatus) & MPI2_IOCSTATUS_MASK) ==
MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR)
mpssas_log_command(cm, "recovered error\n");
@@ -2175,7 +2175,7 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
* TLR_bits for the target.
*/
if ((rep->SCSIState & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) &&
- ((rep->ResponseInfo & MPI2_SCSI_RI_MASK_REASONCODE) ==
+ ((le32toh(rep->ResponseInfo) & MPI2_SCSI_RI_MASK_REASONCODE) ==
MPS_SCSI_RI_INVALID_FRAME)) {
sc->mapping_table[csio->ccb_h.target_id].TLR_bits =
(u8)MPI2_SCSIIO_CONTROL_NO_TLR;
@@ -2203,7 +2203,7 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
int sense_len, returned_sense_len;
- returned_sense_len = min(rep->SenseCount,
+ returned_sense_len = min(le32toh(rep->SenseCount),
sizeof(struct scsi_sense_data));
if (returned_sense_len < ccb->csio.sense_len)
ccb->csio.sense_resid = ccb->csio.sense_len -
@@ -2297,8 +2297,8 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
ccb->ccb_h.status = CAM_REQUEUE_REQ;
mpssas_log_command(cm,
"terminated ioc %x scsi %x state %x xfer %u\n",
- rep->IOCStatus, rep->SCSIStatus, rep->SCSIState,
- rep->TransferCount);
+ le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState,
+ le32toh(rep->TransferCount));
break;
case MPI2_IOCSTATUS_INVALID_FUNCTION:
case MPI2_IOCSTATUS_INTERNAL_ERROR:
@@ -2313,8 +2313,8 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
default:
mpssas_log_command(cm,
"completed ioc %x scsi %x state %x xfer %u\n",
- rep->IOCStatus, rep->SCSIStatus, rep->SCSIState,
- rep->TransferCount);
+ le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState,
+ le32toh(rep->TransferCount));
csio->resid = cm->cm_length;
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
break;
@@ -2338,6 +2338,7 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
xpt_done(ccb);
}
+/* All Request reached here are Endian safe */
static void
mpssas_direct_drive_io(struct mpssas_softc *sassc, struct mps_command *cm,
union ccb *ccb) {
@@ -2396,7 +2397,8 @@ mpssas_direct_drive_io(struct mpssas_softc *sassc, struct mps_command *cm,
stripe_unit = physLBA / sc->DD_num_phys_disks;
column = physLBA % sc->DD_num_phys_disks;
pIO_req->DevHandle =
- sc->DD_column_map[column].dev_handle;
+ htole16(sc->DD_column_map[column].dev_handle);
+ /* ???? Is this endian safe*/
cm->cm_desc.SCSIIO.DevHandle =
pIO_req->DevHandle;
@@ -2423,17 +2425,21 @@ mpssas_direct_drive_io(struct mpssas_softc *sassc, struct mps_command *cm,
}
/*
- * Handle 10 or 16 byte CDBs.
+ * Handle 10, 12 or 16 byte CDBs.
*/
if ((pIO_req->DevHandle == sc->DD_dev_handle) && ((CDB[0] == READ_10) ||
(CDB[0] == WRITE_10) || (CDB[0] == READ_16) ||
- (CDB[0] == WRITE_16))) {
+ (CDB[0] == WRITE_16) || (CDB[0] == READ_12) ||
+ (CDB[0] == WRITE_12))) {
/*
* For 16-byte CDB's, verify that the upper 4 bytes of the CDB
* are 0. If not, this is accessing beyond 2TB so handle it in
- * the else section. 10-byte CDB's are OK.
+ * the else section. 10-byte and 12-byte CDB's are OK.
+ * FreeBSD sends very rare 12 byte READ/WRITE, but driver is
+ * ready to accept 12byte CDB for Direct IOs.
*/
- if ((CDB[0] < READ_16) ||
+ if ((CDB[0] == READ_10 || CDB[0] == WRITE_10) ||
+ (CDB[0] == READ_12 || CDB[0] == WRITE_12) ||
!(CDB[2] | CDB[3] | CDB[4] | CDB[5])) {
/*
* Get the transfer size in blocks.
@@ -2444,7 +2450,10 @@ mpssas_direct_drive_io(struct mpssas_softc *sassc, struct mps_command *cm,
* Get virtual LBA. Point to correct lower 4 bytes of
* LBA in the CDB depending on command.
*/
- lba_idx = (CDB[0] < READ_16) ? 2 : 6;
+ lba_idx = ((CDB[0] == READ_12) ||
+ (CDB[0] == WRITE_12) ||
+ (CDB[0] == READ_10) ||
+ (CDB[0] == WRITE_10))? 2 : 6;
virtLBA = ((uint64_t)CDB[lba_idx] << 24) |
((uint64_t)CDB[lba_idx + 1] << 16) |
((uint64_t)CDB[lba_idx + 2] << 8) |
@@ -2477,8 +2486,8 @@ mpssas_direct_drive_io(struct mpssas_softc *sassc, struct mps_command *cm,
column = physLBA %
sc->DD_num_phys_disks;
pIO_req->DevHandle =
- sc->DD_column_map[column].
- dev_handle;
+ htole16(sc->DD_column_map[column].
+ dev_handle);
cm->cm_desc.SCSIIO.DevHandle =
pIO_req->DevHandle;
@@ -2555,8 +2564,8 @@ mpssas_direct_drive_io(struct mpssas_softc *sassc, struct mps_command *cm,
column = physLBA %
sc->DD_num_phys_disks;
pIO_req->DevHandle =
- sc->DD_column_map[column].
- dev_handle;
+ htole16(sc->DD_column_map[column].
+ dev_handle);
cm->cm_desc.SCSIIO.DevHandle =
pIO_req->DevHandle;
@@ -2633,10 +2642,10 @@ mpssas_smpio_complete(struct mps_softc *sc, struct mps_command *cm)
sasaddr = le32toh(req->SASAddress.Low);
sasaddr |= ((uint64_t)(le32toh(req->SASAddress.High))) << 32;
- if ((rpl->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS ||
+ if ((le16toh(rpl->IOCStatus) & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS ||
rpl->SASStatus != MPI2_SASSTATUS_SUCCESS) {
mps_dprint(sc, MPS_INFO, "%s: IOCStatus %04x SASStatus %02x\n",
- __func__, rpl->IOCStatus, rpl->SASStatus);
+ __func__, le16toh(rpl->IOCStatus), rpl->SASStatus);
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
goto bailout;
}
@@ -2749,7 +2758,7 @@ mpssas_send_smpcmd(struct mpssas_softc *sassc, union ccb *ccb, uint64_t sasaddr)
/* Allow the chip to use any route to this SAS address. */
req->PhysicalPort = 0xff;
- req->RequestDataLength = ccb->smpio.smp_request_len;
+ req->RequestDataLength = htole16(ccb->smpio.smp_request_len);
req->SGLFlags =
MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE | MPI2_SGLFLAGS_SGL_TYPE_MPI;
@@ -2774,7 +2783,7 @@ mpssas_send_smpcmd(struct mpssas_softc *sassc, union ccb *ccb, uint64_t sasaddr)
cm->cm_uio.uio_rw = UIO_WRITE;
cm->cm_iovec[0].iov_base = request;
- cm->cm_iovec[0].iov_len = req->RequestDataLength;
+ cm->cm_iovec[0].iov_len = le16toh(req->RequestDataLength);
cm->cm_iovec[1].iov_base = response;
cm->cm_iovec[1].iov_len = ccb->smpio.smp_response_len;
@@ -2980,7 +2989,7 @@ mpssas_action_resetdev(struct mpssas_softc *sassc, union ccb *ccb)
targ = &sassc->targets[ccb->ccb_h.target_id];
req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req;
- req->DevHandle = targ->handle;
+ req->DevHandle = htole16(targ->handle);
req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
@@ -3024,9 +3033,9 @@ mpssas_resetdev_complete(struct mps_softc *sc, struct mps_command *tm)
}
printf("%s: IOCStatus = 0x%x ResponseCode = 0x%x\n", __func__,
- resp->IOCStatus, resp->ResponseCode);
+ le16toh(resp->IOCStatus), le32toh(resp->ResponseCode));
- if (resp->ResponseCode == MPI2_SCSITASKMGMT_RSP_TM_COMPLETE) {
+ if (le32toh(resp->ResponseCode) == MPI2_SCSITASKMGMT_RSP_TM_COMPLETE) {
ccb->ccb_h.status = CAM_REQ_CMP;
mpssas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid,
CAM_LUN_WILDCARD);
@@ -3131,6 +3140,17 @@ next_work:
mps_kproc_exit(0);
}
+/*
+ * This function will send READ_CAP_16 to find out EEDP protection mode.
+ * It will check inquiry data before sending READ_CAP_16.
+ * Callback for READ_CAP_16 is "mpssas_read_cap_done".
+ * This is insternal scsi command and we need to take care release of devq, if
+ * CAM_DEV_QFRZN is set. Driver needs to release devq if it has frozen any.
+ * xpt_release_devq is called from mpssas_read_cap_done.
+ *
+ * All other commands will be handled by periph layer and there it will
+ * check for "CAM_DEV_QFRZN" and release of devq will be done.
+ */
static void
mpssas_rescan(struct mpssas_softc *sassc, union ccb *ccb)
{
@@ -3264,6 +3284,8 @@ mpssas_check_eedp(struct mpssas_softc *sassc)
struct mpssas_target *target;
struct mpssas_lun *lun;
uint8_t found_lun;
+ struct ccb_getdev cgd;
+ char path_str[64];
/*
* Issue a READ CAPACITY 16 command to each LUN of each target. This
@@ -3277,19 +3299,10 @@ mpssas_check_eedp(struct mpssas_softc *sassc)
lunid = 0;
do {
- rcap_buf =
- malloc(sizeof(struct scsi_read_capacity_eedp),
- M_MPT2, M_NOWAIT | M_ZERO);
- if (rcap_buf == NULL) {
- mps_dprint(sc, MPS_FAULT, "Unable to alloc read "
- "capacity buffer for EEDP support.\n");
- return;
- }
ccb = xpt_alloc_ccb_nowait();
if (ccb == NULL) {
mps_dprint(sc, MPS_FAULT, "Unable to alloc CCB "
"for EEDP support.\n");
- free(rcap_buf, M_MPT2);
return;
}
@@ -3297,7 +3310,6 @@ mpssas_check_eedp(struct mpssas_softc *sassc)
pathid, targetid, lunid) != CAM_REQ_CMP) {
mps_dprint(sc, MPS_FAULT, "Unable to create "
"path for EEDP support\n");
- free(rcap_buf, M_MPT2);
xpt_free_ccb(ccb);
return;
}
@@ -3326,7 +3338,6 @@ mpssas_check_eedp(struct mpssas_softc *sassc)
mps_dprint(sc, MPS_FAULT,
"Unable to alloc LUN for "
"EEDP support.\n");
- free(rcap_buf, M_MPT2);
xpt_free_path(ccb->ccb_h.path);
xpt_free_ccb(ccb);
return;
@@ -3336,12 +3347,51 @@ mpssas_check_eedp(struct mpssas_softc *sassc)
lun_link);
}
lunid++;
+ /* Before Issuing READ CAPACITY 16,
+ * check Device type.
+ */
+ xpt_setup_ccb(&cgd.ccb_h, ccb->ccb_h.path,
+ CAM_PRIORITY_NORMAL);
+ cgd.ccb_h.func_code = XPT_GDEV_TYPE;
+ xpt_action((union ccb *)&cgd);
/*
+ * If this flag is set in the inquiry data,
+ * the device supports protection information,
+ * and must support the 16 byte read
+ * capacity command, otherwise continue without
+ * sending read cap 16
+ */
+
+ xpt_path_string(ccb->ccb_h.path, path_str,
+ sizeof(path_str));
+
+ if ((cgd.inq_data.spc3_flags &
+ SPC3_SID_PROTECT) == 0) {
+ xpt_free_path(ccb->ccb_h.path);
+ xpt_free_ccb(ccb);
+ continue;
+ }
+
+ mps_dprint(sc, MPS_INFO,
+ "Sending read cap: path %s"
+ " handle %d\n", path_str, target->handle );
+
+ /*
* Issue a READ CAPACITY 16 command for the LUN.
* The mpssas_read_cap_done function will load
* the read cap info into the LUN struct.
*/
+ rcap_buf =
+ malloc(sizeof(struct scsi_read_capacity_eedp),
+ M_MPT2, M_NOWAIT| M_ZERO);
+ if (rcap_buf == NULL) {
+ mps_dprint(sc, MPS_FAULT, "Unable to alloc read "
+ "capacity buffer for EEDP support.\n");
+ xpt_free_path(ccb->ccb_h.path);
+ xpt_free_ccb(ccb);
+ return;
+ }
csio = &ccb->csio;
csio->ccb_h.func_code = XPT_SCSI_IO;
csio->ccb_h.flags = CAM_DIR_IN;
@@ -3377,7 +3427,6 @@ mpssas_check_eedp(struct mpssas_softc *sassc)
ccb->ccb_h.ppriv_ptr1 = sassc;
xpt_action(ccb);
} else {
- free(rcap_buf, M_MPT2);
xpt_free_path(ccb->ccb_h.path);
xpt_free_ccb(ccb);
}
@@ -3499,8 +3548,6 @@ mpssas_portenable_complete(struct mps_softc *sc, struct mps_command *cm)
{
MPI2_PORT_ENABLE_REPLY *reply;
struct mpssas_softc *sassc;
- struct mpssas_target *target;
- int i;
mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
sassc = sc->sassc;
@@ -3518,7 +3565,7 @@ mpssas_portenable_complete(struct mps_softc *sc, struct mps_command *cm)
reply = (MPI2_PORT_ENABLE_REPLY *)cm->cm_reply;
if (reply == NULL)
mps_dprint(sc, MPS_FAULT, "Portenable NULL reply\n");
- else if ((reply->IOCStatus & MPI2_IOCSTATUS_MASK) !=
+ else if (le16toh(reply->IOCStatus & MPI2_IOCSTATUS_MASK) !=
MPI2_IOCSTATUS_SUCCESS)
mps_dprint(sc, MPS_FAULT, "Portenable failed\n");
@@ -3537,23 +3584,6 @@ mpssas_portenable_complete(struct mps_softc *sc, struct mps_command *cm)
* some info and a volume's will be 0. Use that to remove disks.
*/
mps_wd_config_pages(sc);
- if (((sc->mps_flags & MPS_FLAGS_WD_AVAILABLE)
- && (sc->WD_hide_expose == MPS_WD_HIDE_ALWAYS))
- || (sc->WD_valid_config && (sc->WD_hide_expose ==
- MPS_WD_HIDE_IF_VOLUME))) {
- for (i = 0; i < sassc->sc->facts->MaxTargets; i++) {
- target = &sassc->targets[i];
- if (target->devinfo) {
- target->devinfo = 0x0;
- target->encl_handle = 0x0;
- target->encl_slot = 0x0;
- target->handle = 0x0;
- target->tid = 0x0;
- target->linkrate = 0x0;
- target->flags = 0x0;
- }
- }
- }
/*
* Done waiting for port enable to complete. Decrement the refcount.
@@ -3564,6 +3594,7 @@ mpssas_portenable_complete(struct mps_softc *sc, struct mps_command *cm)
*/
sc->wait_for_port_enable = 0;
sc->port_enable_complete = 1;
+ wakeup(&sc->port_enable_complete);
mpssas_startup_decrement(sassc);
xpt_release_simq(sassc->sim, 1);
}
diff --git a/sys/dev/mps/mps_sas.h b/sys/dev/mps/mps_sas.h
index 6653cc365e48..6857b98f06d4 100644
--- a/sys/dev/mps/mps_sas.h
+++ b/sys/dev/mps/mps_sas.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/mps/mps_sas_lsi.c b/sys/dev/mps/mps_sas_lsi.c
index 41814056fccb..9cedcd3d938c 100644
--- a/sys/dev/mps/mps_sas_lsi.c
+++ b/sys/dev/mps/mps_sas_lsi.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -210,17 +210,17 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
switch (phy->PhyStatus & MPI2_EVENT_SAS_TOPO_RC_MASK) {
case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
if (mpssas_add_device(sc,
- phy->AttachedDevHandle, phy->LinkRate)){
+ le16toh(phy->AttachedDevHandle), phy->LinkRate)){
printf("%s: failed to add device with "
"handle 0x%x\n", __func__,
- phy->AttachedDevHandle);
- mpssas_prepare_remove(sassc, phy->
- AttachedDevHandle);
+ le16toh(phy->AttachedDevHandle));
+ mpssas_prepare_remove(sassc, le16toh(
+ phy->AttachedDevHandle));
}
break;
case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
- mpssas_prepare_remove(sassc, phy->
- AttachedDevHandle);
+ mpssas_prepare_remove(sassc,le16toh(
+ phy->AttachedDevHandle));
break;
case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
@@ -304,7 +304,7 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
printf("%s: could not get ID "
"for volume with handle "
"0x%04x\n", __func__,
- element->VolDevHandle);
+ le16toh(element->VolDevHandle));
break;
}
@@ -329,8 +329,17 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
targ = mpssas_find_target_by_handle(sassc, 0, element->PhysDiskDevHandle);
if (targ == NULL)
break;
-
- targ->flags |= MPS_TARGET_FLAGS_RAID_COMPONENT;
+
+ /* Set raid component flags only if it is not WD.
+ * OR WrapDrive with WD_HIDE_ALWAYS/WD_HIDE_IF_VOLUME is set in NVRAM
+ */
+ if((!sc->WD_available) ||
+ ((sc->WD_available &&
+ (sc->WD_hide_expose == MPS_WD_HIDE_ALWAYS)) ||
+ (sc->WD_valid_config && (sc->WD_hide_expose ==
+ MPS_WD_HIDE_IF_VOLUME)))) {
+ targ->flags |= MPS_TARGET_FLAGS_RAID_COMPONENT;
+ }
mpssas_rescan_target(sc, targ);
break;
@@ -340,12 +349,12 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
* Expose it to the OS.
*/
if (mpssas_add_device(sc,
- element->PhysDiskDevHandle, 0)){
+ le16toh(element->PhysDiskDevHandle), 0)){
printf("%s: failed to add device with "
"handle 0x%x\n", __func__,
- element->PhysDiskDevHandle);
- mpssas_prepare_remove(sassc, element->
- PhysDiskDevHandle);
+ le16toh(element->PhysDiskDevHandle));
+ mpssas_prepare_remove(sassc, le16toh(element->
+ PhysDiskDevHandle));
}
break;
}
@@ -368,25 +377,25 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
mps_dprint(sc, MPS_INFO, "Received IR Volume event:\n");
switch (event_data->ReasonCode) {
case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED:
- mps_dprint(sc, MPS_INFO, " Volume Settings "
- "changed from 0x%x to 0x%x for Volome with "
- "handle 0x%x", event_data->PreviousValue,
- event_data->NewValue,
- event_data->VolDevHandle);
+ mps_dprint(sc, MPS_INFO, " Volume Settings "
+ "changed from 0x%x to 0x%x for Volome with "
+ "handle 0x%x", le32toh(event_data->PreviousValue),
+ le32toh(event_data->NewValue),
+ le16toh(event_data->VolDevHandle));
break;
case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED:
- mps_dprint(sc, MPS_INFO, " Volume Status "
- "changed from 0x%x to 0x%x for Volome with "
- "handle 0x%x", event_data->PreviousValue,
- event_data->NewValue,
- event_data->VolDevHandle);
+ mps_dprint(sc, MPS_INFO, " Volume Status "
+ "changed from 0x%x to 0x%x for Volome with "
+ "handle 0x%x", le32toh(event_data->PreviousValue),
+ le32toh(event_data->NewValue),
+ le16toh(event_data->VolDevHandle));
break;
case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED:
- mps_dprint(sc, MPS_INFO, " Volume State "
- "changed from 0x%x to 0x%x for Volome with "
- "handle 0x%x", event_data->PreviousValue,
- event_data->NewValue,
- event_data->VolDevHandle);
+ mps_dprint(sc, MPS_INFO, " Volume State "
+ "changed from 0x%x to 0x%x for Volome with "
+ "handle 0x%x", le32toh(event_data->PreviousValue),
+ le32toh(event_data->NewValue),
+ le16toh(event_data->VolDevHandle));
u32 state;
struct mpssas_target *targ;
state = le32toh(event_data->NewValue);
@@ -434,31 +443,32 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
mps_dprint(sc, MPS_INFO, "Received IR Phys Disk event:\n");
switch (event_data->ReasonCode) {
case MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED:
- mps_dprint(sc, MPS_INFO, " Phys Disk Settings "
- "changed from 0x%x to 0x%x for Phys Disk Number "
- "%d and handle 0x%x at Enclosure handle 0x%x, Slot "
- "%d\n", event_data->PreviousValue,
- event_data->NewValue, event_data->PhysDiskNum,
- event_data->PhysDiskDevHandle,
- event_data->EnclosureHandle, event_data->Slot);
+ mps_dprint(sc, MPS_INFO, " Phys Disk Settings "
+ "changed from 0x%x to 0x%x for Phys Disk Number "
+ "%d and handle 0x%x at Enclosure handle 0x%x, Slot "
+ "%d", le32toh(event_data->PreviousValue),
+ le32toh(event_data->NewValue),
+ event_data->PhysDiskNum,
+ le16toh(event_data->PhysDiskDevHandle),
+ le16toh(event_data->EnclosureHandle), le16toh(event_data->Slot));
break;
case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED:
- mps_dprint(sc, MPS_INFO, " Phys Disk Status changed "
- "from 0x%x to 0x%x for Phys Disk Number %d and "
- "handle 0x%x at Enclosure handle 0x%x, Slot %d\n",
- event_data->PreviousValue, event_data->NewValue,
- event_data->PhysDiskNum,
- event_data->PhysDiskDevHandle,
- event_data->EnclosureHandle, event_data->Slot);
+ mps_dprint(sc, MPS_INFO, " Phys Disk Status changed "
+ "from 0x%x to 0x%x for Phys Disk Number %d and "
+ "handle 0x%x at Enclosure handle 0x%x, Slot %d",
+ le32toh(event_data->PreviousValue),
+ le32toh(event_data->NewValue), event_data->PhysDiskNum,
+ le16toh(event_data->PhysDiskDevHandle),
+ le16toh(event_data->EnclosureHandle), le16toh(event_data->Slot));
break;
case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED:
- mps_dprint(sc, MPS_INFO, " Phys Disk State changed "
- "from 0x%x to 0x%x for Phys Disk Number %d and "
- "handle 0x%x at Enclosure handle 0x%x, Slot %d\n",
- event_data->PreviousValue, event_data->NewValue,
- event_data->PhysDiskNum,
- event_data->PhysDiskDevHandle,
- event_data->EnclosureHandle, event_data->Slot);
+ mps_dprint(sc, MPS_INFO, " Phys Disk State changed "
+ "from 0x%x to 0x%x for Phys Disk Number %d and "
+ "handle 0x%x at Enclosure handle 0x%x, Slot %d",
+ le32toh(event_data->PreviousValue),
+ le32toh(event_data->NewValue), event_data->PhysDiskNum,
+ le16toh(event_data->PhysDiskDevHandle),
+ le16toh(event_data->EnclosureHandle), le16toh(event_data->Slot));
switch (event_data->NewValue) {
case MPI2_RAID_PD_STATE_ONLINE:
case MPI2_RAID_PD_STATE_DEGRADED:
@@ -468,10 +478,19 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
targ = mpssas_find_target_by_handle(sassc, 0,
event_data->PhysDiskDevHandle);
if (targ) {
- targ->flags |= MPS_TARGET_FLAGS_RAID_COMPONENT;
- printf("%s %d: Found Target for handle 0x%x. \n",
- __func__, __LINE__ , event_data->PhysDiskDevHandle);
- }
+ if(!sc->WD_available) {
+ targ->flags |= MPS_TARGET_FLAGS_RAID_COMPONENT;
+ printf("%s %d: Found Target for handle 0x%x. \n",
+ __func__, __LINE__ , event_data->PhysDiskDevHandle);
+ } else if ((sc->WD_available &&
+ (sc->WD_hide_expose == MPS_WD_HIDE_ALWAYS)) ||
+ (sc->WD_valid_config && (sc->WD_hide_expose ==
+ MPS_WD_HIDE_IF_VOLUME))) {
+ targ->flags |= MPS_TARGET_FLAGS_RAID_COMPONENT;
+ printf("%s %d: WD: Found Target for handle 0x%x. \n",
+ __func__, __LINE__ , event_data->PhysDiskDevHandle);
+ }
+ }
break;
case MPI2_RAID_PD_STATE_OFFLINE:
case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
@@ -503,7 +522,7 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
mps_dprint(sc, MPS_INFO, " RAID Operation of %d is %d "
"percent complete for Volume with handle 0x%x",
event_data->RAIDOperation, event_data->PercentComplete,
- event_data->VolDevHandle);
+ le16toh(event_data->VolDevHandle));
break;
}
case MPI2_EVENT_LOG_ENTRY_ADDED:
@@ -591,6 +610,7 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
unsigned int id;
int ret;
int error = 0;
+ struct mpssas_lun *lun;
sassc = sc->sassc;
mpssas_startup_increment(sassc);
@@ -604,7 +624,7 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
device_info = le32toh(config_page.DeviceInfo);
if (((device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0)
- && (config_page.ParentDevHandle != 0)) {
+ && (le16toh(config_page.ParentDevHandle) != 0)) {
Mpi2ConfigReply_t tmp_mpi_reply;
Mpi2SasDevicePage0_t parent_config_page;
@@ -668,7 +688,13 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
targ->flags = 0;
TAILQ_INIT(&targ->commands);
TAILQ_INIT(&targ->timedout_commands);
+ while(!SLIST_EMPTY(&targ->luns)) {
+ lun = SLIST_FIRST(&targ->luns);
+ SLIST_REMOVE_HEAD(&targ->luns, lun_link);
+ free(lun, M_MPT2);
+ }
SLIST_INIT(&targ->luns);
+
mps_describe_devinfo(targ->devinfo, devstring, 80);
mps_dprint(sc, MPS_INFO, "Found device <%s> <%s> <0x%04x> <%d/%d>\n", devstring,
mps_describe_table(mps_linkrate_names, targ->linkrate),
@@ -802,7 +828,7 @@ mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
}
bcopy(buffer, id_buffer, sz);
bcopy(reply, mpi_reply, sizeof(Mpi2SataPassthroughReply_t));
- if ((reply->IOCStatus & MPI2_IOCSTATUS_MASK) !=
+ if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
MPI2_IOCSTATUS_SUCCESS) {
printf("%s: error reading SATA PASSTHRU; iocstatus = 0x%x\n",
__func__, reply->IOCStatus);
@@ -823,9 +849,11 @@ mpssas_volume_add(struct mps_softc *sc, u16 handle)
u64 wwid;
unsigned int id;
int error = 0;
+ struct mpssas_lun *lun;
sassc = sc->sassc;
mpssas_startup_increment(sassc);
+ /* wwid is endian safe */
mps_config_get_volume_wwid(sc, handle, &wwid);
if (!wwid) {
printf("%s: invalid WWID; cannot add volume to mapping table\n",
@@ -849,6 +877,11 @@ mpssas_volume_add(struct mps_softc *sc, u16 handle)
targ->devname = wwid;
TAILQ_INIT(&targ->commands);
TAILQ_INIT(&targ->timedout_commands);
+ while(!SLIST_EMPTY(&targ->luns)) {
+ lun = SLIST_FIRST(&targ->luns);
+ SLIST_REMOVE_HEAD(&targ->luns, lun_link);
+ free(lun, M_MPT2);
+ }
SLIST_INIT(&targ->luns);
if ((sassc->flags & MPSSAS_IN_STARTUP) == 0)
mpssas_rescan_target(sc, targ);
diff --git a/sys/dev/mps/mps_user.c b/sys/dev/mps/mps_user.c
index f4e5e35b58df..98dc511ad572 100644
--- a/sys/dev/mps/mps_user.c
+++ b/sys/dev/mps/mps_user.c
@@ -30,7 +30,7 @@
* LSI MPT-Fusion Host Adapter FreeBSD userland interface
*/
/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -701,6 +701,11 @@ mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd)
if (cmd->len > 0) {
buf = malloc(cmd->len, M_MPSUSER, M_WAITOK|M_ZERO);
+ if(!buf) {
+ mps_printf(sc, "Cannot allocate memory %s %d\n",
+ __func__, __LINE__);
+ return (ENOMEM);
+ }
cm->cm_data = buf;
cm->cm_length = cmd->len;
} else {
@@ -946,7 +951,7 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data)
*/
scsi_io_req->SenseBufferLength = (uint8_t)(data->RequestSize -
64);
- scsi_io_req->SenseBufferLowAddress = cm->cm_sense_busaddr;
+ scsi_io_req->SenseBufferLowAddress = htole32(cm->cm_sense_busaddr);
/*
* Set SGLOffset0 value. This is the number of dwords that SGL
@@ -1033,7 +1038,7 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data)
if (((MPI2_SCSI_IO_REPLY *)rpl)->SCSIState &
MPI2_SCSI_STATE_AUTOSENSE_VALID) {
sense_len =
- MIN(((MPI2_SCSI_IO_REPLY *)rpl)->SenseCount,
+ MIN((le32toh(((MPI2_SCSI_IO_REPLY *)rpl)->SenseCount)),
sizeof(struct scsi_sense_data));
mps_unlock(sc);
copyout(cm->cm_sense, cm->cm_req + 64, sense_len);
@@ -2053,7 +2058,7 @@ mps_ioctl(struct cdev *dev, u_long cmd, void *arg, int flag,
struct mps_cfg_page_req *page_req;
struct mps_ext_cfg_page_req *ext_page_req;
void *mps_page;
- int error, reset_loop;
+ int error, msleep_ret;
mps_page = NULL;
sc = dev->si_drv1;
@@ -2068,6 +2073,11 @@ mps_ioctl(struct cdev *dev, u_long cmd, void *arg, int flag,
break;
case MPSIO_READ_CFG_PAGE:
mps_page = malloc(page_req->len, M_MPSUSER, M_WAITOK | M_ZERO);
+ if(!mps_page) {
+ mps_printf(sc, "Cannot allocate memory %s %d\n",
+ __func__, __LINE__);
+ return (ENOMEM);
+ }
error = copyin(page_req->buf, mps_page,
sizeof(MPI2_CONFIG_PAGE_HEADER));
if (error)
@@ -2086,6 +2096,11 @@ mps_ioctl(struct cdev *dev, u_long cmd, void *arg, int flag,
break;
case MPSIO_READ_EXT_CFG_PAGE:
mps_page = malloc(ext_page_req->len, M_MPSUSER, M_WAITOK|M_ZERO);
+ if(!mps_page) {
+ mps_printf(sc, "Cannot allocate memory %s %d\n",
+ __func__, __LINE__);
+ return (ENOMEM);
+ }
error = copyin(ext_page_req->buf, mps_page,
sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
if (error)
@@ -2099,6 +2114,11 @@ mps_ioctl(struct cdev *dev, u_long cmd, void *arg, int flag,
break;
case MPSIO_WRITE_CFG_PAGE:
mps_page = malloc(page_req->len, M_MPSUSER, M_WAITOK|M_ZERO);
+ if(!mps_page) {
+ mps_printf(sc, "Cannot allocate memory %s %d\n",
+ __func__, __LINE__);
+ return (ENOMEM);
+ }
error = copyin(page_req->buf, mps_page, page_req->len);
if (error)
break;
@@ -2138,19 +2158,19 @@ mps_ioctl(struct cdev *dev, u_long cmd, void *arg, int flag,
case MPTIOCTL_RESET_ADAPTER:
mps_lock(sc);
sc->port_enable_complete = 0;
+ uint32_t reinit_start = time_uptime;
error = mps_reinit(sc);
+ /* Sleep for 300 second. */
+ msleep_ret = msleep(&sc->port_enable_complete, &sc->mps_mtx, PRIBIO,
+ "mps_porten", 300 * hz);
mps_unlock(sc);
- /*
- * Wait no more than 5 minutes for Port Enable to complete
- */
- for (reset_loop = 0; (reset_loop < MPS_DIAG_RESET_TIMEOUT) &&
- (!sc->port_enable_complete); reset_loop++) {
- DELAY(1000);
- }
- if (reset_loop == MPS_DIAG_RESET_TIMEOUT) {
+ if (msleep_ret)
printf("Port Enable did not complete after Diag "
- "Reset.\n");
- }
+ "Reset msleep error %d.\n", msleep_ret);
+ else
+ mps_dprint(sc, MPS_INFO,
+ "Hard Reset with Port Enable completed in %d seconds.\n",
+ (uint32_t) (time_uptime - reinit_start));
break;
case MPTIOCTL_DIAG_ACTION:
/*
diff --git a/sys/dev/mps/mpsvar.h b/sys/dev/mps/mpsvar.h
index 6246c4651950..2acb75b74568 100644
--- a/sys/dev/mps/mpsvar.h
+++ b/sys/dev/mps/mpsvar.h
@@ -1,32 +1,6 @@
/*-
* Copyright (c) 2009 Yahoo! Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-/*-
- * Copyright (c) 2011 LSI Corp.
+ * Copyright (c) 2011, 2012 LSI Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -58,7 +32,7 @@
#ifndef _MPSVAR_H
#define _MPSVAR_H
-#define MPS_DRIVER_VERSION "13.00.00.00-fbsd"
+#define MPS_DRIVER_VERSION "14.00.00.01-fbsd"
#define MPS_DB_MAX_WAIT 2500
@@ -80,6 +54,8 @@
#define MPS_SCSI_RI_INVALID_FRAME (0x00000002)
#define MPS_STRING_LENGTH 64
+#include <sys/endian.h>
+
/*
* host mapping related macro definitions
*/
@@ -276,7 +252,7 @@ struct mps_event_handle {
TAILQ_ENTRY(mps_event_handle) eh_list;
mps_evt_callback_t *callback;
void *data;
- uint8_t mask[16];
+ u32 mask[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
};
struct mps_softc {
@@ -333,7 +309,7 @@ struct mps_softc {
int fqdepth; /* Free queue */
int pqdepth; /* Post queue */
- uint8_t event_mask[16];
+ u32 event_mask[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
TAILQ_HEAD(, mps_event_handle) event_list;
struct mps_event_handle *mps_log_eh;
@@ -422,8 +398,10 @@ struct mps_softc {
#define MPS_DIAG_RESET_TIMEOUT 300000
uint8_t wait_for_port_enable;
uint8_t port_enable_complete;
+ uint8_t msleep_fake_chan;
/* WD controller */
+ uint8_t WD_available;
uint8_t WD_valid_config;
uint8_t WD_hide_expose;
@@ -469,12 +447,15 @@ mps_regwrite(struct mps_softc *sc, uint32_t offset, uint32_t val)
bus_space_write_4(sc->mps_btag, sc->mps_bhandle, offset, val);
}
+/* free_queue must have Little Endian address
+ * TODO- cm_reply_data is unwanted. We can remove it.
+ * */
static __inline void
mps_free_reply(struct mps_softc *sc, uint32_t busaddr)
{
if (++sc->replyfreeindex >= sc->fqdepth)
sc->replyfreeindex = 0;
- sc->free_queue[sc->replyfreeindex] = busaddr;
+ sc->free_queue[sc->replyfreeindex] = htole32(busaddr);
mps_regwrite(sc, MPI2_REPLY_FREE_HOST_INDEX_OFFSET, sc->replyfreeindex);
}
@@ -640,6 +621,9 @@ do { \
#define MPS_EVENTFIELD(sc, facts, attr, fmt) \
mps_dprint_field((sc), MPS_EVENT, #attr ": " #fmt "\n", (facts)->attr)
+#define CAN_SLEEP 1
+#define NO_SLEEP 0
+
static __inline void
mps_from_u64(uint64_t data, U64 *mps)
{
@@ -682,11 +666,11 @@ int mps_free(struct mps_softc *sc);
void mps_intr(void *);
void mps_intr_msi(void *);
void mps_intr_locked(void *);
-int mps_register_events(struct mps_softc *, uint8_t *, mps_evt_callback_t *,
+int mps_register_events(struct mps_softc *, u32 *, mps_evt_callback_t *,
void *, struct mps_event_handle **);
int mps_restart(struct mps_softc *);
-int mps_update_events(struct mps_softc *, struct mps_event_handle *, uint8_t *);
-int mps_deregister_events(struct mps_softc *, struct mps_event_handle *);
+int mps_update_events(struct mps_softc *, struct mps_event_handle *, u32 *);
+void mps_deregister_events(struct mps_softc *, struct mps_event_handle *);
int mps_push_sge(struct mps_command *, void *, size_t, int);
int mps_add_dmaseg(struct mps_command *, vm_paddr_t, size_t, u_int, int);
int mps_attach_sas(struct mps_softc *sc);
@@ -778,5 +762,21 @@ SYSCTL_DECL(_hw_mps);
#else
#define MPS_PRIORITY_XPT 5
#endif
+
+#if __FreeBSD_version < 800107
+// Prior to FreeBSD-8.0 scp3_flags was not defined.
+#define spc3_flags reserved
+
+#define SPC3_SID_PROTECT 0x01
+#define SPC3_SID_3PC 0x08
+#define SPC3_SID_TPGS_MASK 0x30
+#define SPC3_SID_TPGS_IMPLICIT 0x10
+#define SPC3_SID_TPGS_EXPLICIT 0x20
+#define SPC3_SID_ACC 0x40
+#define SPC3_SID_SCCS 0x80
+
+#define CAM_PRIORITY_NORMAL CAM_PRIORITY_NONE
+#endif
+
#endif