summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/mps/mps.c6
-rw-r--r--sys/dev/mps/mps_sas.c368
-rw-r--r--sys/dev/mps/mps_sas.h3
-rw-r--r--sys/dev/mps/mps_sas_lsi.c94
-rw-r--r--sys/dev/mps/mps_user.c12
-rw-r--r--sys/dev/mps/mpsvar.h13
6 files changed, 452 insertions, 44 deletions
diff --git a/sys/dev/mps/mps.c b/sys/dev/mps/mps.c
index d3d068b..e11e9a6 100644
--- a/sys/dev/mps/mps.c
+++ b/sys/dev/mps/mps.c
@@ -529,7 +529,7 @@ mps_enqueue_request(struct mps_softc *sc, struct mps_command *cm)
mps_dprint(sc, MPS_TRACE, "%s SMID %u cm %p ccb %p\n", __func__,
cm->cm_desc.Default.SMID, cm, cm->cm_ccb);
- if (sc->mps_flags & MPS_FLAGS_ATTACH_DONE)
+ if (sc->mps_flags & MPS_FLAGS_ATTACH_DONE && !(sc->mps_flags & MPS_FLAGS_SHUTDOWN))
mtx_assert(&sc->mps_mtx, MA_OWNED);
if (++sc->io_cmds_active > sc->io_cmds_highwater)
@@ -1335,6 +1335,8 @@ mps_free(struct mps_softc *sc)
((error = mps_detach_sas(sc)) != 0))
return (error);
+ mps_detach_user(sc);
+
/* Put the IOC back in the READY state. */
mps_lock(sc);
if ((error = mps_transition_ready(sc)) != 0) {
@@ -2142,7 +2144,7 @@ mps_wait_command(struct mps_softc *sc, struct mps_command *cm, int timeout)
error = mps_map_command(sc, cm);
if ((error != 0) && (error != EINPROGRESS))
return (error);
- error = msleep(cm, &sc->mps_mtx, 0, "mpswait", timeout);
+ error = msleep(cm, &sc->mps_mtx, 0, "mpswait", timeout*hz);
if (error == EWOULDBLOCK)
error = ETIMEDOUT;
return (error);
diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c
index fb57b63..12a1d51 100644
--- a/sys/dev/mps/mps_sas.c
+++ b/sys/dev/mps/mps_sas.c
@@ -139,7 +139,6 @@ static uint8_t op_code_prot[256] = {
MALLOC_DEFINE(M_MPSSAS, "MPSSAS", "MPS SAS memory");
-static struct mpssas_target * mpssas_find_target_by_handle(struct mpssas_softc *, int, uint16_t);
static void mpssas_discovery_timeout(void *data);
static void mpssas_remove_device(struct mps_softc *, struct mps_command *);
static void mpssas_remove_complete(struct mps_softc *, struct mps_command *);
@@ -175,7 +174,7 @@ static int mpssas_send_portenable(struct mps_softc *sc);
static void mpssas_portenable_complete(struct mps_softc *sc,
struct mps_command *cm);
-static struct mpssas_target *
+struct mpssas_target *
mpssas_find_target_by_handle(struct mpssas_softc *sassc, int start, uint16_t handle)
{
struct mpssas_target *target;
@@ -351,22 +350,123 @@ mpssas_log_command(struct mps_command *cm, const char *fmt, ...)
va_end(ap);
}
+
static void
-mpssas_lost_target(struct mps_softc *sc, struct mpssas_target *targ)
+mpssas_remove_volume(struct mps_softc *sc, struct mps_command *tm)
{
- struct mpssas_softc *sassc = sc->sassc;
- path_id_t pathid = cam_sim_path(sassc->sim);
- struct cam_path *path;
+ MPI2_SCSI_TASK_MANAGE_REPLY *reply;
+ struct mpssas_target *targ;
+ uint16_t handle;
+
+ mps_dprint(sc, MPS_INFO, "%s\n", __func__);
+
+ reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply;
+ handle = (uint16_t)(uintptr_t)tm->cm_complete_data;
+ targ = tm->cm_targ;
- mps_printf(sc, "%s targetid %u\n", __func__, targ->tid);
- if (xpt_create_path(&path, NULL, pathid, targ->tid, 0) != CAM_REQ_CMP) {
- mps_printf(sc, "unable to create path for lost target %d\n",
- targ->tid);
+ if (reply == NULL) {
+ /* XXX retry the remove after the diag reset completes? */
+ mps_printf(sc, "%s NULL reply reseting device 0x%04x\n",
+ __func__, handle);
+ mpssas_free_tm(sc, tm);
return;
}
- xpt_async(AC_LOST_DEVICE, path, NULL);
- xpt_free_path(path);
+ if (reply->IOCStatus != MPI2_IOCSTATUS_SUCCESS) {
+ mps_printf(sc, "IOCStatus = 0x%x while resetting device 0x%x\n",
+ reply->IOCStatus, handle);
+ mpssas_free_tm(sc, tm);
+ return;
+ }
+
+ mps_printf(sc, "Reset aborted %u commands\n", reply->TerminationCount);
+ mps_free_reply(sc, tm->cm_reply_data);
+ tm->cm_reply = NULL; /* Ensures the the reply won't get re-freed */
+
+ mps_printf(sc, "clearing target %u handle 0x%04x\n", targ->tid, handle);
+
+ /*
+ * Don't clear target if remove fails because things will get confusing.
+ * Leave the devname and sasaddr intact so that we know to avoid reusing
+ * 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) {
+ targ = tm->cm_targ;
+ targ->handle = 0x0;
+ targ->encl_handle = 0x0;
+ targ->encl_slot = 0x0;
+ targ->exp_dev_handle = 0x0;
+ targ->phy_num = 0x0;
+ targ->linkrate = 0x0;
+ targ->devinfo = 0x0;
+ targ->flags = 0x0;
+ }
+
+ mpssas_free_tm(sc, tm);
+}
+
+
+/*
+ * No Need to call "MPI2_SAS_OP_REMOVE_DEVICE" For Volume removal.
+ * Otherwise Volume Delete is same as Bare Drive Removal.
+ */
+void
+mpssas_prepare_volume_remove(struct mpssas_softc *sassc, uint16_t handle)
+{
+ MPI2_SCSI_TASK_MANAGE_REQUEST *req;
+ struct mps_softc *sc;
+ struct mps_command *cm;
+ struct mpssas_target *targ = NULL;
+
+ mps_dprint(sassc->sc, MPS_INFO, "%s\n", __func__);
+ sc = sassc->sc;
+
+#ifdef WD_SUPPORT
+ /*
+ * 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.
+ */
+ if (sc->WD_available && (sc->WD_hide_expose ==
+ MPS_WD_EXPOSE_ALWAYS)) {
+ return;
+ }
+#endif //WD_SUPPORT
+
+ targ = mpssas_find_target_by_handle(sassc, 0, handle);
+ if (targ == NULL) {
+ /* FIXME: what is the action? */
+ /* We don't know about this device? */
+ printf("%s %d : invalid handle 0x%x \n", __func__,__LINE__, handle);
+ return;
+ }
+
+ targ->flags |= MPSSAS_TARGET_INREMOVAL;
+
+ cm = mpssas_alloc_tm(sc);
+ if (cm == NULL) {
+ mps_printf(sc, "%s: command alloc failure\n", __func__);
+ return;
+ }
+
+ mpssas_rescan_target(sc, targ);
+
+ req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req;
+ req->DevHandle = targ->handle;
+ req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
+ req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
+
+ /* SAS Hard Link Reset / SATA Link Reset */
+ req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
+
+ cm->cm_targ = targ;
+ cm->cm_data = NULL;
+ cm->cm_desc.HighPriority.RequestFlags =
+ MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
+ cm->cm_complete = mpssas_remove_volume;
+ cm->cm_complete_data = (void *)(uintptr_t)handle;
+ mps_map_command(sc, cm);
}
/*
@@ -386,7 +486,7 @@ mpssas_prepare_remove(struct mpssas_softc *sassc, uint16_t handle)
struct mps_command *cm;
struct mpssas_target *targ = NULL;
- mps_dprint(sassc->sc, MPS_TRACE, "%s\n", __func__);
+ mps_dprint(sassc->sc, MPS_INFO, "%s\n", __func__);
/*
* If this is a WD controller, determine if the disk should be exposed
@@ -403,7 +503,7 @@ mpssas_prepare_remove(struct mpssas_softc *sassc, uint16_t handle)
if (targ == NULL) {
/* FIXME: what is the action? */
/* We don't know about this device? */
- printf("%s: invalid handle 0x%x \n", __func__, handle);
+ printf("%s %d : invalid handle 0x%x \n", __func__,__LINE__, handle);
return;
}
@@ -415,7 +515,7 @@ mpssas_prepare_remove(struct mpssas_softc *sassc, uint16_t handle)
return;
}
- mpssas_lost_target(sc, targ);
+ mpssas_rescan_target(sc, targ);
req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req;
memset(req, 0, sizeof(*req));
@@ -443,7 +543,7 @@ mpssas_remove_device(struct mps_softc *sc, struct mps_command *tm)
struct mps_command *next_cm;
uint16_t handle;
- mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+ mps_dprint(sc, MPS_INFO, "%s\n", __func__);
reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply;
handle = (uint16_t)(uintptr_t)tm->cm_complete_data;
@@ -514,7 +614,7 @@ mpssas_remove_complete(struct mps_softc *sc, struct mps_command *tm)
uint16_t handle;
struct mpssas_target *targ;
- mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+ mps_dprint(sc, MPS_INFO, "%s\n", __func__);
reply = (MPI2_SAS_IOUNIT_CONTROL_REPLY *)tm->cm_reply;
handle = (uint16_t)(uintptr_t)tm->cm_complete_data;
@@ -558,6 +658,7 @@ mpssas_remove_complete(struct mps_softc *sc, struct mps_command *tm)
targ->phy_num = 0x0;
targ->linkrate = 0x0;
targ->devinfo = 0x0;
+ targ->flags = 0x0;
}
mpssas_free_tm(sc, tm);
@@ -690,7 +791,7 @@ mps_detach_sas(struct mps_softc *sc)
{
struct mpssas_softc *sassc;
- mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+ mps_dprint(sc, MPS_INFO, "%s\n", __func__);
if (sc->sassc == NULL)
return (0);
@@ -733,6 +834,7 @@ mps_detach_sas(struct mps_softc *sc)
}
mps_unlock(sc);
+ mps_dprint(sc, MPS_INFO, "%s:%d\n", __func__,__LINE__);
if (sassc->devq != NULL)
cam_simq_free(sassc->devq);
@@ -1475,11 +1577,11 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
uint16_t eedp_flags;
sc = sassc->sc;
- mps_dprint(sc, MPS_TRACE, "%s ccb %p\n", __func__, ccb);
mtx_assert(&sc->mps_mtx, MA_OWNED);
csio = &ccb->csio;
targ = &sassc->targets[csio->ccb_h.target_id];
+ mps_dprint(sc, MPS_TRACE, "%s ccb %p target flag %x\n", __func__, ccb, targ->flags);
if (targ->handle == 0x0) {
mps_dprint(sc, MPS_TRACE, "%s NULL handle for target %u\n",
__func__, csio->ccb_h.target_id);
@@ -1487,6 +1589,13 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
xpt_done(ccb);
return;
}
+ if (targ->flags & MPS_TARGET_FLAGS_RAID_COMPONENT) {
+ mps_dprint(sc, MPS_TRACE, "%s Raid component no SCSI IO supported %u\n",
+ __func__, csio->ccb_h.target_id);
+ csio->ccb_h.status = CAM_TID_INVALID;
+ xpt_done(ccb);
+ return;
+ }
/*
* If devinfo is 0 this will be a volume. In that case don't tell CAM
* that the volume has timed out. We want volumes to be enumerated
@@ -1684,6 +1793,198 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
}
static void
+mps_response_code(struct mps_softc *sc, u8 response_code)
+{
+ char *desc;
+
+ switch (response_code) {
+ case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE:
+ desc = "task management request completed";
+ break;
+ case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME:
+ desc = "invalid frame";
+ break;
+ case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
+ desc = "task management request not supported";
+ break;
+ case MPI2_SCSITASKMGMT_RSP_TM_FAILED:
+ desc = "task management request failed";
+ break;
+ case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED:
+ desc = "task management request succeeded";
+ break;
+ case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN:
+ desc = "invalid lun";
+ break;
+ case 0xA:
+ desc = "overlapped tag attempted";
+ break;
+ case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
+ desc = "task queued, however not sent to target";
+ break;
+ default:
+ desc = "unknown";
+ break;
+ }
+ mps_dprint(sc, MPS_INFO, "response_code(0x%01x): %s\n",
+ response_code, desc);
+}
+/**
+ * mps_sc_failed_io_info - translated non-succesfull SCSI_IO request
+ */
+static void
+mps_sc_failed_io_info(struct mps_softc *sc, struct ccb_scsiio *csio,
+ Mpi2SCSIIOReply_t *mpi_reply)
+{
+ u32 response_info;
+ u8 *response_bytes;
+ u16 ioc_status = le16toh(mpi_reply->IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ u8 scsi_state = mpi_reply->SCSIState;
+ u8 scsi_status = mpi_reply->SCSIStatus;
+ char *desc_ioc_state = NULL;
+ char *desc_scsi_status = NULL;
+ char *desc_scsi_state = sc->tmp_string;
+ u32 log_info = le32toh(mpi_reply->IOCLogInfo);
+
+ if (log_info == 0x31170000)
+ return;
+
+ switch (ioc_status) {
+ case MPI2_IOCSTATUS_SUCCESS:
+ desc_ioc_state = "success";
+ break;
+ case MPI2_IOCSTATUS_INVALID_FUNCTION:
+ desc_ioc_state = "invalid function";
+ break;
+ case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
+ desc_ioc_state = "scsi recovered error";
+ break;
+ case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
+ desc_ioc_state = "scsi invalid dev handle";
+ break;
+ case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
+ desc_ioc_state = "scsi device not there";
+ break;
+ case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
+ desc_ioc_state = "scsi data overrun";
+ break;
+ case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
+ desc_ioc_state = "scsi data underrun";
+ break;
+ case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
+ desc_ioc_state = "scsi io data error";
+ break;
+ case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
+ desc_ioc_state = "scsi protocol error";
+ break;
+ case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
+ desc_ioc_state = "scsi task terminated";
+ break;
+ case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
+ desc_ioc_state = "scsi residual mismatch";
+ break;
+ case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
+ desc_ioc_state = "scsi task mgmt failed";
+ break;
+ case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
+ desc_ioc_state = "scsi ioc terminated";
+ break;
+ case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
+ desc_ioc_state = "scsi ext terminated";
+ break;
+ case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
+ desc_ioc_state = "eedp guard error";
+ break;
+ case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
+ desc_ioc_state = "eedp ref tag error";
+ break;
+ case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
+ desc_ioc_state = "eedp app tag error";
+ break;
+ default:
+ desc_ioc_state = "unknown";
+ break;
+ }
+
+ switch (scsi_status) {
+ case MPI2_SCSI_STATUS_GOOD:
+ desc_scsi_status = "good";
+ break;
+ case MPI2_SCSI_STATUS_CHECK_CONDITION:
+ desc_scsi_status = "check condition";
+ break;
+ case MPI2_SCSI_STATUS_CONDITION_MET:
+ desc_scsi_status = "condition met";
+ break;
+ case MPI2_SCSI_STATUS_BUSY:
+ desc_scsi_status = "busy";
+ break;
+ case MPI2_SCSI_STATUS_INTERMEDIATE:
+ desc_scsi_status = "intermediate";
+ break;
+ case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET:
+ desc_scsi_status = "intermediate condmet";
+ break;
+ case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
+ desc_scsi_status = "reservation conflict";
+ break;
+ case MPI2_SCSI_STATUS_COMMAND_TERMINATED:
+ desc_scsi_status = "command terminated";
+ break;
+ case MPI2_SCSI_STATUS_TASK_SET_FULL:
+ desc_scsi_status = "task set full";
+ break;
+ case MPI2_SCSI_STATUS_ACA_ACTIVE:
+ desc_scsi_status = "aca active";
+ break;
+ case MPI2_SCSI_STATUS_TASK_ABORTED:
+ desc_scsi_status = "task aborted";
+ break;
+ default:
+ desc_scsi_status = "unknown";
+ break;
+ }
+
+ desc_scsi_state[0] = '\0';
+ if (!scsi_state)
+ desc_scsi_state = " ";
+ if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
+ strcat(desc_scsi_state, "response info ");
+ if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
+ strcat(desc_scsi_state, "state terminated ");
+ if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS)
+ strcat(desc_scsi_state, "no status ");
+ if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED)
+ strcat(desc_scsi_state, "autosense failed ");
+ if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)
+ strcat(desc_scsi_state, "autosense valid ");
+
+ mps_dprint(sc, MPS_INFO, "\thandle(0x%04x), ioc_status(%s)(0x%04x), \n",
+ le16toh(mpi_reply->DevHandle),
+ desc_ioc_state, ioc_status);
+ /* We can add more detail about underflow data here
+ * TO-DO
+ * */
+ mps_dprint(sc, MPS_INFO, "\tscsi_status(%s)(0x%02x), "
+ "scsi_state(%s)(0x%02x)\n", desc_scsi_status,
+ scsi_status, desc_scsi_state, scsi_state);
+
+ if (sc->mps_debug & MPS_INFO &&
+ scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
+ mps_dprint(sc, MPS_INFO, "-> Sense Buffer Data : Start :\n");
+ scsi_sense_print(csio);
+ mps_dprint(sc, MPS_INFO, "-> Sense Buffer Data : End :\n");
+ }
+
+ if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
+ response_info = le32toh(mpi_reply->ResponseInfo);
+ response_bytes = (u8 *)&response_info;
+ mps_response_code(sc,response_bytes[0]);
+ }
+}
+
+static void
mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
{
MPI2_SCSI_IO_REPLY *rep;
@@ -2018,6 +2319,8 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
break;
}
+
+ mps_sc_failed_io_info(sc,csio,rep);
if (sassc->flags & MPSSAS_QUEUE_FROZEN) {
ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
@@ -2799,17 +3102,26 @@ mpssas_scanner_thread(void *arg)
mps_lock(sc);
for (;;) {
+ /* Sleep for 1 second and check the queue status*/
msleep(&sassc->ccb_scanq, &sc->mps_mtx, PRIBIO,
- "mps_scanq", 0);
+ "mps_scanq", 1 * hz);
if (sassc->flags & MPSSAS_SHUTDOWN) {
mps_dprint(sc, MPS_TRACE, "Scanner shutting down\n");
break;
}
+next_work:
+ // Get first work.
ccb = (union ccb *)TAILQ_FIRST(&sassc->ccb_scanq);
if (ccb == NULL)
continue;
+ // Got first work.
TAILQ_REMOVE(&sassc->ccb_scanq, &ccb->ccb_h, sim_links.tqe);
xpt_action(ccb);
+ if (sassc->flags & MPSSAS_SHUTDOWN) {
+ mps_dprint(sc, MPS_TRACE, "Scanner shutting down\n");
+ break;
+ }
+ goto next_work;
}
sassc->flags &= ~MPSSAS_SCANTHREAD;
@@ -3009,7 +3321,7 @@ mpssas_check_eedp(struct mpssas_softc *sassc)
}
if (!found_lun) {
lun = malloc(sizeof(struct mpssas_lun),
- M_MPT2, M_WAITOK | M_ZERO);
+ M_MPT2, M_NOWAIT | M_ZERO);
if (lun == NULL) {
mps_dprint(sc, MPS_FAULT,
"Unable to alloc LUN for "
@@ -3084,6 +3396,20 @@ mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb)
if (done_ccb == NULL)
return;
+
+ /* Driver need to release devq, it Scsi command is
+ * generated by driver internally.
+ * Currently there is a single place where driver
+ * calls scsi command internally. In future if driver
+ * calls more scsi command internally, it needs to release
+ * devq internally, since those command will not go back to
+ * cam_periph.
+ */
+ if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) ) {
+ done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
+ xpt_release_devq(done_ccb->ccb_h.path,
+ /*count*/ 1, /*run_queue*/TRUE);
+ }
rcap_buf = (struct scsi_read_capacity_eedp *)done_ccb->csio.data_ptr;
diff --git a/sys/dev/mps/mps_sas.h b/sys/dev/mps/mps_sas.h
index 343247f..6653cc3 100644
--- a/sys/dev/mps/mps_sas.h
+++ b/sys/dev/mps/mps_sas.h
@@ -49,8 +49,11 @@ struct mpssas_target {
#define MPSSAS_TARGET_INRESET (1 << 1)
#define MPSSAS_TARGET_INDIAGRESET (1 << 2)
#define MPSSAS_TARGET_INREMOVAL (1 << 3)
+#define MPS_TARGET_FLAGS_RAID_COMPONENT (1 << 4)
+#define MPS_TARGET_FLAGS_VOLUME (1 << 5)
#define MPSSAS_TARGET_INRECOVERY (MPSSAS_TARGET_INABORT | \
MPSSAS_TARGET_INRESET | MPSSAS_TARGET_INCHIPRESET)
+
#define MPSSAS_TARGET_ADD (1 << 29)
#define MPSSAS_TARGET_REMOVE (1 << 30)
uint16_t tid;
diff --git a/sys/dev/mps/mps_sas_lsi.c b/sys/dev/mps/mps_sas_lsi.c
index 70c74ea..4181405 100644
--- a/sys/dev/mps/mps_sas_lsi.c
+++ b/sys/dev/mps/mps_sas_lsi.c
@@ -107,7 +107,7 @@ struct _ata_identify_device_data {
u16 model_number[20]; /* 27-46*/
u16 reserved3[209]; /* 47-255*/
};
-
+static u32 event_count;
static void mpssas_fw_work(struct mps_softc *sc,
struct mps_fw_event_work *fw_event);
static void mpssas_fw_event_free(struct mps_softc *,
@@ -119,7 +119,7 @@ static int mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
int mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
u64 *sas_address, u16 handle, u32 device_info);
static int mpssas_volume_add(struct mps_softc *sc,
- Mpi2EventIrConfigElement_t *element);
+ u16 handle);
void
mpssas_evt_handler(struct mps_softc *sc, uintptr_t data,
@@ -191,6 +191,8 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
struct mpssas_softc *sassc;
sassc = sc->sassc;
+ mps_dprint(sc, MPS_INFO, "(%d)->(%s) Working on Event: [%x]\n",
+ event_count++,__func__,fw_event->event);
switch (fw_event->event) {
case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
{
@@ -284,7 +286,7 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
case MPI2_EVENT_IR_CHANGE_RC_ADDED:
if (!foreign_config) {
- if (mpssas_volume_add(sc, element)) {
+ if (mpssas_volume_add(sc, le16toh(element->VolDevHandle))){
printf("%s: failed to add RAID "
"volume with handle 0x%x\n",
__func__, le16toh(element->
@@ -319,12 +321,18 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
}
break;
case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
+ case MPI2_EVENT_IR_CHANGE_RC_HIDE:
/*
* Phys Disk of a volume has been created. Hide
* it from the OS.
*/
- mpssas_prepare_remove(sassc, element->
- PhysDiskDevHandle);
+ targ = mpssas_find_target_by_handle(sassc, 0, element->PhysDiskDevHandle);
+ if (targ == NULL)
+ break;
+
+ targ->flags |= MPS_TARGET_FLAGS_RAID_COMPONENT;
+ mpssas_rescan_target(sc, targ);
+
break;
case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
/*
@@ -379,6 +387,35 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
"handle 0x%x", event_data->PreviousValue,
event_data->NewValue,
event_data->VolDevHandle);
+ u32 state;
+ struct mpssas_target *targ;
+ state = le32toh(event_data->NewValue);
+ switch (state) {
+ case MPI2_RAID_VOL_STATE_MISSING:
+ case MPI2_RAID_VOL_STATE_FAILED:
+ mpssas_prepare_volume_remove(sassc, event_data->
+ VolDevHandle);
+ break;
+
+ case MPI2_RAID_VOL_STATE_ONLINE:
+ case MPI2_RAID_VOL_STATE_DEGRADED:
+ case MPI2_RAID_VOL_STATE_OPTIMAL:
+ targ = mpssas_find_target_by_handle(sassc, 0, event_data->VolDevHandle);
+ if (targ) {
+ printf("%s %d: Volume handle 0x%x is already added \n",
+ __func__, __LINE__ , event_data->VolDevHandle);
+ break;
+ }
+ if (mpssas_volume_add(sc, le16toh(event_data->VolDevHandle))) {
+ printf("%s: failed to add RAID "
+ "volume with handle 0x%x\n",
+ __func__, le16toh(event_data->
+ VolDevHandle));
+ }
+ break;
+ default:
+ break;
+ }
break;
default:
break;
@@ -389,6 +426,7 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
{
Mpi2EventDataIrPhysicalDisk_t *event_data =
fw_event->event_data;
+ struct mpssas_target *targ;
/*
* Informational only.
@@ -399,7 +437,7 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
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", event_data->PreviousValue,
+ "%d\n", event_data->PreviousValue,
event_data->NewValue, event_data->PhysDiskNum,
event_data->PhysDiskDevHandle,
event_data->EnclosureHandle, event_data->Slot);
@@ -407,7 +445,7 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
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",
+ "handle 0x%x at Enclosure handle 0x%x, Slot %d\n",
event_data->PreviousValue, event_data->NewValue,
event_data->PhysDiskNum,
event_data->PhysDiskDevHandle,
@@ -416,12 +454,38 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
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",
+ "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);
- break;
+ switch (event_data->NewValue) {
+ case MPI2_RAID_PD_STATE_ONLINE:
+ case MPI2_RAID_PD_STATE_DEGRADED:
+ case MPI2_RAID_PD_STATE_REBUILDING:
+ case MPI2_RAID_PD_STATE_OPTIMAL:
+ case MPI2_RAID_PD_STATE_HOT_SPARE:
+ 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);
+ }
+ break;
+ case MPI2_RAID_PD_STATE_OFFLINE:
+ case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
+ case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
+ default:
+ 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);
+ }
+ break;
+ }
default:
break;
}
@@ -494,6 +558,7 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
break;
}
+ mps_dprint(sc, MPS_INFO, "(%d)->(%s) Event Free: [%x]\n",event_count,__func__, fw_event->event);
mpssas_fw_event_free(sc, fw_event);
}
@@ -584,7 +649,7 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
error = ENXIO;
goto out;
}
- mps_vprintf(sc, "SAS Address from SAS device page0 = %jx\n",
+ mps_dprint(sc, MPS_INFO, "SAS Address from SAS device page0 = %jx\n",
sas_address);
targ = &sassc->targets[id];
targ->devinfo = device_info;
@@ -605,12 +670,12 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
TAILQ_INIT(&targ->timedout_commands);
SLIST_INIT(&targ->luns);
mps_describe_devinfo(targ->devinfo, devstring, 80);
- mps_vprintf(sc, "Found device <%s> <%s> <0x%04x> <%d/%d>\n", devstring,
+ mps_dprint(sc, MPS_INFO, "Found device <%s> <%s> <0x%04x> <%d/%d>\n", devstring,
mps_describe_table(mps_linkrate_names, targ->linkrate),
targ->handle, targ->encl_handle, targ->encl_slot);
if ((sassc->flags & MPSSAS_IN_STARTUP) == 0)
mpssas_rescan_target(sc, targ);
- mps_vprintf(sc, "Target id 0x%x added\n", targ->tid);
+ mps_dprint(sc, MPS_INFO, "Target id 0x%x added\n", targ->tid);
out:
mpssas_startup_decrement(sassc);
return (error);
@@ -751,12 +816,11 @@ out:
}
static int
-mpssas_volume_add(struct mps_softc *sc, Mpi2EventIrConfigElement_t *element)
+mpssas_volume_add(struct mps_softc *sc, u16 handle)
{
struct mpssas_softc *sassc;
struct mpssas_target *targ;
u64 wwid;
- u16 handle = le16toh(element->VolDevHandle);
unsigned int id;
int error = 0;
@@ -855,7 +919,9 @@ mpssas_ir_shutdown(struct mps_softc *sc)
action->Function = MPI2_FUNCTION_RAID_ACTION;
action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+ mps_lock(sc);
mps_request_polled(sc, cm);
+ mps_unlock(sc);
/*
* Don't check for reply, just leave.
diff --git a/sys/dev/mps/mps_user.c b/sys/dev/mps/mps_user.c
index 75bb7ad..f4e5e35 100644
--- a/sys/dev/mps/mps_user.c
+++ b/sys/dev/mps/mps_user.c
@@ -712,7 +712,7 @@ mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd)
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
mps_lock(sc);
- err = mps_wait_command(sc, cm, 0);
+ err = mps_wait_command(sc, cm, 30);
if (err) {
mps_printf(sc, "%s: invalid request: error %d\n",
@@ -842,7 +842,7 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data)
cm->cm_complete = NULL;
cm->cm_complete_data = NULL;
- err = mps_wait_command(sc, cm, 0);
+ err = mps_wait_command(sc, cm, 30);
if (err != 0) {
err = EIO;
@@ -979,7 +979,7 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data)
mps_lock(sc);
- err = mps_wait_command(sc, cm, 0);
+ err = mps_wait_command(sc, cm, 30);
if (err) {
mps_printf(sc, "%s: invalid request: error %d\n", __func__,
@@ -1098,10 +1098,12 @@ mps_user_get_adapter_data(struct mps_softc *sc, mps_adapter_data_t *data)
* Need to get BIOS Config Page 3 for the BIOS Version.
*/
data->BiosVersion = 0;
+ mps_lock(sc);
if (mps_config_get_bios_pg3(sc, &mpi_reply, &config_page))
printf("%s: Error while retrieving BIOS Version\n", __func__);
else
data->BiosVersion = config_page.BiosVersion;
+ mps_unlock(sc);
}
static void
@@ -1194,7 +1196,7 @@ mps_post_fw_diag_buffer(struct mps_softc *sc,
/*
* Send command synchronously.
*/
- status = mps_wait_command(sc, cm, 0);
+ status = mps_wait_command(sc, cm, 30);
if (status) {
mps_printf(sc, "%s: invalid request: error %d\n", __func__,
status);
@@ -1278,7 +1280,7 @@ mps_release_fw_diag_buffer(struct mps_softc *sc,
/*
* Send command synchronously.
*/
- status = mps_wait_command(sc, cm, 0);
+ status = mps_wait_command(sc, cm, 30);
if (status) {
mps_printf(sc, "%s: invalid request: error %d\n", __func__,
status);
diff --git a/sys/dev/mps/mpsvar.h b/sys/dev/mps/mpsvar.h
index c6f83df..6246c46 100644
--- a/sys/dev/mps/mpsvar.h
+++ b/sys/dev/mps/mpsvar.h
@@ -58,7 +58,7 @@
#ifndef _MPSVAR_H
#define _MPSVAR_H
-#define MPS_DRIVER_VERSION "11.255.03.00-fbsd"
+#define MPS_DRIVER_VERSION "13.00.00.00-fbsd"
#define MPS_DB_MAX_WAIT 2500
@@ -78,6 +78,7 @@
#define MPS_PERIODIC_DELAY 1 /* 1 second heartbeat/watchdog check */
#define MPS_SCSI_RI_INVALID_FRAME (0x00000002)
+#define MPS_STRING_LENGTH 64
/*
* host mapping related macro definitions
@@ -309,7 +310,7 @@ struct mps_softc {
struct callout periodic;
struct mpssas_softc *sassc;
-
+ char tmp_string[MPS_STRING_LENGTH];
TAILQ_HEAD(, mps_command) req_list;
TAILQ_HEAD(, mps_command) high_priority_req_list;
TAILQ_HEAD(, mps_chain) chain_list;
@@ -521,6 +522,12 @@ mps_free_command(struct mps_softc *sc, struct mps_command *cm)
cm->cm_max_segs = 0;
cm->cm_lun = 0;
cm->cm_state = MPS_CM_STATE_FREE;
+ cm->cm_data = NULL;
+ cm->cm_length = 0;
+ cm->cm_out_len = 0;
+ cm->cm_sglsize = 0;
+ cm->cm_sge = NULL;
+
TAILQ_FOREACH_SAFE(chain, &cm->cm_chain_list, chain_link, chain_temp) {
TAILQ_REMOVE(&cm->cm_chain_list, chain, chain_link);
mps_free_chain(sc, chain);
@@ -749,7 +756,9 @@ void mps_mapping_ir_config_change_event(struct mps_softc *sc,
void mpssas_evt_handler(struct mps_softc *sc, uintptr_t data,
MPI2_EVENT_NOTIFICATION_REPLY *event);
void mpssas_prepare_remove(struct mpssas_softc *sassc, uint16_t handle);
+void mpssas_prepare_volume_remove(struct mpssas_softc *sassc, uint16_t handle);
int mpssas_startup(struct mps_softc *sc);
+struct mpssas_target * mpssas_find_target_by_handle(struct mpssas_softc *, int, uint16_t);
SYSCTL_DECL(_hw_mps);
OpenPOWER on IntegriCloud