aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/mpr
diff options
context:
space:
mode:
authorKashyap D Desai <kadesai@FreeBSD.org>2018-12-26 10:40:27 +0000
committerKashyap D Desai <kadesai@FreeBSD.org>2018-12-26 10:40:27 +0000
commit89d1c21f458d83a882c92a8a2b2b5be92cbdf2ec (patch)
treee3e3fcec2ed4883a0d148fafd5fe77ff2ee56685 /sys/dev/mpr
parent23daf8f40bd5665caf4871c8b21ab4cd1a09bb84 (diff)
Notes
Diffstat (limited to 'sys/dev/mpr')
-rw-r--r--sys/dev/mpr/mpr_config.c159
-rw-r--r--sys/dev/mpr/mpr_sas.c60
-rw-r--r--sys/dev/mpr/mpr_sas.h1
-rw-r--r--sys/dev/mpr/mpr_sas_lsi.c20
-rw-r--r--sys/dev/mpr/mprvar.h36
5 files changed, 259 insertions, 17 deletions
diff --git a/sys/dev/mpr/mpr_config.c b/sys/dev/mpr/mpr_config.c
index 9f1ed1d0f566..f172fb453a5b 100644
--- a/sys/dev/mpr/mpr_config.c
+++ b/sys/dev/mpr/mpr_config.c
@@ -324,6 +324,137 @@ out:
}
/**
+ * mpr_config_get_man_pg11 - obtain manufacturing page 11
+ * @sc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpr_config_get_man_pg11(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
+ Mpi2ManufacturingPage11_t *config_page)
+{
+ MPI2_CONFIG_REQUEST *request;
+ MPI2_CONFIG_REPLY *reply;
+ struct mpr_command *cm;
+ MPI2_CONFIG_PAGE_MAN_11 *page = NULL;
+ int error = 0;
+ u16 ioc_status;
+
+ mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
+
+ if ((cm = mpr_alloc_command(sc)) == NULL) {
+ printf("%s: command alloc failed @ line %d\n", __func__,
+ __LINE__);
+ error = EBUSY;
+ goto out;
+ }
+ request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+ bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+ request->Function = MPI2_FUNCTION_CONFIG;
+ request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
+ request->Header.PageNumber = 11;
+ request->Header.PageLength = request->Header.PageVersion = 0;
+ cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+ cm->cm_data = NULL;
+ error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+ if (error || (reply == NULL)) {
+ /* FIXME */
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
+ printf("%s: request for header completed with error %d",
+ __func__, error);
+ error = ENXIO;
+ goto out;
+ }
+ ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+ bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ /* FIXME */
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
+ printf("%s: header read with error; iocstatus = 0x%x\n",
+ __func__, ioc_status);
+ error = ENXIO;
+ goto out;
+ }
+ /* We have to do free and alloc for the reply-free and reply-post
+ * counters to match - Need to review the reply FIFO handling.
+ */
+ mpr_free_command(sc, cm);
+
+ if ((cm = mpr_alloc_command(sc)) == NULL) {
+ printf("%s: command alloc failed @ line %d\n", __func__,
+ __LINE__);
+ error = EBUSY;
+ goto out;
+ }
+ request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
+ bzero(request, sizeof(MPI2_CONFIG_REQUEST));
+ request->Function = MPI2_FUNCTION_CONFIG;
+ request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
+ request->Header.PageNumber = 11;
+ request->Header.PageVersion = mpi_reply->Header.PageVersion;
+ request->Header.PageLength = mpi_reply->Header.PageLength;
+ cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
+ cm->cm_sge = &request->PageBufferSGE;
+ cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
+ cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
+ cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+ page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
+ if (!page) {
+ printf("%s: page alloc failed\n", __func__);
+ error = ENOMEM;
+ goto out;
+ }
+ cm->cm_data = page;
+
+ error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
+ reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
+ if (error || (reply == NULL)) {
+ /* FIXME */
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
+ printf("%s: request for page completed with error %d",
+ __func__, error);
+ error = ENXIO;
+ goto out;
+ }
+ ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+ bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ /* FIXME */
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
+ printf("%s: page read with error; iocstatus = 0x%x\n",
+ __func__, ioc_status);
+ error = ENXIO;
+ goto out;
+ }
+ bcopy(page, config_page, MIN(cm->cm_length,
+ (sizeof(Mpi2ManufacturingPage11_t))));
+
+out:
+ free(page, M_MPR);
+ if (cm)
+ mpr_free_command(sc, cm);
+ return (error);
+}
+
+/**
* mpr_base_static_config_pages - static start of day config pages.
* @sc: per adapter object
*
@@ -332,8 +463,9 @@ out:
void
mpr_base_static_config_pages(struct mpr_softc *sc)
{
- Mpi2ConfigReply_t mpi_reply;
- int retry;
+ Mpi2ConfigReply_t mpi_reply;
+ Mpi2ManufacturingPage11_t man_pg11;
+ int retry, rc;
retry = 0;
while (mpr_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
@@ -353,6 +485,29 @@ mpr_base_static_config_pages(struct mpr_softc *sc)
break;
}
}
+ retry = 0;
+ while ((rc = mpr_config_get_man_pg11(sc, &mpi_reply, &man_pg11))) {
+ retry++;
+ if (retry > 5) {
+ /* We need to Handle this situation */
+ /*FIXME*/
+ break;
+ }
+ }
+
+ if (!rc) {
+ sc->custom_nvme_tm_handling = (le16toh(man_pg11.AddlFlags2) &
+ MPI2_MAN_PG11_ADDLFLAGS2_CUSTOM_TM_HANDLING_MASK);
+ sc->nvme_abort_timeout = man_pg11.NVMeAbortTO;
+
+ /* Minimum NVMe Abort timeout value should be 6 seconds &
+ * maximum value should be 60 seconds.
+ */
+ if (sc->nvme_abort_timeout < 6)
+ sc->nvme_abort_timeout = 6;
+ if (sc->nvme_abort_timeout > 60)
+ sc->nvme_abort_timeout = 60;
+ }
}
/**
diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c
index 82116e263d82..f76703a5cb26 100644
--- a/sys/dev/mpr/mpr_sas.c
+++ b/sys/dev/mpr/mpr_sas.c
@@ -470,8 +470,14 @@ mprsas_prepare_volume_remove(struct mprsas_softc *sassc, uint16_t handle)
req->DevHandle = targ->handle;
req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
- /* SAS Hard Link Reset / SATA Link Reset */
- req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
+ if (!targ->is_nvme || sc->custom_nvme_tm_handling) {
+ /* SAS Hard Link Reset / SATA Link Reset */
+ req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
+ } else {
+ /* PCIe Protocol Level Reset*/
+ req->MsgFlags =
+ MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE;
+ }
cm->cm_targ = targ;
cm->cm_data = NULL;
@@ -1360,8 +1366,11 @@ mprsas_logical_unit_reset_complete(struct mpr_softc *sc, struct mpr_command *tm)
"logical unit reset complete for target %u, but still "
"have %u command(s), sending target reset\n", targ->tid,
cm_count);
- mprsas_send_reset(sc, tm,
- MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET);
+ if (!targ->is_nvme || sc->custom_nvme_tm_handling)
+ mprsas_send_reset(sc, tm,
+ MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET);
+ else
+ mpr_reinit(sc);
}
}
@@ -1449,7 +1458,7 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type)
{
MPI2_SCSI_TASK_MANAGE_REQUEST *req;
struct mprsas_target *target;
- int err;
+ int err, timeout;
target = tm->cm_targ;
if (target->handle == 0) {
@@ -1462,6 +1471,21 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type)
req->DevHandle = htole16(target->handle);
req->TaskType = type;
+ if (!target->is_nvme || sc->custom_nvme_tm_handling) {
+ timeout = MPR_RESET_TIMEOUT;
+ /*
+ * Target reset method =
+ * SAS Hard Link Reset / SATA Link Reset
+ */
+ req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
+ } else {
+ timeout = (target->controller_reset_timeout) ? (
+ target->controller_reset_timeout) : (MPR_RESET_TIMEOUT);
+ /* PCIe Protocol Level Reset*/
+ req->MsgFlags =
+ MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE;
+ }
+
if (type == MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET) {
/* XXX Need to handle invalid LUNs */
MPR_SET_LUN(req->LUN, tm->cm_lun);
@@ -1472,11 +1496,6 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type)
tm->cm_complete = mprsas_logical_unit_reset_complete;
mprsas_prepare_for_tm(sc, tm, target, tm->cm_lun);
} else if (type == MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
- /*
- * Target reset method =
- * SAS Hard Link Reset / SATA Link Reset
- */
- req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
tm->cm_targ->target_resets++;
mpr_dprint(sc, MPR_RECOVERY|MPR_INFO,
"Sending target reset to target %u\n", target->tid);
@@ -1498,7 +1517,7 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type)
tm->cm_data = NULL;
tm->cm_complete_data = (void *)tm;
- callout_reset(&tm->cm_callout, MPR_RESET_TIMEOUT * hz,
+ callout_reset(&tm->cm_callout, timeout * hz,
mprsas_tm_timeout, tm);
err = mpr_map_command(sc, tm);
@@ -1599,7 +1618,7 @@ mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm,
{
MPI2_SCSI_TASK_MANAGE_REQUEST *req;
struct mprsas_target *targ;
- int err;
+ int err, timeout;
targ = cm->cm_targ;
if (targ->handle == 0) {
@@ -1627,7 +1646,12 @@ mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm,
tm->cm_targ = cm->cm_targ;
tm->cm_lun = cm->cm_lun;
- callout_reset(&tm->cm_callout, MPR_ABORT_TIMEOUT * hz,
+ if (!targ->is_nvme || sc->custom_nvme_tm_handling)
+ timeout = MPR_ABORT_TIMEOUT;
+ else
+ timeout = sc->nvme_abort_timeout;
+
+ callout_reset(&tm->cm_callout, timeout * hz,
mprsas_tm_timeout, tm);
targ->aborts++;
@@ -3328,8 +3352,14 @@ mprsas_action_resetdev(struct mprsas_softc *sassc, union ccb *ccb)
req->DevHandle = htole16(targ->handle);
req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
- /* SAS Hard Link Reset / SATA Link Reset */
- req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
+ if (!targ->is_nvme || sc->custom_nvme_tm_handling) {
+ /* SAS Hard Link Reset / SATA Link Reset */
+ req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
+ } else {
+ /* PCIe Protocol Level Reset*/
+ req->MsgFlags =
+ MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE;
+ }
tm->cm_data = NULL;
tm->cm_complete = mprsas_resetdev_complete;
diff --git a/sys/dev/mpr/mpr_sas.h b/sys/dev/mpr/mpr_sas.h
index c2ab1e40d236..914099b2eb22 100644
--- a/sys/dev/mpr/mpr_sas.h
+++ b/sys/dev/mpr/mpr_sas.h
@@ -82,6 +82,7 @@ struct mprsas_target {
uint8_t supports_SSU;
uint8_t is_nvme;
uint32_t MDTS;
+ uint8_t controller_reset_timeout;
};
struct mprsas_softc {
diff --git a/sys/dev/mpr/mpr_sas_lsi.c b/sys/dev/mpr/mpr_sas_lsi.c
index f428e26df771..1664f03e41a6 100644
--- a/sys/dev/mpr/mpr_sas_lsi.c
+++ b/sys/dev/mpr/mpr_sas_lsi.c
@@ -683,6 +683,24 @@ skip_fp_send:
}
break;
}
+ case MPI2_EVENT_PCIE_DEVICE_STATUS_CHANGE:
+ {
+ pMpi26EventDataPCIeDeviceStatusChange_t pcie_status_event_data;
+ pcie_status_event_data =
+ (pMpi26EventDataPCIeDeviceStatusChange_t)fw_event->event_data;
+
+ switch (pcie_status_event_data->ReasonCode) {
+ case MPI26_EVENT_PCIDEV_STAT_RC_PCIE_HOT_RESET_FAILED:
+ {
+ mpr_printf(sc, "PCIe Host Reset failed on DevHandle "
+ "0x%x\n", pcie_status_event_data->DevHandle);
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+ }
case MPI2_EVENT_SAS_DEVICE_DISCOVERY_ERROR:
{
pMpi25EventDataSasDeviceDiscoveryError_t discovery_error_data;
@@ -1317,6 +1335,8 @@ mprsas_add_pcie_device(struct mpr_softc *sc, u16 handle, u8 linkrate)
targ->connector_name[3] = ((char *)&config_page.ConnectorName)[3];
targ->is_nvme = device_info & MPI26_PCIE_DEVINFO_NVME;
targ->MDTS = config_page2.MaximumDataTransferSize;
+ if (targ->is_nvme)
+ targ->controller_reset_timeout = config_page2.ControllerResetTO;
/*
* Assume always TRUE for encl_level_valid because there is no valid
* flag for PCIe.
diff --git a/sys/dev/mpr/mprvar.h b/sys/dev/mpr/mprvar.h
index 0bbc2ece599c..9c8b4892accf 100644
--- a/sys/dev/mpr/mprvar.h
+++ b/sys/dev/mpr/mprvar.h
@@ -97,6 +97,38 @@ typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
+typedef struct _MPI2_CONFIG_PAGE_MAN_11
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U8 FlashTime; /* 0x04 */
+ U8 NVTime; /* 0x05 */
+ U16 Flag; /* 0x06 */
+ U8 RFIoTimeout; /* 0x08 */
+ U8 EEDPTagMode; /* 0x09 */
+ U8 AWTValue; /* 0x0A */
+ U8 Reserve1; /* 0x0B */
+ U8 MaxCmdFrames; /* 0x0C */
+ U8 Reserve2; /* 0x0D */
+ U16 AddlFlags; /* 0x0E */
+ U32 SysRefClk; /* 0x10 */
+ U64 Reserve3[3]; /* 0x14 */
+ U16 AddlFlags2; /* 0x2C */
+ U8 AddlFlags3; /* 0x2E */
+ U8 Reserve4; /* 0x2F */
+ U64 opDebugEnable; /* 0x30 */
+ U64 PlDebugEnable; /* 0x38 */
+ U64 IrDebugEnable; /* 0x40 */
+ U32 BoardPowerRequirement; /* 0x48 */
+ U8 NVMeAbortTO; /* 0x4C */
+ U8 Reserve5; /* 0x4D */
+ U16 Reserve6; /* 0x4E */
+ U32 Reserve7[3]; /* 0x50 */
+} MPI2_CONFIG_PAGE_MAN_11,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_11,
+ Mpi2ManufacturingPage11_t, MPI2_POINTER pMpi2ManufacturingPage11_t;
+
+#define MPI2_MAN_PG11_ADDLFLAGS2_CUSTOM_TM_HANDLING_MASK (0x0010)
+
/**
* struct dev_mapping_table - device mapping information
* @physical_id: SAS address for drives or WWID for RAID volumes
@@ -471,6 +503,8 @@ struct mpr_softc {
char exclude_ids[80];
struct timeval lastfail;
+ uint8_t custom_nvme_tm_handling;
+ uint8_t nvme_abort_timeout;
};
struct mpr_config_params {
@@ -812,6 +846,8 @@ int mpr_config_get_volume_wwid(struct mpr_softc *sc, u16 volume_handle,
int mpr_config_get_raid_pd_pg0(struct mpr_softc *sc,
Mpi2ConfigReply_t *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page,
u32 page_address);
+int mpr_config_get_man_pg11(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
+ Mpi2ManufacturingPage11_t *config_page);
void mprsas_ir_shutdown(struct mpr_softc *sc, int howto);
int mpr_reinit(struct mpr_softc *sc);