diff options
| author | Kashyap D Desai <kadesai@FreeBSD.org> | 2018-12-26 10:40:27 +0000 |
|---|---|---|
| committer | Kashyap D Desai <kadesai@FreeBSD.org> | 2018-12-26 10:40:27 +0000 |
| commit | 89d1c21f458d83a882c92a8a2b2b5be92cbdf2ec (patch) | |
| tree | e3e3fcec2ed4883a0d148fafd5fe77ff2ee56685 /sys/dev/mpr | |
| parent | 23daf8f40bd5665caf4871c8b21ab4cd1a09bb84 (diff) | |
Notes
Diffstat (limited to 'sys/dev/mpr')
| -rw-r--r-- | sys/dev/mpr/mpr_config.c | 159 | ||||
| -rw-r--r-- | sys/dev/mpr/mpr_sas.c | 60 | ||||
| -rw-r--r-- | sys/dev/mpr/mpr_sas.h | 1 | ||||
| -rw-r--r-- | sys/dev/mpr/mpr_sas_lsi.c | 20 | ||||
| -rw-r--r-- | sys/dev/mpr/mprvar.h | 36 |
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); |
