From 6d4ffcb4acd13b34175df069e09e8d7920188bd4 Mon Sep 17 00:00:00 2001 From: "Kenneth D. Merry" Date: Thu, 10 Aug 2017 14:59:17 +0000 Subject: [PATCH] Changes to make mps(4) and mpr(4) handle reinit with reallocation. When the mps(4) and mpr(4) drivers need to reinitialize the firmware, they sometimes need to reallocate all of the memory allocated by the driver. The reallocation happens whenever the IOC Facts change. That should only happen after a firmware upgrade. If the reinitialization happens as a result of a timed out command sent to the card, the command that timed out and triggered the reinit may have been freed if iocfacts_allocate() reallocated all memory. If the caller attempts to access the command after that, the kernel will panic because the caller will be dereferencing freed memory. The solution is to set a flag in the softc when we reallocate, and avoid dereferencing the command strucure if we've reallocated. The changes are largely the same in both drivers, since mpr(4) is a derivative of mps(4). o In iocfacts_allocate(), if the IOC Facts have changed and we need to reallocate, set the REALLOCATED flag in the softc. o Change wait_command() to take a struct mps_command ** instead of a struct mps_command *. This allows us to NULL out the caller's command pointer if we have to reinit the controller and the data structures get reallocated. (The REALLOCATED flag will be set in the softc if that has happened.) o In every place that calls wait_command(), make sure we handle the case where the command is NULL after the call. o The mpr(4) driver has mpr_request_polled() which can also reinitialize the card. Also check for reallocation there. Reviewed by: scottl, slm MFC after: 1 week Sponsored by: Spectra Logic --- sys/dev/mpr/mpr.c | 53 +++++++++++++----- sys/dev/mpr/mpr_config.c | 114 +++++++++++++++++++++++--------------- sys/dev/mpr/mpr_sas.c | 7 +-- sys/dev/mpr/mpr_sas_lsi.c | 16 ++++-- sys/dev/mpr/mpr_user.c | 41 ++++++++------ sys/dev/mpr/mprvar.h | 5 +- sys/dev/mps/mps.c | 30 +++++++--- sys/dev/mps/mps_config.c | 108 +++++++++++++++++++++--------------- sys/dev/mps/mps_sas.c | 7 +-- sys/dev/mps/mps_sas_lsi.c | 13 +++-- sys/dev/mps/mps_user.c | 38 +++++++------ sys/dev/mps/mpsvar.h | 3 +- 12 files changed, 262 insertions(+), 173 deletions(-) diff --git a/sys/dev/mpr/mpr.c b/sys/dev/mpr/mpr.c index eead6b572b0c..7b04d541d7c5 100644 --- a/sys/dev/mpr/mpr.c +++ b/sys/dev/mpr/mpr.c @@ -436,6 +436,8 @@ mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching) /* Only deallocate and reallocate if relevant IOC Facts have changed */ reallocating = FALSE; + sc->mpr_flags &= ~MPR_FLAGS_REALLOCATED; + if ((!attaching) && ((saved_facts.MsgVersion != sc->facts->MsgVersion) || (saved_facts.HeaderVersion != sc->facts->HeaderVersion) || @@ -458,6 +460,9 @@ mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching) (saved_facts.MaxPersistentEntries != sc->facts->MaxPersistentEntries))) { reallocating = TRUE; + + /* Record that we reallocated everything */ + sc->mpr_flags |= MPR_FLAGS_REALLOCATED; } /* @@ -2229,8 +2234,8 @@ mpr_update_events(struct mpr_softc *sc, struct mpr_event_handle *handle, uint8_t *mask) { MPI2_EVENT_NOTIFICATION_REQUEST *evtreq; - MPI2_EVENT_NOTIFICATION_REPLY *reply; - struct mpr_command *cm; + MPI2_EVENT_NOTIFICATION_REPLY *reply = NULL; + struct mpr_command *cm = NULL; struct mpr_event_handle *eh; int error, i; @@ -2263,8 +2268,9 @@ mpr_update_events(struct mpr_softc *sc, struct mpr_event_handle *handle, cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; - error = mpr_request_polled(sc, cm); - reply = (MPI2_EVENT_NOTIFICATION_REPLY *)cm->cm_reply; + error = mpr_request_polled(sc, &cm); + if (cm != NULL) + reply = (MPI2_EVENT_NOTIFICATION_REPLY *)cm->cm_reply; if ((reply == NULL) || (reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) error = ENXIO; @@ -2274,7 +2280,8 @@ mpr_update_events(struct mpr_softc *sc, struct mpr_event_handle *handle, mpr_dprint(sc, MPR_TRACE, "%s finished error %d\n", __func__, error); - mpr_free_command(sc, cm); + if (cm != NULL) + mpr_free_command(sc, cm); return (error); } @@ -3260,11 +3267,12 @@ mpr_map_command(struct mpr_softc *sc, struct mpr_command *cm) * be executed and enqueued automatically. Other errors come from msleep(). */ int -mpr_wait_command(struct mpr_softc *sc, struct mpr_command *cm, int timeout, +mpr_wait_command(struct mpr_softc *sc, struct mpr_command **cmp, int timeout, int sleep_flag) { int error, rc; struct timeval cur_time, start_time; + struct mpr_command *cm = *cmp; if (sc->mpr_flags & MPR_FLAGS_DIAGRESET) return EBUSY; @@ -3319,6 +3327,13 @@ mpr_wait_command(struct mpr_softc *sc, struct mpr_command *cm, int timeout, rc = mpr_reinit(sc); mpr_dprint(sc, MPR_FAULT, "Reinit %s\n", (rc == 0) ? "success" : "failed"); + if (sc->mpr_flags & MPR_FLAGS_REALLOCATED) { + /* + * Tell the caller that we freed the command in a + * reinit. + */ + *cmp = NULL; + } error = ETIMEDOUT; } return (error); @@ -3329,10 +3344,11 @@ mpr_wait_command(struct mpr_softc *sc, struct mpr_command *cm, int timeout, * completion. Its use should be rare. */ int -mpr_request_polled(struct mpr_softc *sc, struct mpr_command *cm) +mpr_request_polled(struct mpr_softc *sc, struct mpr_command **cmp) { - int error, timeout = 0, rc; + int error, rc; struct timeval cur_time, start_time; + struct mpr_command *cm = *cmp; error = 0; @@ -3340,7 +3356,7 @@ mpr_request_polled(struct mpr_softc *sc, struct mpr_command *cm) cm->cm_complete = NULL; mpr_map_command(sc, cm); - getmicrotime(&start_time); + getmicrouptime(&start_time); while ((cm->cm_flags & MPR_CM_FLAGS_COMPLETE) == 0) { mpr_intr_locked(sc); @@ -3353,9 +3369,9 @@ mpr_request_polled(struct mpr_softc *sc, struct mpr_command *cm) /* * Check for real-time timeout and fail if more than 60 seconds. */ - getmicrotime(&cur_time); - timeout = cur_time.tv_sec - start_time.tv_sec; - if (timeout > 60) { + getmicrouptime(&cur_time); + timevalsub(&cur_time, &start_time); + if (cur_time.tv_sec > 60) { mpr_dprint(sc, MPR_FAULT, "polling failed\n"); error = ETIMEDOUT; break; @@ -3367,6 +3383,14 @@ mpr_request_polled(struct mpr_softc *sc, struct mpr_command *cm) rc = mpr_reinit(sc); mpr_dprint(sc, MPR_FAULT, "Reinit %s\n", (rc == 0) ? "success" : "failed"); + + if (sc->mpr_flags & MPR_FLAGS_REALLOCATED) { + /* + * Tell the caller that we freed the command in a + * reinit. + */ + *cmp = NULL; + } } return (error); } @@ -3432,11 +3456,12 @@ mpr_read_config_page(struct mpr_softc *sc, struct mpr_config_params *params) cm->cm_complete = mpr_config_complete; return (mpr_map_command(sc, cm)); } else { - error = mpr_wait_command(sc, cm, 0, CAN_SLEEP); + error = mpr_wait_command(sc, &cm, 0, CAN_SLEEP); if (error) { mpr_dprint(sc, MPR_FAULT, "Error %d reading config page\n", error); - mpr_free_command(sc, cm); + if (cm != NULL) + mpr_free_command(sc, cm); return (error); } mpr_config_complete(sc, cm); diff --git a/sys/dev/mpr/mpr_config.c b/sys/dev/mpr/mpr_config.c index 1ae070056159..9f1ed1d0f566 100644 --- a/sys/dev/mpr/mpr_config.c +++ b/sys/dev/mpr/mpr_config.c @@ -95,8 +95,9 @@ mpr_config_get_ioc_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 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; + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -153,8 +154,9 @@ mpr_config_get_ioc_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, } cm->cm_data = page; - error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -225,8 +227,9 @@ mpr_config_get_iounit_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 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; + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -283,8 +286,9 @@ mpr_config_get_iounit_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, } cm->cm_data = page; - error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -393,8 +397,9 @@ mpr_config_get_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 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; + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -453,8 +458,9 @@ mpr_config_get_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, goto out; } cm->cm_data = page; - error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -529,8 +535,9 @@ int mpr_config_set_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, request->PageAddress |= htole16(entry_idx); 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; + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -591,8 +598,9 @@ int mpr_config_set_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, bcopy(config_page, page, MIN(cm->cm_length, (sizeof(Mpi2DriverMappingPage0_t)))); cm->cm_data = page; - error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -664,8 +672,9 @@ mpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t request->ExtPageLength = 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; + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -724,8 +733,9 @@ mpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t } cm->cm_data = page; - error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -799,8 +809,9 @@ mpr_config_get_pcie_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t request->ExtPageLength = 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; + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -859,8 +870,9 @@ mpr_config_get_pcie_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t } cm->cm_data = page; - error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -934,8 +946,9 @@ mpr_config_get_pcie_device_pg2(struct mpr_softc *sc, Mpi2ConfigReply_t request->ExtPageLength = 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; + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -994,8 +1007,9 @@ mpr_config_get_pcie_device_pg2(struct mpr_softc *sc, Mpi2ConfigReply_t } cm->cm_data = page; - error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -1066,8 +1080,9 @@ mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 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; + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -1124,8 +1139,9 @@ mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, } cm->cm_data = page; - error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -1173,7 +1189,7 @@ mpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address) { MPI2_CONFIG_REQUEST *request; - MPI2_CONFIG_REPLY *reply; + MPI2_CONFIG_REPLY *reply = NULL; struct mpr_command *cm; Mpi2RaidVolPage0_t *page = NULL; int error = 0; @@ -1201,8 +1217,9 @@ mpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t * This page must be polled because the IOC isn't ready yet when this * page is needed. */ - error = mpr_request_polled(sc, cm); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mpr_request_polled(sc, &cm); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* If the poll returns error then we need to do diag reset */ @@ -1258,8 +1275,9 @@ mpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t * This page must be polled because the IOC isn't ready yet when this * page is needed. */ - error = mpr_request_polled(sc, cm); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mpr_request_polled(sc, &cm); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* If the poll returns error then we need to do diag reset */ @@ -1325,8 +1343,9 @@ mpr_config_get_raid_volume_pg1(struct mpr_softc *sc, Mpi2ConfigReply_t 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; + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -1384,8 +1403,9 @@ mpr_config_get_raid_volume_pg1(struct mpr_softc *sc, Mpi2ConfigReply_t } cm->cm_data = page; - error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -1459,7 +1479,7 @@ mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address) { MPI2_CONFIG_REQUEST *request; - MPI2_CONFIG_REPLY *reply; + MPI2_CONFIG_REPLY *reply = NULL; struct mpr_command *cm; Mpi2RaidPhysDiskPage0_t *page = NULL; int error = 0; @@ -1487,8 +1507,9 @@ mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, * This page must be polled because the IOC isn't ready yet when this * page is needed. */ - error = mpr_request_polled(sc, cm); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mpr_request_polled(sc, &cm); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* If the poll returns error then we need to do diag reset */ @@ -1544,8 +1565,9 @@ mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, * This page must be polled because the IOC isn't ready yet when this * page is needed. */ - error = mpr_request_polled(sc, cm); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mpr_request_polled(sc, &cm); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* If the poll returns error then we need to do diag reset */ diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c index e724bd43086c..bdaa4abe5819 100644 --- a/sys/dev/mpr/mpr_sas.c +++ b/sys/dev/mpr/mpr_sas.c @@ -1193,13 +1193,8 @@ mprsas_complete_all_commands(struct mpr_softc *sc) completed = 1; } - if (cm->cm_sc->io_cmds_active != 0) { + if (cm->cm_sc->io_cmds_active != 0) cm->cm_sc->io_cmds_active--; - } else { - mpr_dprint(cm->cm_sc, MPR_INFO, "Warning: " - "io_cmds_active is out of sync - resynching to " - "0\n"); - } if ((completed == 0) && (cm->cm_state != MPR_CM_STATE_FREE)) { /* this should never happen, but if it does, log */ diff --git a/sys/dev/mpr/mpr_sas_lsi.c b/sys/dev/mpr/mpr_sas_lsi.c index 5f7a4c6dd43c..2d346d56199e 100644 --- a/sys/dev/mpr/mpr_sas_lsi.c +++ b/sys/dev/mpr/mpr_sas_lsi.c @@ -324,7 +324,7 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) { // build RAID Action message Mpi2RaidActionRequest_t *action; - Mpi2RaidActionReply_t *reply; + Mpi2RaidActionReply_t *reply = NULL; struct mpr_command *cm; int error = 0; if ((cm = mpr_alloc_command(sc)) == NULL) { @@ -344,8 +344,10 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) action->PhysDiskNum = element->PhysDiskNum; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; - error = mpr_request_polled(sc, cm); - reply = (Mpi2RaidActionReply_t *)cm->cm_reply; + error = mpr_request_polled(sc, &cm); + if (cm != NULL) + reply = (Mpi2RaidActionReply_t *) + cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -1132,12 +1134,14 @@ mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, "command\n", __func__); callout_reset(&cm->cm_callout, MPR_ATA_ID_TIMEOUT * hz, mprsas_ata_id_timeout, cm); - error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); + error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); mpr_dprint(sc, MPR_XINFO, "%s stop timeout counter for SATA ID " "command\n", __func__); + /* XXX KDM need to fix the case where this command is destroyed */ callout_stop(&cm->cm_callout); - reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply; + if (cm != NULL) + reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -1603,7 +1607,7 @@ mprsas_ir_shutdown(struct mpr_softc *sc) action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; mpr_lock(sc); - mpr_wait_command(sc, cm, 5, CAN_SLEEP); + mpr_wait_command(sc, &cm, 5, CAN_SLEEP); mpr_unlock(sc); /* diff --git a/sys/dev/mpr/mpr_user.c b/sys/dev/mpr/mpr_user.c index 750b126368b8..fb9a0ba0ceff 100644 --- a/sys/dev/mpr/mpr_user.c +++ b/sys/dev/mpr/mpr_user.c @@ -652,7 +652,7 @@ static int mpr_user_command(struct mpr_softc *sc, struct mpr_usr_command *cmd) { MPI2_REQUEST_HEADER *hdr; - MPI2_DEFAULT_REPLY *rpl; + MPI2_DEFAULT_REPLY *rpl = NULL; void *buf = NULL; struct mpr_command *cm = NULL; int err = 0; @@ -664,7 +664,7 @@ mpr_user_command(struct mpr_softc *sc, struct mpr_usr_command *cmd) if (cm == NULL) { mpr_printf(sc, "%s: no mpr requests\n", __func__); err = ENOMEM; - goto Ret; + goto RetFree; } mpr_unlock(sc); @@ -706,15 +706,16 @@ mpr_user_command(struct mpr_softc *sc, struct mpr_usr_command *cmd) goto RetFreeUnlocked; mpr_lock(sc); - err = mpr_wait_command(sc, cm, 30, CAN_SLEEP); + err = mpr_wait_command(sc, &cm, 30, CAN_SLEEP); - if (err) { + if (err || (cm == NULL)) { mpr_printf(sc, "%s: invalid request: error %d\n", __func__, err); - goto Ret; + goto RetFree; } - rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply; + if (cm != NULL) + rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply; if (rpl != NULL) sz = rpl->MsgLength * 4; else @@ -734,9 +735,9 @@ mpr_user_command(struct mpr_softc *sc, struct mpr_usr_command *cmd) RetFreeUnlocked: mpr_lock(sc); +RetFree: if (cm != NULL) mpr_free_command(sc, cm); -Ret: mpr_unlock(sc); if (buf != NULL) free(buf, M_MPRUSER); @@ -850,7 +851,7 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data) err = 1; } else { mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); - err = mpr_wait_command(sc, cm, 30, CAN_SLEEP); + err = mpr_wait_command(sc, &cm, 30, CAN_SLEEP); } if (err != 0) { @@ -861,7 +862,7 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data) /* * Copy the reply data and sense data to user space. */ - if (cm->cm_reply != NULL) { + if ((cm != NULL) && (cm->cm_reply != NULL)) { rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply; sz = rpl->MsgLength * 4; @@ -1054,13 +1055,12 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data) mpr_lock(sc); - err = mpr_wait_command(sc, cm, 30, CAN_SLEEP); + err = mpr_wait_command(sc, &cm, 30, CAN_SLEEP); - if (err) { + if (err || (cm == NULL)) { mpr_printf(sc, "%s: invalid request: error %d\n", __func__, err); - mpr_unlock(sc); - goto RetFreeUnlocked; + goto RetFree; } /* @@ -1153,6 +1153,7 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data) RetFreeUnlocked: mpr_lock(sc); +RetFree: if (cm != NULL) { if (cm->cm_data) free(cm->cm_data, M_MPRUSER); @@ -1301,8 +1302,8 @@ mpr_post_fw_diag_buffer(struct mpr_softc *sc, /* * Send command synchronously. */ - status = mpr_wait_command(sc, cm, 30, CAN_SLEEP); - if (status) { + status = mpr_wait_command(sc, &cm, 30, CAN_SLEEP); + if (status || (cm == NULL)) { mpr_printf(sc, "%s: invalid request: error %d\n", __func__, status); status = MPR_DIAG_FAILURE; @@ -1333,7 +1334,8 @@ mpr_post_fw_diag_buffer(struct mpr_softc *sc, status = MPR_DIAG_SUCCESS; done: - mpr_free_command(sc, cm); + if (cm != NULL) + mpr_free_command(sc, cm); return (status); } @@ -1387,8 +1389,8 @@ mpr_release_fw_diag_buffer(struct mpr_softc *sc, /* * Send command synchronously. */ - status = mpr_wait_command(sc, cm, 30, CAN_SLEEP); - if (status) { + status = mpr_wait_command(sc, &cm, 30, CAN_SLEEP); + if (status || (cm == NULL)) { mpr_printf(sc, "%s: invalid request: error %d\n", __func__, status); status = MPR_DIAG_FAILURE; @@ -1423,6 +1425,9 @@ mpr_release_fw_diag_buffer(struct mpr_softc *sc, } done: + if (cm != NULL) + mpr_free_command(sc, cm); + return (status); } diff --git a/sys/dev/mpr/mprvar.h b/sys/dev/mpr/mprvar.h index bab76604549f..fd16bef30fed 100644 --- a/sys/dev/mpr/mprvar.h +++ b/sys/dev/mpr/mprvar.h @@ -275,6 +275,7 @@ struct mpr_softc { #define MPR_FLAGS_DIAGRESET (1 << 4) #define MPR_FLAGS_ATTACH_DONE (1 << 5) #define MPR_FLAGS_GEN35_IOC (1 << 6) +#define MPR_FLAGS_REALLOCATED (1 << 7) u_int mpr_debug; u_int disable_msix; u_int disable_msi; @@ -732,9 +733,9 @@ void mprsas_record_event(struct mpr_softc *sc, MPI2_EVENT_NOTIFICATION_REPLY *event_reply); int mpr_map_command(struct mpr_softc *sc, struct mpr_command *cm); -int mpr_wait_command(struct mpr_softc *sc, struct mpr_command *cm, int timeout, +int mpr_wait_command(struct mpr_softc *sc, struct mpr_command **cm, int timeout, int sleep_flag); -int mpr_request_polled(struct mpr_softc *sc, struct mpr_command *cm); +int mpr_request_polled(struct mpr_softc *sc, struct mpr_command **cm); int mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage3_t *config_page); diff --git a/sys/dev/mps/mps.c b/sys/dev/mps/mps.c index 378cb044e66a..56cb61d8483a 100644 --- a/sys/dev/mps/mps.c +++ b/sys/dev/mps/mps.c @@ -427,6 +427,8 @@ mps_iocfacts_allocate(struct mps_softc *sc, uint8_t attaching) /* Only deallocate and reallocate if relevant IOC Facts have changed */ reallocating = FALSE; + sc->mps_flags &= ~MPS_FLAGS_REALLOCATED; + if ((!attaching) && ((saved_facts.MsgVersion != sc->facts->MsgVersion) || (saved_facts.HeaderVersion != sc->facts->HeaderVersion) || @@ -447,6 +449,9 @@ mps_iocfacts_allocate(struct mps_softc *sc, uint8_t attaching) (saved_facts.MaxPersistentEntries != sc->facts->MaxPersistentEntries))) { reallocating = TRUE; + + /* Record that we reallocated everything */ + sc->mps_flags |= MPS_FLAGS_REALLOCATED; } /* @@ -2075,7 +2080,7 @@ mps_update_events(struct mps_softc *sc, struct mps_event_handle *handle, u32 *mask) { MPI2_EVENT_NOTIFICATION_REQUEST *evtreq; - MPI2_EVENT_NOTIFICATION_REPLY *reply; + MPI2_EVENT_NOTIFICATION_REPLY *reply = NULL; struct mps_command *cm; int error, i; @@ -2113,8 +2118,9 @@ mps_update_events(struct mps_softc *sc, struct mps_event_handle *handle, cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; - error = mps_wait_command(sc, cm, 60, 0); - reply = (MPI2_EVENT_NOTIFICATION_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, 0); + if (cm != NULL) + reply = (MPI2_EVENT_NOTIFICATION_REPLY *)cm->cm_reply; if ((reply == NULL) || (reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) error = ENXIO; @@ -2124,7 +2130,8 @@ mps_update_events(struct mps_softc *sc, struct mps_event_handle *handle, mps_dprint(sc, MPS_TRACE, "%s finished error %d\n", __func__, error); - mps_free_command(sc, cm); + if (cm != NULL) + mps_free_command(sc, cm); return (error); } @@ -2530,11 +2537,12 @@ mps_map_command(struct mps_softc *sc, struct mps_command *cm) * be executed and enqueued automatically. Other errors come from msleep(). */ int -mps_wait_command(struct mps_softc *sc, struct mps_command *cm, int timeout, +mps_wait_command(struct mps_softc *sc, struct mps_command **cmp, int timeout, int sleep_flag) { int error, rc; struct timeval cur_time, start_time; + struct mps_command *cm = *cmp; if (sc->mps_flags & MPS_FLAGS_DIAGRESET) return EBUSY; @@ -2588,6 +2596,13 @@ mps_wait_command(struct mps_softc *sc, struct mps_command *cm, int timeout, rc = mps_reinit(sc); mps_dprint(sc, MPS_FAULT, "Reinit %s\n", (rc == 0) ? "success" : "failed"); + if (sc->mps_flags & MPS_FLAGS_REALLOCATED) { + /* + * Tell the caller that we freed the command in a + * reinit. + */ + *cmp = NULL; + } error = ETIMEDOUT; } return (error); @@ -2654,11 +2669,12 @@ mps_read_config_page(struct mps_softc *sc, struct mps_config_params *params) cm->cm_complete = mps_config_complete; return (mps_map_command(sc, cm)); } else { - error = mps_wait_command(sc, cm, 0, CAN_SLEEP); + error = mps_wait_command(sc, &cm, 0, CAN_SLEEP); if (error) { mps_dprint(sc, MPS_FAULT, "Error %d reading config page\n", error); - mps_free_command(sc, cm); + if (cm != NULL) + mps_free_command(sc, cm); return (error); } mps_config_complete(sc, cm); diff --git a/sys/dev/mps/mps_config.c b/sys/dev/mps/mps_config.c index e435d4f83d67..cfaf0a472f6a 100644 --- a/sys/dev/mps/mps_config.c +++ b/sys/dev/mps/mps_config.c @@ -71,7 +71,7 @@ mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page) { MPI2_CONFIG_REQUEST *request; - MPI2_CONFIG_REPLY *reply; + MPI2_CONFIG_REPLY *reply = NULL; struct mps_command *cm; MPI2_CONFIG_PAGE_IOC_8 *page = NULL; int error = 0; @@ -94,8 +94,9 @@ mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; - error = mps_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -152,8 +153,9 @@ mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, } cm->cm_data = page; - error = mps_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -200,7 +202,7 @@ int mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply) { MPI2_CONFIG_REQUEST *request; - MPI2_CONFIG_REPLY *reply; + MPI2_CONFIG_REPLY *reply = NULL; struct mps_command *cm; pMpi2ManufacturingPagePS_t page = NULL; uint32_t *pPS_info; @@ -230,8 +232,9 @@ mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply) * This page must be polled because the IOC isn't ready yet when this * page is needed. */ - error = mps_wait_command(sc, cm, 60, 0); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, 0); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* If the poll returns error then we need to do diag reset */ @@ -286,8 +289,9 @@ mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply) * This page must be polled because the IOC isn't ready yet when this * page is needed. */ - error = mps_wait_command(sc, cm, 60, 0); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, 0); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* If the poll returns error then we need to do diag reset */ @@ -559,7 +563,7 @@ mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, Mpi2DriverMappingPage0_t *config_page, u16 sz) { MPI2_CONFIG_REQUEST *request; - MPI2_CONFIG_REPLY *reply; + MPI2_CONFIG_REPLY *reply = NULL; struct mps_command *cm; Mpi2DriverMappingPage0_t *page = NULL; int error = 0; @@ -586,8 +590,9 @@ mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; - error = mps_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -646,8 +651,9 @@ mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, goto out; } cm->cm_data = page; - error = mps_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -695,7 +701,7 @@ int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, Mpi2DriverMappingPage0_t *config_page, u16 entry_idx) { MPI2_CONFIG_REQUEST *request; - MPI2_CONFIG_REPLY *reply; + MPI2_CONFIG_REPLY *reply = NULL; struct mps_command *cm; MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL; int error = 0; @@ -722,8 +728,9 @@ int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, request->PageAddress |= htole16(entry_idx); cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; - error = mps_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -784,8 +791,9 @@ int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, bcopy(config_page, page, MIN(cm->cm_length, (sizeof(Mpi2DriverMappingPage0_t)))); cm->cm_data = page; - error = mps_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -833,7 +841,7 @@ mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle) { MPI2_CONFIG_REQUEST *request; - MPI2_CONFIG_REPLY *reply; + MPI2_CONFIG_REPLY *reply = NULL; struct mps_command *cm; Mpi2SasDevicePage0_t *page = NULL; int error = 0; @@ -857,8 +865,9 @@ mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; - error = mps_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -917,8 +926,9 @@ mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t } cm->cm_data = page; - error = mps_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -966,7 +976,7 @@ mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage3_t *config_page) { MPI2_CONFIG_REQUEST *request; - MPI2_CONFIG_REPLY *reply; + MPI2_CONFIG_REPLY *reply = NULL; struct mps_command *cm; Mpi2BiosPage3_t *page = NULL; int error = 0; @@ -989,8 +999,9 @@ mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; - error = mps_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -1047,8 +1058,9 @@ mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, } cm->cm_data = page; - error = mps_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -1096,7 +1108,7 @@ mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address) { MPI2_CONFIG_REQUEST *request; - MPI2_CONFIG_REPLY *reply; + MPI2_CONFIG_REPLY *reply = NULL; struct mps_command *cm; Mpi2RaidVolPage0_t *page = NULL; int error = 0; @@ -1124,8 +1136,9 @@ mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t * This page must be polled because the IOC isn't ready yet when this * page is needed. */ - error = mps_wait_command(sc, cm, 60, 0); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, 0); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* If the poll returns error then we need to do diag reset */ @@ -1181,8 +1194,9 @@ mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t * This page must be polled because the IOC isn't ready yet when this * page is needed. */ - error = mps_wait_command(sc, cm, 60, 0); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, 0); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* If the poll returns error then we need to do diag reset */ @@ -1225,7 +1239,7 @@ mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle) { MPI2_CONFIG_REQUEST *request; - MPI2_CONFIG_REPLY *reply; + MPI2_CONFIG_REPLY *reply = NULL; struct mps_command *cm; Mpi2RaidVolPage1_t *page = NULL; int error = 0; @@ -1248,8 +1262,9 @@ mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; - error = mps_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -1307,8 +1322,9 @@ mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t } cm->cm_data = page; - error = mps_wait_command(sc, cm, 60, CAN_SLEEP); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -1382,7 +1398,7 @@ mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address) { MPI2_CONFIG_REQUEST *request; - MPI2_CONFIG_REPLY *reply; + MPI2_CONFIG_REPLY *reply = NULL; struct mps_command *cm; Mpi2RaidPhysDiskPage0_t *page = NULL; int error = 0; @@ -1410,8 +1426,9 @@ mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, * This page must be polled because the IOC isn't ready yet when this * page is needed. */ - error = mps_wait_command(sc, cm, 60, 0); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, 0); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* If the poll returns error then we need to do diag reset */ @@ -1467,8 +1484,9 @@ mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, * This page must be polled because the IOC isn't ready yet when this * page is needed. */ - error = mps_wait_command(sc, cm, 60, 0); - reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; + error = mps_wait_command(sc, &cm, 60, 0); + if (cm != NULL) + reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* If the poll returns error then we need to do diag reset */ diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c index be864effc69f..c09df175425d 100644 --- a/sys/dev/mps/mps_sas.c +++ b/sys/dev/mps/mps_sas.c @@ -1131,13 +1131,8 @@ mpssas_complete_all_commands(struct mps_softc *sc) completed = 1; } - if (cm->cm_sc->io_cmds_active != 0) { + if (cm->cm_sc->io_cmds_active != 0) cm->cm_sc->io_cmds_active--; - } else { - mps_dprint(cm->cm_sc, MPS_INFO, "Warning: " - "io_cmds_active is out of sync - resynching to " - "0\n"); - } if ((completed == 0) && (cm->cm_state != MPS_CM_STATE_FREE)) { /* this should never happen, but if it does, log */ diff --git a/sys/dev/mps/mps_sas_lsi.c b/sys/dev/mps/mps_sas_lsi.c index 618d193bfedf..3d62a9a4bff5 100644 --- a/sys/dev/mps/mps_sas_lsi.c +++ b/sys/dev/mps/mps_sas_lsi.c @@ -915,7 +915,7 @@ mpssas_get_sata_identify(struct mps_softc *sc, u16 handle, Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, u32 devinfo) { Mpi2SataPassthroughRequest_t *mpi_request; - Mpi2SataPassthroughReply_t *reply; + Mpi2SataPassthroughReply_t *reply = NULL; struct mps_command *cm; char *buffer; int error = 0; @@ -957,12 +957,14 @@ mpssas_get_sata_identify(struct mps_softc *sc, u16 handle, "command\n", __func__); callout_reset(&cm->cm_callout, MPS_ATA_ID_TIMEOUT * hz, mpssas_ata_id_timeout, cm); - error = mps_wait_command(sc, cm, 60, CAN_SLEEP); + error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); mps_dprint(sc, MPS_XINFO, "%s stop timeout counter for SATA ID " "command\n", __func__); + /* XXX KDM need to fix the case where this command is destroyed */ callout_stop(&cm->cm_callout); - reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply; + if (cm != NULL) + reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* @@ -989,7 +991,8 @@ out: * it. The command will be freed after sending a target reset TM. If * the command did timeout, use EWOULDBLOCK. */ - if ((cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) == 0) + if ((cm != NULL) + && (cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) == 0) mps_free_command(sc, cm); else if (error == 0) error = EWOULDBLOCK; @@ -1285,7 +1288,7 @@ mpssas_ir_shutdown(struct mps_softc *sc) action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; mps_lock(sc); - mps_wait_command(sc, cm, 5, CAN_SLEEP); + mps_wait_command(sc, &cm, 5, CAN_SLEEP); mps_unlock(sc); /* diff --git a/sys/dev/mps/mps_user.c b/sys/dev/mps/mps_user.c index dc1ced14840f..c245efa969e9 100644 --- a/sys/dev/mps/mps_user.c +++ b/sys/dev/mps/mps_user.c @@ -677,7 +677,7 @@ mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd) if (cm == NULL) { mps_printf(sc, "%s: no mps requests\n", __func__); err = ENOMEM; - goto Ret; + goto RetFree; } mps_unlock(sc); @@ -719,12 +719,12 @@ mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd) goto RetFreeUnlocked; mps_lock(sc); - err = mps_wait_command(sc, cm, 60, CAN_SLEEP); + err = mps_wait_command(sc, &cm, 60, CAN_SLEEP); - if (err) { + if (err || (cm == NULL)) { mps_printf(sc, "%s: invalid request: error %d\n", __func__, err); - goto Ret; + goto RetFree; } rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply; @@ -747,9 +747,9 @@ mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd) RetFreeUnlocked: mps_lock(sc); +RetFree: if (cm != NULL) mps_free_command(sc, cm); -Ret: mps_unlock(sc); if (buf != NULL) free(buf, M_MPSUSER); @@ -760,7 +760,7 @@ static int mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data) { MPI2_REQUEST_HEADER *hdr, tmphdr; - MPI2_DEFAULT_REPLY *rpl; + MPI2_DEFAULT_REPLY *rpl = NULL; struct mps_command *cm = NULL; int err = 0, dir = 0, sz; uint8_t function = 0; @@ -861,7 +861,7 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data) err = 1; } else { mpssas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); - err = mps_wait_command(sc, cm, 30, CAN_SLEEP); + err = mps_wait_command(sc, &cm, 30, CAN_SLEEP); } if (err != 0) { @@ -872,7 +872,7 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data) /* * Copy the reply data and sense data to user space. */ - if (cm->cm_reply != NULL) { + if ((cm != NULL) && (cm->cm_reply != NULL)) { rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply; sz = rpl->MsgLength * 4; @@ -993,9 +993,9 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data) mps_lock(sc); - err = mps_wait_command(sc, cm, 30, CAN_SLEEP); + err = mps_wait_command(sc, &cm, 30, CAN_SLEEP); - if (err) { + if (err || (cm == NULL)) { mps_printf(sc, "%s: invalid request: error %d\n", __func__, err); mps_unlock(sc); @@ -1161,7 +1161,7 @@ mps_post_fw_diag_buffer(struct mps_softc *sc, mps_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code) { MPI2_DIAG_BUFFER_POST_REQUEST *req; - MPI2_DIAG_BUFFER_POST_REPLY *reply; + MPI2_DIAG_BUFFER_POST_REPLY *reply = NULL; struct mps_command *cm = NULL; int i, status; @@ -1208,8 +1208,8 @@ mps_post_fw_diag_buffer(struct mps_softc *sc, /* * Send command synchronously. */ - status = mps_wait_command(sc, cm, 30, CAN_SLEEP); - if (status) { + status = mps_wait_command(sc, &cm, 30, CAN_SLEEP); + if (status || (cm == NULL)) { mps_printf(sc, "%s: invalid request: error %d\n", __func__, status); status = MPS_DIAG_FAILURE; @@ -1240,7 +1240,8 @@ mps_post_fw_diag_buffer(struct mps_softc *sc, status = MPS_DIAG_SUCCESS; done: - mps_free_command(sc, cm); + if (cm != NULL) + mps_free_command(sc, cm); return (status); } @@ -1250,7 +1251,7 @@ mps_release_fw_diag_buffer(struct mps_softc *sc, uint32_t diag_type) { MPI2_DIAG_RELEASE_REQUEST *req; - MPI2_DIAG_RELEASE_REPLY *reply; + MPI2_DIAG_RELEASE_REPLY *reply = NULL; struct mps_command *cm = NULL; int status; @@ -1294,8 +1295,8 @@ mps_release_fw_diag_buffer(struct mps_softc *sc, /* * Send command synchronously. */ - status = mps_wait_command(sc, cm, 30, CAN_SLEEP); - if (status) { + status = mps_wait_command(sc, &cm, 30, CAN_SLEEP); + if (status || (cm == NULL)) { mps_printf(sc, "%s: invalid request: error %d\n", __func__, status); status = MPS_DIAG_FAILURE; @@ -1330,6 +1331,9 @@ mps_release_fw_diag_buffer(struct mps_softc *sc, } done: + if (cm != NULL) + mps_free_command(sc, cm); + return (status); } diff --git a/sys/dev/mps/mpsvar.h b/sys/dev/mps/mpsvar.h index b7cc549d3a96..b8d074a8e2bb 100644 --- a/sys/dev/mps/mpsvar.h +++ b/sys/dev/mps/mpsvar.h @@ -271,6 +271,7 @@ struct mps_softc { #define MPS_FLAGS_DIAGRESET (1 << 4) #define MPS_FLAGS_ATTACH_DONE (1 << 5) #define MPS_FLAGS_WD_AVAILABLE (1 << 6) +#define MPS_FLAGS_REALLOCATED (1 << 7) u_int mps_debug; u_int disable_msix; u_int disable_msi; @@ -697,7 +698,7 @@ void mpssas_record_event(struct mps_softc *sc, MPI2_EVENT_NOTIFICATION_REPLY *event_reply); int 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 mps_wait_command(struct mps_softc *sc, struct mps_command **cm, int timeout, int sleep_flag); int mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t