summaryrefslogtreecommitdiffstats
path: root/sys/dev/mps
diff options
context:
space:
mode:
authorken <ken@FreeBSD.org>2013-07-22 18:41:53 +0000
committerken <ken@FreeBSD.org>2013-07-22 18:41:53 +0000
commitba9cc3ab8526ced3a521b91f2a372d9962474fb0 (patch)
tree334176d6edbef84c24ecb7c3a9043fed3904a4e2 /sys/dev/mps
parent71b805798bf6d7e4be7d593becfe3bcd5c3bdbf6 (diff)
downloadFreeBSD-src-ba9cc3ab8526ced3a521b91f2a372d9962474fb0.zip
FreeBSD-src-ba9cc3ab8526ced3a521b91f2a372d9962474fb0.tar.gz
Merge in phase 14+ -> 16 mps driver fixes from LSI:
--------------------------------------------------------------- System panics during a Port reset with ouststanding I/O --------------------------------------------------------------- It is possible to call mps_mapping_free_memory after this memory is already freed, causing a panic. Removed this extra call to mps_mappiing_free_memory and call mps_mapping_exit in place of the mps_mapping_free_memory call so that any outstanding mapping items can be flushed before memory is freed. --------------------------------------------------------------- Correct memory leak during a Port reset with ouststanding I/O --------------------------------------------------------------- In mps_reinit function, the mapping memory was not being freed before being re-allocated. Added line to call the memory free function for mapping memory. --------------------------------------------------------------- Use CAM_SIM_QUEUED flag in Driver IO path. --------------------------------------------------------------- This flag informs the XPT that successful abort of a CCB requires an abort ccb to be issued to the SIM. While processing SCSI IO's, set the CAM_SIM_QUEUED flag in the status for the IO. When the command completes, clear this flag. --------------------------------------------------------------- Check for CAM_REQ_INPROG in I/O path. --------------------------------------------------------------- Added a check in mpssas_action_scsiio for the In Progress status for the IO. If this flag is set, the IO has already been aborted by the upper layer (before CAM_SIM_QUEUED was set) and there is no need to send the IO. The request will be completed without error. --------------------------------------------------------------- Improve "doorbell handshake method" for mps_get_iocfacts --------------------------------------------------------------- Removed call to get Port Facts since this information is not used currently. Added mps_iocfacts_allocate function to allocate memory that is based on IOC Facts data. Added mps_iocfacts_free function to free memory that is based on IOC Facts data. Both of the functions are used when a Diag Reset is performed or when the driver is attached/detached. This is needed in case IOC Facts changes after a Diag Reset, which could happen if FW is upgraded. Moved call of mps_bases_static_config_pages from the attach routine to after the IOC is ready to process accesses based on the new memory allocations (instead of polling through the Doorbell). --------------------------------------------------------------- Set TimeStamp in INIT message in millisecond format Set the IOC --------------------------------------------------------------- --------------------------------------------------------------- Prefer mps_wait_command to mps_request_polled --------------------------------------------------------------- Instead of using mps_request_polled, call mps_wait_command whenever possible. Change the mps_wait_command function to check the current context and either use interrupt context or poll if required by using the pause or DELAY function. Added a check after waiting 50mSecs to see if the command has timed out. This is only done if polliing, the msleep command will automatically timeout if the command has taken too long to complete. --------------------------------------------------------------- Integrated RAID: Volume Activation Failed error message is displayed though the volume has been activated. --------------------------------------------------------------- Instead of failing an IOCTL request that does not have a large enough buffer to hold the complete reply, copy as much data from the reply as possible into the user's buffer and log a message saying that the user's buffer was smaller than the returned data. --------------------------------------------------------------- mapping_add_new_device failure due to persistent table FULL --------------------------------------------------------------- When a new device is added, if it is determined that the device persistent table is being used and is full, instead of displaying a message for this condition every time, only log a message if the MPS_INFO bit is set in the debug_flags. Submitted by: LSI MFC after: 1 week
Diffstat (limited to 'sys/dev/mps')
-rw-r--r--sys/dev/mps/mps.c731
-rw-r--r--sys/dev/mps/mps_config.c197
-rw-r--r--sys/dev/mps/mps_mapping.c24
-rw-r--r--sys/dev/mps/mps_sas.c38
-rw-r--r--sys/dev/mps/mps_sas_lsi.c11
-rw-r--r--sys/dev/mps/mps_user.c71
-rw-r--r--sys/dev/mps/mpsvar.h6
7 files changed, 687 insertions, 391 deletions
diff --git a/sys/dev/mps/mps.c b/sys/dev/mps/mps.c
index 1bb693f..b6c549a 100644
--- a/sys/dev/mps/mps.c
+++ b/sys/dev/mps/mps.c
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/queue.h>
#include <sys/kthread.h>
+#include <sys/taskqueue.h>
#include <sys/endian.h>
#include <sys/eventhandler.h>
@@ -61,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcivar.h>
+#include <cam/cam.h>
#include <cam/scsi/scsi_all.h>
#include <dev/mps/mpi/mpi2_type.h>
@@ -73,13 +75,19 @@ __FBSDID("$FreeBSD$");
#include <dev/mps/mps_ioctl.h>
#include <dev/mps/mpsvar.h>
#include <dev/mps/mps_table.h>
+#include <dev/mps/mps_sas.h>
static int mps_diag_reset(struct mps_softc *sc, int sleep_flag);
static int mps_init_queues(struct mps_softc *sc);
static int mps_message_unit_reset(struct mps_softc *sc, int sleep_flag);
static int mps_transition_operational(struct mps_softc *sc);
+static int mps_iocfacts_allocate(struct mps_softc *sc, uint8_t attaching);
+static void mps_iocfacts_free(struct mps_softc *sc);
static void mps_startup(void *arg);
static int mps_send_iocinit(struct mps_softc *sc);
+static int mps_alloc_queues(struct mps_softc *sc);
+static int mps_alloc_replies(struct mps_softc *sc);
+static int mps_alloc_requests(struct mps_softc *sc);
static int mps_attach_log(struct mps_softc *sc);
static __inline void mps_complete_command(struct mps_softc *sc,
struct mps_command *cm);
@@ -89,6 +97,7 @@ static void mps_config_complete(struct mps_softc *sc, struct mps_command *cm);
static void mps_periodic(void *);
static int mps_reregister_events(struct mps_softc *sc);
static void mps_enqueue_request(struct mps_softc *sc, struct mps_command *cm);
+static int mps_get_iocfacts(struct mps_softc *sc, MPI2_IOC_FACTS_REPLY *facts);
static int mps_wait_db_ack(struct mps_softc *sc, int timeout, int sleep_flag);
SYSCTL_NODE(_hw, OID_AUTO, mps, CTLFLAG_RD, 0, "MPS Driver Parameters");
@@ -149,7 +158,8 @@ mps_diag_reset(struct mps_softc *sc,int sleep_flag)
mpt2_reset_magic[i]);
/* wait 100 msec */
if (mtx_owned(&sc->mps_mtx) && sleep_flag == CAN_SLEEP)
- msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0, "mpsdiag", hz/10);
+ msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0,
+ "mpsdiag", hz/10);
else if (sleep_flag == CAN_SLEEP)
pause("mpsdiag", hz/10);
else
@@ -173,7 +183,8 @@ mps_diag_reset(struct mps_softc *sc,int sleep_flag)
for (i = 0; i < 60000; i++) {
/* wait 50 msec */
if (mtx_owned(&sc->mps_mtx) && sleep_flag == CAN_SLEEP)
- msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0, "mpsdiag", hz/20);
+ msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0,
+ "mpsdiag", hz/20);
else if (sleep_flag == CAN_SLEEP)
pause("mpsdiag", hz/20);
else
@@ -303,9 +314,357 @@ mps_transition_operational(struct mps_softc *sc)
return (error);
}
+/*
+ * This is called during attach and when re-initializing due to a Diag Reset.
+ * IOC Facts is used to allocate many of the structures needed by the driver.
+ * If called from attach, de-allocation is not required because the driver has
+ * not allocated any structures yet, but if called from a Diag Reset, previously
+ * allocated structures based on IOC Facts will need to be freed and re-
+ * allocated bases on the latest IOC Facts.
+ */
+static int
+mps_iocfacts_allocate(struct mps_softc *sc, uint8_t attaching)
+{
+ int error, i;
+ Mpi2IOCFactsReply_t saved_facts;
+ uint8_t saved_mode, reallocating;
+ struct mpssas_lun *lun, *lun_tmp;
+ struct mpssas_target *targ;
+
+ mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+ /* Save old IOC Facts and then only reallocate if Facts have changed */
+ if (!attaching) {
+ bcopy(sc->facts, &saved_facts, sizeof(MPI2_IOC_FACTS_REPLY));
+ }
+
+ /*
+ * Get IOC Facts. In all cases throughout this function, panic if doing
+ * a re-initialization and only return the error if attaching so the OS
+ * can handle it.
+ */
+ if ((error = mps_get_iocfacts(sc, sc->facts)) != 0) {
+ if (attaching) {
+ mps_dprint(sc, MPS_FAULT, "%s failed to get IOC Facts "
+ "with error %d\n", __func__, error);
+ return (error);
+ } else {
+ panic("%s failed to get IOC Facts with error %d\n",
+ __func__, error);
+ }
+ }
+
+ mps_print_iocfacts(sc, sc->facts);
+
+ snprintf(sc->fw_version, sizeof(sc->fw_version),
+ "%02d.%02d.%02d.%02d",
+ sc->facts->FWVersion.Struct.Major,
+ sc->facts->FWVersion.Struct.Minor,
+ sc->facts->FWVersion.Struct.Unit,
+ sc->facts->FWVersion.Struct.Dev);
+
+ mps_printf(sc, "Firmware: %s, Driver: %s\n", sc->fw_version,
+ MPS_DRIVER_VERSION);
+ mps_printf(sc, "IOCCapabilities: %b\n", sc->facts->IOCCapabilities,
+ "\20" "\3ScsiTaskFull" "\4DiagTrace" "\5SnapBuf" "\6ExtBuf"
+ "\7EEDP" "\10BiDirTarg" "\11Multicast" "\14TransRetry" "\15IR"
+ "\16EventReplay" "\17RaidAccel" "\20MSIXIndex" "\21HostDisc");
+
+ /*
+ * If the chip doesn't support event replay then a hard reset will be
+ * required to trigger a full discovery. Do the reset here then
+ * retransition to Ready. A hard reset might have already been done,
+ * but it doesn't hurt to do it again. Only do this if attaching, not
+ * for a Diag Reset.
+ */
+ if (attaching) {
+ if ((sc->facts->IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY) == 0) {
+ mps_diag_reset(sc, NO_SLEEP);
+ if ((error = mps_transition_ready(sc)) != 0) {
+ mps_dprint(sc, MPS_FAULT, "%s failed to "
+ "transition to ready with error %d\n",
+ __func__, error);
+ return (error);
+ }
+ }
+ }
+
+ /*
+ * Set flag if IR Firmware is loaded. If the RAID Capability has
+ * changed from the previous IOC Facts, log a warning, but only if
+ * checking this after a Diag Reset and not during attach.
+ */
+ saved_mode = sc->ir_firmware;
+ if (sc->facts->IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID)
+ sc->ir_firmware = 1;
+ if (!attaching) {
+ if (sc->ir_firmware != saved_mode) {
+ mps_dprint(sc, MPS_FAULT, "%s new IR/IT mode in IOC "
+ "Facts does not match previous mode\n", __func__);
+ }
+ }
+
+ /* Only deallocate and reallocate if relevant IOC Facts have changed */
+ reallocating = FALSE;
+ if ((!attaching) &&
+ ((saved_facts.MsgVersion != sc->facts->MsgVersion) ||
+ (saved_facts.HeaderVersion != sc->facts->HeaderVersion) ||
+ (saved_facts.MaxChainDepth != sc->facts->MaxChainDepth) ||
+ (saved_facts.RequestCredit != sc->facts->RequestCredit) ||
+ (saved_facts.ProductID != sc->facts->ProductID) ||
+ (saved_facts.IOCCapabilities != sc->facts->IOCCapabilities) ||
+ (saved_facts.IOCRequestFrameSize !=
+ sc->facts->IOCRequestFrameSize) ||
+ (saved_facts.MaxTargets != sc->facts->MaxTargets) ||
+ (saved_facts.MaxSasExpanders != sc->facts->MaxSasExpanders) ||
+ (saved_facts.MaxEnclosures != sc->facts->MaxEnclosures) ||
+ (saved_facts.HighPriorityCredit != sc->facts->HighPriorityCredit) ||
+ (saved_facts.MaxReplyDescriptorPostQueueDepth !=
+ sc->facts->MaxReplyDescriptorPostQueueDepth) ||
+ (saved_facts.ReplyFrameSize != sc->facts->ReplyFrameSize) ||
+ (saved_facts.MaxVolumes != sc->facts->MaxVolumes) ||
+ (saved_facts.MaxPersistentEntries !=
+ sc->facts->MaxPersistentEntries))) {
+ reallocating = TRUE;
+ }
+
+ /*
+ * Some things should be done if attaching or re-allocating after a Diag
+ * Reset, but are not needed after a Diag Reset if the FW has not
+ * changed.
+ */
+ if (attaching || reallocating) {
+ /*
+ * Check if controller supports FW diag buffers and set flag to
+ * enable each type.
+ */
+ if (sc->facts->IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER)
+ sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_TRACE].
+ enabled = TRUE;
+ if (sc->facts->IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER)
+ sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_SNAPSHOT].
+ enabled = TRUE;
+ if (sc->facts->IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER)
+ sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_EXTENDED].
+ enabled = TRUE;
+
+ /*
+ * Set flag if EEDP is supported and if TLR is supported.
+ */
+ if (sc->facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP)
+ sc->eedp_enabled = TRUE;
+ if (sc->facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR)
+ sc->control_TLR = TRUE;
+
+ /*
+ * Size the queues. Since the reply queues always need one free
+ * entry, we'll just deduct one reply message here.
+ */
+ sc->num_reqs = MIN(MPS_REQ_FRAMES, sc->facts->RequestCredit);
+ sc->num_replies = MIN(MPS_REPLY_FRAMES + MPS_EVT_REPLY_FRAMES,
+ sc->facts->MaxReplyDescriptorPostQueueDepth) - 1;
+
+ /*
+ * Initialize all Tail Queues
+ */
+ TAILQ_INIT(&sc->req_list);
+ TAILQ_INIT(&sc->high_priority_req_list);
+ TAILQ_INIT(&sc->chain_list);
+ TAILQ_INIT(&sc->tm_list);
+ }
+
+ /*
+ * If doing a Diag Reset and the FW is significantly different
+ * (reallocating will be set above in IOC Facts comparison), then all
+ * buffers based on the IOC Facts will need to be freed before they are
+ * reallocated.
+ */
+ if (reallocating) {
+ mps_iocfacts_free(sc);
+
+ /*
+ * The number of targets is based on IOC Facts, so free all of
+ * the allocated LUNs for each target and then the target buffer
+ * itself.
+ */
+ for (i=0; i< saved_facts.MaxTargets; i++) {
+ targ = &sc->sassc->targets[i];
+ SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link,
+ lun_tmp) {
+ free(lun, M_MPT2);
+ }
+ }
+ free(sc->sassc->targets, M_MPT2);
+
+ sc->sassc->targets = malloc(sizeof(struct mpssas_target) *
+ sc->facts->MaxTargets, M_MPT2, M_WAITOK|M_ZERO);
+ if (!sc->sassc->targets) {
+ panic("%s failed to alloc targets with error %d\n",
+ __func__, ENOMEM);
+ }
+ }
+
+ /*
+ * Any deallocation has been completed. Now start reallocating
+ * if needed. Will only need to reallocate if attaching or if the new
+ * IOC Facts are different from the previous IOC Facts after a Diag
+ * Reset. Targets have already been allocated above if needed.
+ */
+ if (attaching || reallocating) {
+ if (((error = mps_alloc_queues(sc)) != 0) ||
+ ((error = mps_alloc_replies(sc)) != 0) ||
+ ((error = mps_alloc_requests(sc)) != 0)) {
+ if (attaching ) {
+ mps_dprint(sc, MPS_FAULT, "%s failed to alloc "
+ "queues with error %d\n", __func__, error);
+ mps_free(sc);
+ return (error);
+ } else {
+ panic("%s failed to alloc queues with error "
+ "%d\n", __func__, error);
+ }
+ }
+ }
+
+ /* Always initialize the queues */
+ bzero(sc->free_queue, sc->fqdepth * 4);
+ mps_init_queues(sc);
+
+ /*
+ * Always get the chip out of the reset state, but only panic if not
+ * attaching. If attaching and there is an error, that is handled by
+ * the OS.
+ */
+ error = mps_transition_operational(sc);
+ if (error != 0) {
+ if (attaching) {
+ mps_printf(sc, "%s failed to transition to operational "
+ "with error %d\n", __func__, error);
+ mps_free(sc);
+ return (error);
+ } else {
+ panic("%s failed to transition to operational with "
+ "error %d\n", __func__, error);
+ }
+ }
+
+ /*
+ * Finish the queue initialization.
+ * These are set here instead of in mps_init_queues() because the
+ * IOC resets these values during the state transition in
+ * mps_transition_operational(). The free index is set to 1
+ * because the corresponding index in the IOC is set to 0, and the
+ * IOC treats the queues as full if both are set to the same value.
+ * Hence the reason that the queue can't hold all of the possible
+ * replies.
+ */
+ sc->replypostindex = 0;
+ mps_regwrite(sc, MPI2_REPLY_FREE_HOST_INDEX_OFFSET, sc->replyfreeindex);
+ mps_regwrite(sc, MPI2_REPLY_POST_HOST_INDEX_OFFSET, 0);
+
+ /*
+ * Attach the subsystems so they can prepare their event masks.
+ */
+ /* XXX Should be dynamic so that IM/IR and user modules can attach */
+ if (attaching) {
+ if (((error = mps_attach_log(sc)) != 0) ||
+ ((error = mps_attach_sas(sc)) != 0) ||
+ ((error = mps_attach_user(sc)) != 0)) {
+ mps_printf(sc, "%s failed to attach all subsystems: "
+ "error %d\n", __func__, error);
+ mps_free(sc);
+ return (error);
+ }
+
+ if ((error = mps_pci_setup_interrupts(sc)) != 0) {
+ mps_printf(sc, "%s failed to setup interrupts\n",
+ __func__);
+ mps_free(sc);
+ return (error);
+ }
+ }
+
+ /*
+ * Set flag if this is a WD controller. This shouldn't ever change, but
+ * reset it after a Diag Reset, just in case.
+ */
+ sc->WD_available = FALSE;
+ if (pci_get_device(sc->mps_dev) == MPI2_MFGPAGE_DEVID_SSS6200)
+ sc->WD_available = TRUE;
+
+ return (error);
+}
+
+/*
+ * This is called if memory is being free (during detach for example) and when
+ * buffers need to be reallocated due to a Diag Reset.
+ */
+static void
+mps_iocfacts_free(struct mps_softc *sc)
+{
+ struct mps_command *cm;
+ int i;
+
+ mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
+
+ if (sc->post_busaddr != 0)
+ bus_dmamap_unload(sc->queues_dmat, sc->queues_map);
+ if (sc->post_queue != NULL)
+ bus_dmamem_free(sc->queues_dmat, sc->post_queue,
+ sc->queues_map);
+ if (sc->queues_dmat != NULL)
+ bus_dma_tag_destroy(sc->queues_dmat);
+
+ if (sc->chain_busaddr != 0)
+ bus_dmamap_unload(sc->chain_dmat, sc->chain_map);
+ if (sc->chain_frames != NULL)
+ bus_dmamem_free(sc->chain_dmat, sc->chain_frames,
+ sc->chain_map);
+ if (sc->chain_dmat != NULL)
+ bus_dma_tag_destroy(sc->chain_dmat);
+
+ if (sc->sense_busaddr != 0)
+ bus_dmamap_unload(sc->sense_dmat, sc->sense_map);
+ if (sc->sense_frames != NULL)
+ bus_dmamem_free(sc->sense_dmat, sc->sense_frames,
+ sc->sense_map);
+ if (sc->sense_dmat != NULL)
+ bus_dma_tag_destroy(sc->sense_dmat);
+
+ if (sc->reply_busaddr != 0)
+ bus_dmamap_unload(sc->reply_dmat, sc->reply_map);
+ if (sc->reply_frames != NULL)
+ bus_dmamem_free(sc->reply_dmat, sc->reply_frames,
+ sc->reply_map);
+ if (sc->reply_dmat != NULL)
+ bus_dma_tag_destroy(sc->reply_dmat);
+
+ if (sc->req_busaddr != 0)
+ bus_dmamap_unload(sc->req_dmat, sc->req_map);
+ if (sc->req_frames != NULL)
+ bus_dmamem_free(sc->req_dmat, sc->req_frames, sc->req_map);
+ if (sc->req_dmat != NULL)
+ bus_dma_tag_destroy(sc->req_dmat);
+
+ if (sc->chains != NULL)
+ free(sc->chains, M_MPT2);
+ if (sc->commands != NULL) {
+ for (i = 1; i < sc->num_reqs; i++) {
+ cm = &sc->commands[i];
+ bus_dmamap_destroy(sc->buffer_dmat, cm->cm_dmamap);
+ }
+ free(sc->commands, M_MPT2);
+ }
+ if (sc->buffer_dmat != NULL)
+ bus_dma_tag_destroy(sc->buffer_dmat);
+}
+
/*
- * XXX Some of this should probably move to mps.c
- *
* The terms diag reset and hard reset are used interchangeably in the MPI
* docs to mean resetting the controller chip. In this code diag reset
* cleans everything up, and the hard reset function just sends the reset
@@ -317,7 +676,6 @@ int
mps_reinit(struct mps_softc *sc)
{
int error;
- uint32_t db;
MPS_FUNCTRACE(sc);
@@ -335,6 +693,9 @@ mps_reinit(struct mps_softc *sc)
*/
sc->mps_flags |= MPS_FLAGS_DIAGRESET;
+ /*
+ * Mask interrupts here.
+ */
mps_dprint(sc, MPS_INIT, "%s mask interrupts\n", __func__);
mps_mask_intr(sc);
@@ -351,39 +712,42 @@ mps_reinit(struct mps_softc *sc)
/* Give the I/O subsystem special priority to get itself prepared */
mpssas_handle_reinit(sc);
- /* reinitialize queues after the reset */
- bzero(sc->free_queue, sc->fqdepth * 4);
- mps_init_queues(sc);
-
- /* get the chip out of the reset state */
- error = mps_transition_operational(sc);
- if (error != 0)
- /* XXXSL No need to panic here */
- panic("%s transition operational failed with error %d\n",
+ /*
+ * Get IOC Facts and allocate all structures based on this information.
+ * The attach function will also call mps_iocfacts_allocate at startup.
+ * If relevant values have changed in IOC Facts, this function will free
+ * all of the memory based on IOC Facts and reallocate that memory.
+ */
+ if ((error = mps_iocfacts_allocate(sc, FALSE)) != 0) {
+ panic("%s IOC Facts based allocation failed with error %d\n",
__func__, error);
+ }
- /* Reinitialize the reply queue. This is delicate because this
- * function is typically invoked by task mgmt completion callbacks,
- * which are called by the interrupt thread. We need to make sure
- * the interrupt handler loop will exit when we return to it, and
- * that it will recognize the indexes we've changed.
+ /*
+ * Mapping structures will be re-allocated after getting IOC Page8, so
+ * free these structures here.
*/
- sc->replypostindex = 0;
- mps_regwrite(sc, MPI2_REPLY_FREE_HOST_INDEX_OFFSET, sc->replyfreeindex);
- mps_regwrite(sc, MPI2_REPLY_POST_HOST_INDEX_OFFSET, sc->replypostindex);
-
- db = mps_regread(sc, MPI2_DOORBELL_OFFSET);
- mps_dprint(sc, MPS_INIT, "%s doorbell 0x%08x\n", __func__, db);
-
- mps_dprint(sc, MPS_INIT, "%s unmask interrupts post %u free %u\n",
- __func__, sc->replypostindex, sc->replyfreeindex);
+ mps_mapping_exit(sc);
+ /*
+ * The static page function currently read is IOC Page8. Others can be
+ * added in future. It's possible that the values in IOC Page8 have
+ * changed after a Diag Reset due to user modification, so always read
+ * these. Interrupts are masked, so unmask them before getting config
+ * pages.
+ */
mps_unmask_intr(sc);
+ sc->mps_flags &= ~MPS_FLAGS_DIAGRESET;
+ mps_base_static_config_pages(sc);
- mps_dprint(sc, MPS_INIT, "%s restarting post %u free %u\n", __func__,
- sc->replypostindex, sc->replyfreeindex);
+ /*
+ * Some mapping info is based in IOC Page8 data, so re-initialize the
+ * mapping tables.
+ */
+ mps_mapping_initialize(sc);
- /* restart will reload the event masks clobbered by the reset, and
+ /*
+ * Restart will reload the event masks clobbered by the reset, and
* then enable the port.
*/
mps_reregister_events(sc);
@@ -392,8 +756,6 @@ mps_reinit(struct mps_softc *sc)
mps_dprint(sc, MPS_INFO, "%s finished sc %p post %u free %u\n",
__func__, sc, sc->replypostindex, sc->replyfreeindex);
- sc->mps_flags &= ~MPS_FLAGS_DIAGRESET;
-
return 0;
}
@@ -639,48 +1001,13 @@ mps_get_iocfacts(struct mps_softc *sc, MPI2_IOC_FACTS_REPLY *facts)
}
static int
-mps_get_portfacts(struct mps_softc *sc, MPI2_PORT_FACTS_REPLY *facts, int port)
-{
- MPI2_PORT_FACTS_REQUEST *request;
- MPI2_PORT_FACTS_REPLY *reply;
- struct mps_command *cm;
- int error;
-
- MPS_FUNCTRACE(sc);
-
- if ((cm = mps_alloc_command(sc)) == NULL)
- return (EBUSY);
- request = (MPI2_PORT_FACTS_REQUEST *)cm->cm_req;
- request->Function = MPI2_FUNCTION_PORT_FACTS;
- request->PortNumber = port;
- cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
- cm->cm_data = NULL;
- error = mps_request_polled(sc, cm);
- reply = (MPI2_PORT_FACTS_REPLY *)cm->cm_reply;
- if (reply == NULL) {
- mps_printf(sc, "%s NULL reply\n", __func__);
- goto done;
- }
- if ((reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) {
- mps_printf(sc,
- "%s error %d iocstatus 0x%x iocloginfo 0x%x type 0x%x\n",
- __func__, error, reply->IOCStatus, reply->IOCLogInfo,
- reply->PortType);
- error = ENXIO;
- }
- bcopy(reply, facts, sizeof(MPI2_PORT_FACTS_REPLY));
-done:
- mps_free_command(sc, cm);
-
- return (error);
-}
-
-static int
mps_send_iocinit(struct mps_softc *sc)
{
MPI2_IOC_INIT_REQUEST init;
MPI2_DEFAULT_REPLY reply;
int req_sz, reply_sz, error;
+ struct timeval now;
+ uint64_t time_in_msec;
MPS_FUNCTRACE(sc);
@@ -709,8 +1036,10 @@ mps_send_iocinit(struct mps_softc *sc)
init.ReplyDescriptorPostQueueAddress.Low = htole32((uint32_t)sc->post_busaddr);
init.ReplyFreeQueueAddress.High = 0;
init.ReplyFreeQueueAddress.Low = htole32((uint32_t)sc->free_busaddr);
- init.TimeStamp.High = 0;
- init.TimeStamp.Low = htole32((uint32_t)time_uptime);
+ getmicrotime(&now);
+ time_in_msec = (now.tv_sec * 1000 + now.tv_usec/1000);
+ init.TimeStamp.High = htole32((time_in_msec >> 32) & 0xFFFFFFFF);
+ init.TimeStamp.Low = htole32(time_in_msec & 0xFFFFFFFF);
error = mps_request_sync(sc, &init, &reply, req_sz, reply_sz, 5);
if ((reply.IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
@@ -1124,7 +1453,7 @@ mps_setup_sysctl(struct mps_softc *sc)
int
mps_attach(struct mps_softc *sc)
{
- int i, error;
+ int error;
mps_get_tunables(sc);
@@ -1146,151 +1475,20 @@ mps_attach(struct mps_softc *sc)
__func__, __LINE__);
return (ENOMEM);
}
- if ((error = mps_get_iocfacts(sc, sc->facts)) != 0)
- return (error);
-
- mps_print_iocfacts(sc, sc->facts);
-
- snprintf(sc->fw_version, sizeof(sc->fw_version),
- "%02d.%02d.%02d.%02d",
- sc->facts->FWVersion.Struct.Major,
- sc->facts->FWVersion.Struct.Minor,
- sc->facts->FWVersion.Struct.Unit,
- sc->facts->FWVersion.Struct.Dev);
-
- mps_printf(sc, "Firmware: %s, Driver: %s\n", sc->fw_version,
- MPS_DRIVER_VERSION);
- mps_printf(sc, "IOCCapabilities: %b\n", sc->facts->IOCCapabilities,
- "\20" "\3ScsiTaskFull" "\4DiagTrace" "\5SnapBuf" "\6ExtBuf"
- "\7EEDP" "\10BiDirTarg" "\11Multicast" "\14TransRetry" "\15IR"
- "\16EventReplay" "\17RaidAccel" "\20MSIXIndex" "\21HostDisc");
-
- /*
- * If the chip doesn't support event replay then a hard reset will be
- * required to trigger a full discovery. Do the reset here then
- * retransition to Ready. A hard reset might have already been done,
- * but it doesn't hurt to do it again.
- */
- if ((sc->facts->IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY) == 0) {
- mps_diag_reset(sc, NO_SLEEP);
- if ((error = mps_transition_ready(sc)) != 0)
- return (error);
- }
-
- /*
- * Set flag if IR Firmware is loaded.
- */
- if (sc->facts->IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID)
- sc->ir_firmware = 1;
-
- /*
- * Check if controller supports FW diag buffers and set flag to enable
- * each type.
- */
- if (sc->facts->IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER)
- sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_TRACE].enabled =
- TRUE;
- if (sc->facts->IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER)
- sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_SNAPSHOT].enabled =
- TRUE;
- if (sc->facts->IOCCapabilities &
- MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER)
- sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_EXTENDED].enabled =
- TRUE;
-
- /*
- * Set flag if EEDP is supported and if TLR is supported.
- */
- if (sc->facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP)
- sc->eedp_enabled = TRUE;
- if (sc->facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR)
- sc->control_TLR = TRUE;
/*
- * Size the queues. Since the reply queues always need one free entry,
- * we'll just deduct one reply message here.
+ * Get IOC Facts and allocate all structures based on this information.
+ * A Diag Reset will also call mps_iocfacts_allocate and re-read the IOC
+ * Facts. If relevant values have changed in IOC Facts, this function
+ * will free all of the memory based on IOC Facts and reallocate that
+ * memory. If this fails, any allocated memory should already be freed.
*/
- sc->num_reqs = MIN(MPS_REQ_FRAMES, sc->facts->RequestCredit);
- sc->num_replies = MIN(MPS_REPLY_FRAMES + MPS_EVT_REPLY_FRAMES,
- sc->facts->MaxReplyDescriptorPostQueueDepth) - 1;
- TAILQ_INIT(&sc->req_list);
- TAILQ_INIT(&sc->high_priority_req_list);
- TAILQ_INIT(&sc->chain_list);
- TAILQ_INIT(&sc->tm_list);
-
- if (((error = mps_alloc_queues(sc)) != 0) ||
- ((error = mps_alloc_replies(sc)) != 0) ||
- ((error = mps_alloc_requests(sc)) != 0)) {
- mps_printf(sc, "%s failed to alloc\n", __func__);
- mps_free(sc);
- return (error);
- }
-
- if (((error = mps_init_queues(sc)) != 0) ||
- ((error = mps_transition_operational(sc)) != 0)) {
- mps_printf(sc, "%s failed to transition operational\n", __func__);
- mps_free(sc);
+ if ((error = mps_iocfacts_allocate(sc, TRUE)) != 0) {
+ mps_dprint(sc, MPS_FAULT, "%s IOC Facts based allocation "
+ "failed with error %d\n", __func__, error);
return (error);
}
- /*
- * Finish the queue initialization.
- * These are set here instead of in mps_init_queues() because the
- * IOC resets these values during the state transition in
- * mps_transition_operational(). The free index is set to 1
- * because the corresponding index in the IOC is set to 0, and the
- * IOC treats the queues as full if both are set to the same value.
- * Hence the reason that the queue can't hold all of the possible
- * replies.
- */
- sc->replypostindex = 0;
- mps_regwrite(sc, MPI2_REPLY_FREE_HOST_INDEX_OFFSET, sc->replyfreeindex);
- mps_regwrite(sc, MPI2_REPLY_POST_HOST_INDEX_OFFSET, 0);
-
- sc->pfacts = malloc(sizeof(MPI2_PORT_FACTS_REPLY) *
- sc->facts->NumberOfPorts, M_MPT2, M_ZERO|M_WAITOK);
- if(!sc->pfacts) {
- device_printf(sc->mps_dev, "Cannot allocate memory %s %d\n",
- __func__, __LINE__);
- return (ENOMEM);
- }
- for (i = 0; i < sc->facts->NumberOfPorts; i++) {
- if ((error = mps_get_portfacts(sc, &sc->pfacts[i], i)) != 0) {
- mps_printf(sc, "%s failed to get portfacts for port %d\n",
- __func__, i);
- mps_free(sc);
- return (error);
- }
- mps_print_portfacts(sc, &sc->pfacts[i]);
- }
-
- /* Attach the subsystems so they can prepare their event masks. */
- /* XXX Should be dynamic so that IM/IR and user modules can attach */
- if (((error = mps_attach_log(sc)) != 0) ||
- ((error = mps_attach_sas(sc)) != 0) ||
- ((error = mps_attach_user(sc)) != 0)) {
- mps_printf(sc, "%s failed to attach all subsystems: error %d\n",
- __func__, error);
- mps_free(sc);
- return (error);
- }
-
- if ((error = mps_pci_setup_interrupts(sc)) != 0) {
- mps_printf(sc, "%s failed to setup interrupts\n", __func__);
- mps_free(sc);
- return (error);
- }
-
- /*
- * The static page function currently read is ioc page8. Others can be
- * added in future.
- */
- mps_base_static_config_pages(sc);
-
/* Start the periodic watchdog check on the IOC Doorbell */
mps_periodic(sc);
@@ -1333,7 +1531,9 @@ mps_startup(void *arg)
mps_lock(sc);
mps_unmask_intr(sc);
+
/* initialize device mapping tables */
+ mps_base_static_config_pages(sc);
mps_mapping_initialize(sc);
mpssas_startup(sc);
mps_unlock(sc);
@@ -1416,8 +1616,7 @@ mps_detach_log(struct mps_softc *sc)
int
mps_free(struct mps_softc *sc)
{
- struct mps_command *cm;
- int i, error;
+ int error;
/* Turn off the watchdog */
mps_lock(sc);
@@ -1443,62 +1642,15 @@ mps_free(struct mps_softc *sc)
if (sc->facts != NULL)
free(sc->facts, M_MPT2);
- if (sc->pfacts != NULL)
- free(sc->pfacts, M_MPT2);
-
- if (sc->post_busaddr != 0)
- bus_dmamap_unload(sc->queues_dmat, sc->queues_map);
- if (sc->post_queue != NULL)
- bus_dmamem_free(sc->queues_dmat, sc->post_queue,
- sc->queues_map);
- if (sc->queues_dmat != NULL)
- bus_dma_tag_destroy(sc->queues_dmat);
-
- if (sc->chain_busaddr != 0)
- bus_dmamap_unload(sc->chain_dmat, sc->chain_map);
- if (sc->chain_frames != NULL)
- bus_dmamem_free(sc->chain_dmat, sc->chain_frames,sc->chain_map);
- if (sc->chain_dmat != NULL)
- bus_dma_tag_destroy(sc->chain_dmat);
-
- if (sc->sense_busaddr != 0)
- bus_dmamap_unload(sc->sense_dmat, sc->sense_map);
- if (sc->sense_frames != NULL)
- bus_dmamem_free(sc->sense_dmat, sc->sense_frames,sc->sense_map);
- if (sc->sense_dmat != NULL)
- bus_dma_tag_destroy(sc->sense_dmat);
-
- if (sc->reply_busaddr != 0)
- bus_dmamap_unload(sc->reply_dmat, sc->reply_map);
- if (sc->reply_frames != NULL)
- bus_dmamem_free(sc->reply_dmat, sc->reply_frames,sc->reply_map);
- if (sc->reply_dmat != NULL)
- bus_dma_tag_destroy(sc->reply_dmat);
-
- if (sc->req_busaddr != 0)
- bus_dmamap_unload(sc->req_dmat, sc->req_map);
- if (sc->req_frames != NULL)
- bus_dmamem_free(sc->req_dmat, sc->req_frames, sc->req_map);
- if (sc->req_dmat != NULL)
- bus_dma_tag_destroy(sc->req_dmat);
-
- if (sc->chains != NULL)
- free(sc->chains, M_MPT2);
- if (sc->commands != NULL) {
- for (i = 1; i < sc->num_reqs; i++) {
- cm = &sc->commands[i];
- bus_dmamap_destroy(sc->buffer_dmat, cm->cm_dmamap);
- }
- free(sc->commands, M_MPT2);
- }
- if (sc->buffer_dmat != NULL)
- bus_dma_tag_destroy(sc->buffer_dmat);
+ /*
+ * Free all buffers that are based on IOC Facts. A Diag Reset may need
+ * to free these buffers too.
+ */
+ mps_iocfacts_free(sc);
if (sc->sysctl_tree != NULL)
sysctl_ctx_free(&sc->sysctl_ctx);
- mps_mapping_free_memory(sc);
-
/* Deregister the shutdown function */
if (sc->shutdown_eh != NULL)
EVENTHANDLER_DEREGISTER(shutdown_final, sc->shutdown_eh);
@@ -1925,7 +2077,7 @@ mps_reregister_events(struct mps_softc *sc)
/* first, reregister events */
- for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
+ for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
sc->event_mask[i] = -1;
TAILQ_FOREACH(eh, &sc->event_list, eh_list) {
@@ -1957,7 +2109,8 @@ mps_reregister_events(struct mps_softc *sc)
error = mps_map_command(sc, cm);
- mps_dprint(sc, MPS_TRACE, "%s finished with error %d\n", __func__, error);
+ mps_dprint(sc, MPS_TRACE, "%s finished with error %d\n", __func__,
+ error);
return (error);
}
@@ -2313,26 +2466,50 @@ 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 *cm, int timeout,
+ int sleep_flag)
{
int error, rc;
+ struct timeval cur_time, start_time;
- mtx_assert(&sc->mps_mtx, MA_OWNED);
-
- if(sc->mps_flags & MPS_FLAGS_DIAGRESET)
+ if (sc->mps_flags & MPS_FLAGS_DIAGRESET)
return EBUSY;
cm->cm_complete = NULL;
- cm->cm_flags |= MPS_CM_FLAGS_WAKEUP;
+ cm->cm_flags |= (MPS_CM_FLAGS_WAKEUP + MPS_CM_FLAGS_POLLED);
error = mps_map_command(sc, cm);
if ((error != 0) && (error != EINPROGRESS))
return (error);
- error = msleep(cm, &sc->mps_mtx, 0, "mpswait", timeout*hz);
+
+ // Check for context and wait for 50 mSec at a time until time has
+ // expired or the command has finished. If msleep can't be used, need
+ // to poll.
+ if (curthread->td_no_sleeping != 0)
+ sleep_flag = NO_SLEEP;
+ getmicrotime(&start_time);
+ if (mtx_owned(&sc->mps_mtx) && sleep_flag == CAN_SLEEP) {
+ error = msleep(cm, &sc->mps_mtx, 0, "mpswait", timeout*hz);
+ } else {
+ while ((cm->cm_flags & MPS_CM_FLAGS_COMPLETE) == 0) {
+ mps_intr_locked(sc);
+ if (sleep_flag == CAN_SLEEP)
+ pause("mpswait", hz/20);
+ else
+ DELAY(50000);
+
+ getmicrotime(&cur_time);
+ if ((cur_time.tv_sec - start_time.tv_sec) > timeout) {
+ error = EWOULDBLOCK;
+ break;
+ }
+ }
+ }
+
if (error == EWOULDBLOCK) {
mps_dprint(sc, MPS_FAULT, "Calling Reinit from %s\n", __func__);
rc = mps_reinit(sc);
- mps_dprint(sc, MPS_FAULT, "Reinit %s\n",
- (rc == 0) ? "success" : "failed");
+ mps_dprint(sc, MPS_FAULT, "Reinit %s\n", (rc == 0) ? "success" :
+ "failed");
error = ETIMEDOUT;
}
return (error);
@@ -2432,7 +2609,7 @@ 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);
+ error = mps_wait_command(sc, cm, 0, CAN_SLEEP);
if (error) {
mps_dprint(sc, MPS_FAULT,
"Error %d reading config page\n", error);
diff --git a/sys/dev/mps/mps_config.c b/sys/dev/mps/mps_config.c
index 939872e..d6e2a8c 100644
--- a/sys/dev/mps/mps_config.c
+++ b/sys/dev/mps/mps_config.c
@@ -93,12 +93,15 @@ 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_request_polled(sc, cm);
+ error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for header completed with error %d",
+ /*
+ * 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;
@@ -107,7 +110,10 @@ mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * 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;
@@ -144,12 +150,16 @@ mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
goto out;
}
cm->cm_data = page;
- error = mps_request_polled(sc, cm);
+
+ error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for page completed with error %d",
+ /*
+ * 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;
@@ -158,7 +168,10 @@ mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * 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;
@@ -211,6 +224,11 @@ mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply)
request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_data = NULL;
+
+ /*
+ * This page must be polled because the IOC isn't ready yet when this
+ * page is needed.
+ */
error = mps_request_polled(sc, cm);
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
@@ -262,6 +280,11 @@ mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply)
goto out;
}
cm->cm_data = page;
+
+ /*
+ * This page must be polled because the IOC isn't ready yet when this
+ * page is needed.
+ */
error = mps_request_polled(sc, cm);
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
@@ -561,12 +584,15 @@ 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_request_polled(sc, cm);
+ error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for header completed with error %d",
+ /*
+ * 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;
@@ -575,7 +601,10 @@ mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * 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;
@@ -615,12 +644,15 @@ mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
goto out;
}
cm->cm_data = page;
- error = mps_request_polled(sc, cm);
+ error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for page completed with error %d",
+ /*
+ * 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;
@@ -629,7 +661,10 @@ mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * 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;
@@ -685,12 +720,15 @@ 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_request_polled(sc, cm);
+ error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for header completed with error %d",
+ /*
+ * 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;
@@ -699,7 +737,10 @@ int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * 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;
@@ -741,12 +782,15 @@ 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_request_polled(sc, cm);
+ error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for page completed with error %d",
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
+ printf("%s: request to write page completed with error %d",
__func__, error);
error = ENXIO;
goto out;
@@ -755,7 +799,10 @@ int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * If the request returns an error then we need to do a diag
+ * reset
+ */
printf("%s: page written with error; iocstatus = 0x%x\n",
__func__, ioc_status);
error = ENXIO;
@@ -808,12 +855,15 @@ 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_request_polled(sc, cm);
+ error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for header completed with error %d",
+ /*
+ * 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;
@@ -822,7 +872,10 @@ mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * 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;
@@ -862,12 +915,15 @@ mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
}
cm->cm_data = page;
- error = mps_request_polled(sc, cm);
+ error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for page completed with error %d",
+ /*
+ * 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;
@@ -876,7 +932,10 @@ mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * 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;
@@ -928,12 +987,15 @@ 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_request_polled(sc, cm);
+ error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for header completed with error %d",
+ /*
+ * 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;
@@ -942,7 +1004,10 @@ mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * 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;
@@ -980,12 +1045,15 @@ mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
}
cm->cm_data = page;
- error = mps_request_polled(sc, cm);
+ error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for page completed with error %d",
+ /*
+ * 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;
@@ -994,7 +1062,10 @@ mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * 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;
@@ -1046,6 +1117,11 @@ mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_data = NULL;
+
+ /*
+ * This page must be polled because the IOC isn't ready yet when this
+ * page is needed.
+ */
error = mps_request_polled(sc, cm);
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
@@ -1099,6 +1175,10 @@ mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
}
cm->cm_data = page;
+ /*
+ * This page must be polled because the IOC isn't ready yet when this
+ * page is needed.
+ */
error = mps_request_polled(sc, cm);
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
@@ -1166,12 +1246,15 @@ 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_request_polled(sc, cm);
+ error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for header completed with error %d",
+ /*
+ * 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;
@@ -1180,7 +1263,10 @@ mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * 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;
@@ -1219,12 +1305,15 @@ mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t
}
cm->cm_data = page;
- error = mps_request_polled(sc, cm);
+ error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for page completed with error %d",
+ /*
+ * 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;
@@ -1233,7 +1322,10 @@ mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
+ /*
+ * 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;
@@ -1311,6 +1403,11 @@ mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_data = NULL;
+
+ /*
+ * This page must be polled because the IOC isn't ready yet when this
+ * page is needed.
+ */
error = mps_request_polled(sc, cm);
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
@@ -1364,6 +1461,10 @@ mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
}
cm->cm_data = page;
+ /*
+ * This page must be polled because the IOC isn't ready yet when this
+ * page is needed.
+ */
error = mps_request_polled(sc, cm);
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
if (error || (reply == NULL)) {
diff --git a/sys/dev/mps/mps_mapping.c b/sys/dev/mps/mps_mapping.c
index c486ecb..97e24be 100644
--- a/sys/dev/mps/mps_mapping.c
+++ b/sys/dev/mps/mps_mapping.c
@@ -1217,12 +1217,12 @@ _mapping_add_new_device(struct mps_softc *sc,
phy_change->is_processed = 1;
} else {
phy_change->is_processed = 1;
- printf("%s: failed to add the "
- "device with handle 0x%04x "
- "to persistent table "
- "because there is no free "
- "space available\n",
- __func__,
+ mps_dprint(sc, MPS_INFO, "%s: "
+ "failed to add the device "
+ "with handle 0x%04x to "
+ "persistent table because "
+ "there is no free space "
+ "available\n", __func__,
phy_change->dev_handle);
}
} else {
@@ -1319,12 +1319,12 @@ _mapping_add_new_device(struct mps_softc *sc,
phy_change->is_processed = 1;
} else if (dpm_idx == MPS_DPM_BAD_IDX) {
phy_change->is_processed = 1;
- printf("%s: failed to add the "
- "device with handle 0x%04x "
- "to persistent table "
- "because there is no free "
- "space available\n",
- __func__,
+ mps_dprint(sc, MPS_INFO, "%s: "
+ "failed to add the device "
+ "with handle 0x%04x to "
+ "persistent table because "
+ "there is no free space "
+ "available\n", __func__,
phy_change->dev_handle);
}
}
diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c
index f524c8a..43c46fd 100644
--- a/sys/dev/mps/mps_sas.c
+++ b/sys/dev/mps/mps_sas.c
@@ -281,7 +281,7 @@ mpssas_rescan_target(struct mps_softc *sc, struct mpssas_target *targ)
}
if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid,
- targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
mps_dprint(sc, MPS_ERROR, "unable to create path for rescan\n");
xpt_free_ccb(ccb);
return;
@@ -1644,13 +1644,24 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
return;
}
if (targ->flags & MPS_TARGET_FLAGS_RAID_COMPONENT) {
- mps_dprint(sc, MPS_ERROR, "%s Raid component no SCSI IO supported %u\n",
- __func__, csio->ccb_h.target_id);
+ mps_dprint(sc, MPS_ERROR, "%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;
}
/*
+ * Sometimes, it is possible to get a command that is not "In
+ * Progress" and was actually aborted by the upper layer. Check for
+ * this here and complete the command without error.
+ */
+ if (ccb->ccb_h.status != CAM_REQ_INPROG) {
+ mps_dprint(sc, MPS_TRACE, "%s Command is not in progress for "
+ "target %u\n", __func__, csio->ccb_h.target_id);
+ 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
* until they are deleted/removed, not just failed.
@@ -1718,7 +1729,7 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
break;
}
- if (csio->cdb_len == 32)
+ if (csio->cdb_len == 32)
mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT;
/*
* It looks like the hardware doesn't require an explicit tag
@@ -1846,6 +1857,7 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
targ->issued++;
targ->outstanding++;
TAILQ_INSERT_TAIL(&targ->commands, cm, cm_link);
+ ccb->ccb_h.status |= CAM_SIM_QUEUED;
mpssas_log_command(cm, MPS_XINFO, "%s cm %p ccb %p outstanding %u\n",
__func__, cm, ccb, targ->outstanding);
@@ -2028,8 +2040,8 @@ mps_sc_failed_io_info(struct mps_softc *sc, struct ccb_scsiio *csio,
* TO-DO
* */
mps_dprint(sc, MPS_XINFO, "\tscsi_status(%s)(0x%02x), "
- "scsi_state(%s)(0x%02x)\n", desc_scsi_status,
- scsi_status, desc_scsi_state, scsi_state);
+ "scsi_state(%s)(0x%02x)\n", desc_scsi_status, scsi_status,
+ desc_scsi_state, scsi_state);
if (sc->mps_debug & MPS_XINFO &&
scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
@@ -2087,6 +2099,7 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
cm->cm_targ->completed++;
cm->cm_targ->outstanding--;
TAILQ_REMOVE(&cm->cm_targ->commands, cm, cm_link);
+ ccb->ccb_h.status |= ~(CAM_STATUS_MASK | CAM_SIM_QUEUED);
if (cm->cm_state == MPS_CM_STATE_TIMEDOUT) {
TAILQ_REMOVE(&cm->cm_targ->timedout_commands, cm, cm_recovery);
@@ -2162,7 +2175,7 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
sassc->flags &= ~MPSSAS_QUEUE_FROZEN;
mps_dprint(sc, MPS_XINFO,
- "Unfreezing SIM queue\n");
+ "Unfreezing SIM queue\n");
}
}
@@ -2388,7 +2401,7 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
sassc->flags &= ~MPSSAS_QUEUE_FROZEN;
mps_dprint(sc, MPS_XINFO, "Command completed, "
- "unfreezing SIM queue\n");
+ "unfreezing SIM queue\n");
}
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
@@ -2704,7 +2717,8 @@ mpssas_smpio_complete(struct mps_softc *sc, struct mps_command *cm)
sasaddr = le32toh(req->SASAddress.Low);
sasaddr |= ((uint64_t)(le32toh(req->SASAddress.High))) << 32;
- if ((le16toh(rpl->IOCStatus) & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS ||
+ if ((le16toh(rpl->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
+ MPI2_IOCSTATUS_SUCCESS ||
rpl->SASStatus != MPI2_SASSTATUS_SUCCESS) {
mps_dprint(sc, MPS_XINFO, "%s: IOCStatus %04x SASStatus %02x\n",
__func__, le16toh(rpl->IOCStatus), rpl->SASStatus);
@@ -2829,7 +2843,7 @@ mpssas_send_smpcmd(struct mpssas_softc *sassc, union ccb *ccb, uint64_t sasaddr)
MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE | MPI2_SGLFLAGS_SGL_TYPE_MPI;
mps_dprint(sc, MPS_XINFO, "%s: sending SMP request to SAS "
- "address %#jx\n", __func__, (uintmax_t)sasaddr);
+ "address %#jx\n", __func__, (uintmax_t)sasaddr);
mpi_init_sge(cm, req, &req->SGL);
@@ -3422,6 +3436,10 @@ mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb)
}
if (rcap_buf->protect & 0x01) {
+ mps_dprint(sassc->sc, MPS_INFO, "LUN %d for "
+ "target ID %d is formatted for EEDP "
+ "support.\n", done_ccb->ccb_h.target_lun,
+ done_ccb->ccb_h.target_id);
lun->eedp_formatted = TRUE;
lun->eedp_block_size = scsi_4btoul(rcap_buf->length);
}
diff --git a/sys/dev/mps/mps_sas_lsi.c b/sys/dev/mps/mps_sas_lsi.c
index e056590..85d6d1f 100644
--- a/sys/dev/mps/mps_sas_lsi.c
+++ b/sys/dev/mps/mps_sas_lsi.c
@@ -821,12 +821,15 @@ mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_data = buffer;
cm->cm_length = htole32(sz);
- error = mps_request_polled(sc, cm);
+ error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
- /* If the poll returns error then we need to do diag reset */
- printf("%s: poll for page completed with error %d",
+ /*
+ * 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;
@@ -958,7 +961,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_request_polled(sc, cm);
+ 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 9a03d8e..9212f77 100644
--- a/sys/dev/mps/mps_user.c
+++ b/sys/dev/mps/mps_user.c
@@ -669,7 +669,7 @@ mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd)
cm = mps_alloc_command(sc);
if (cm == NULL) {
- mps_printf(sc, "mps_user_command: no mps requests\n");
+ mps_printf(sc, "%s: no mps requests\n", __func__);
err = ENOMEM;
goto Ret;
}
@@ -677,8 +677,8 @@ mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd)
hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;
- mps_dprint(sc, MPS_USER, "mps_user_command: req %p %d rpl %p %d\n",
- cmd->req, cmd->req_len, cmd->rpl, cmd->rpl_len );
+ mps_dprint(sc, MPS_USER, "%s: req %p %d rpl %p %d\n", __func__,
+ cmd->req, cmd->req_len, cmd->rpl, cmd->rpl_len);
if (cmd->req_len > (int)sc->facts->IOCRequestFrameSize * 4) {
err = EINVAL;
@@ -688,8 +688,8 @@ mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd)
if (err != 0)
goto RetFreeUnlocked;
- mps_dprint(sc, MPS_USER, "mps_user_command: Function %02X "
- "MsgFlags %02X\n", hdr->Function, hdr->MsgFlags );
+ mps_dprint(sc, MPS_USER, "%s: Function %02X MsgFlags %02X\n", __func__,
+ hdr->Function, hdr->MsgFlags);
if (cmd->len > 0) {
buf = malloc(cmd->len, M_MPSUSER, M_WAITOK|M_ZERO);
@@ -709,14 +709,16 @@ mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd)
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
err = mps_user_setup_request(cm, cmd);
- if (err != 0) {
- mps_printf(sc, "mps_user_command: unsupported function 0x%X\n",
- hdr->Function );
- goto RetFreeUnlocked;
+ if (err == EINVAL) {
+ mps_printf(sc, "%s: unsupported parameter or unsupported "
+ "function in request (function = 0x%X)\n", __func__,
+ hdr->Function);
}
+ if (err != 0)
+ goto RetFreeUnlocked;
mps_lock(sc);
- err = mps_wait_command(sc, cm, 60);
+ err = mps_wait_command(sc, cm, 60, CAN_SLEEP);
if (err) {
mps_printf(sc, "%s: invalid request: error %d\n",
@@ -731,10 +733,8 @@ mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd)
sz = 0;
if (sz > cmd->rpl_len) {
- mps_printf(sc,
- "mps_user_command: reply buffer too small %d required %d\n",
- cmd->rpl_len, sz );
- err = EINVAL;
+ mps_printf(sc, "%s: user reply buffer (%d) smaller than "
+ "returned buffer (%d)\n", __func__, cmd->rpl_len, sz);
sz = cmd->rpl_len;
}
@@ -742,7 +742,7 @@ mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd)
copyout(rpl, cmd->rpl, sz);
if (buf != NULL)
copyout(buf, cmd->buf, cmd->len);
- mps_dprint(sc, MPS_USER, "mps_user_command: reply size %d\n", sz );
+ mps_dprint(sc, MPS_USER, "%s: reply size %d\n", __func__, sz);
RetFreeUnlocked:
mps_lock(sc);
@@ -849,7 +849,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, 30);
+ err = mps_wait_command(sc, cm, 30, CAN_SLEEP);
if (err != 0) {
err = EIO;
@@ -864,15 +864,14 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data)
sz = rpl->MsgLength * 4;
if (sz > data->ReplySize) {
- mps_printf(sc, "%s: reply buffer too small: %d, "
- "required: %d\n", __func__, data->ReplySize, sz);
- err = EINVAL;
- } else {
- mps_unlock(sc);
- copyout(cm->cm_reply, PTRIN(data->PtrReply),
- data->ReplySize);
- mps_lock(sc);
+ mps_printf(sc, "%s: user reply buffer (%d) "
+ "smaller than returned buffer (%d)\n",
+ __func__, data->ReplySize, sz);
}
+ mps_unlock(sc);
+ copyout(cm->cm_reply, PTRIN(data->PtrReply),
+ data->ReplySize);
+ mps_lock(sc);
}
mpssas_free_tm(sc, cm);
goto Ret;
@@ -986,7 +985,7 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data)
mps_lock(sc);
- err = mps_wait_command(sc, cm, 30);
+ err = mps_wait_command(sc, cm, 30, CAN_SLEEP);
if (err) {
mps_printf(sc, "%s: invalid request: error %d\n", __func__,
@@ -1025,15 +1024,13 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data)
sz = rpl->MsgLength * 4;
if (sz > data->ReplySize) {
- mps_printf(sc, "%s: reply buffer too small: %d, "
- "required: %d\n", __func__, data->ReplySize, sz);
- err = EINVAL;
- } else {
- mps_unlock(sc);
- copyout(cm->cm_reply, PTRIN(data->PtrReply),
- data->ReplySize);
- mps_lock(sc);
+ mps_printf(sc, "%s: user reply buffer (%d) smaller "
+ "than returned buffer (%d)\n", __func__,
+ data->ReplySize, sz);
}
+ mps_unlock(sc);
+ copyout(cm->cm_reply, PTRIN(data->PtrReply), data->ReplySize);
+ mps_lock(sc);
if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
(function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
@@ -1203,7 +1200,7 @@ mps_post_fw_diag_buffer(struct mps_softc *sc,
/*
* Send command synchronously.
*/
- status = mps_wait_command(sc, cm, 30);
+ status = mps_wait_command(sc, cm, 30, CAN_SLEEP);
if (status) {
mps_printf(sc, "%s: invalid request: error %d\n", __func__,
status);
@@ -1252,8 +1249,8 @@ mps_release_fw_diag_buffer(struct mps_softc *sc,
*/
*return_code = MPS_FW_DIAG_ERROR_RELEASE_FAILED;
if (!pBuffer->enabled) {
- mps_dprint(sc, MPS_USER, "%s: This buffer type is not supported "
- "by the IOC", __func__);
+ mps_dprint(sc, MPS_USER, "%s: This buffer type is not "
+ "supported by the IOC", __func__);
return (MPS_DIAG_FAILURE);
}
@@ -1287,7 +1284,7 @@ mps_release_fw_diag_buffer(struct mps_softc *sc,
/*
* Send command synchronously.
*/
- status = mps_wait_command(sc, cm, 30);
+ status = mps_wait_command(sc, cm, 30, CAN_SLEEP);
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 c30ee2c..5f8a015 100644
--- a/sys/dev/mps/mpsvar.h
+++ b/sys/dev/mps/mpsvar.h
@@ -32,7 +32,7 @@
#ifndef _MPSVAR_H
#define _MPSVAR_H
-#define MPS_DRIVER_VERSION "14.00.00.02-fbsd"
+#define MPS_DRIVER_VERSION "16.00.00.00-fbsd"
#define MPS_DB_MAX_WAIT 2500
@@ -304,7 +304,6 @@ struct mps_softc {
bus_dma_tag_t buffer_dmat;
MPI2_IOC_FACTS_REPLY *facts;
- MPI2_PORT_FACTS_REPLY *pfacts;
int num_reqs;
int num_replies;
int fqdepth; /* Free queue */
@@ -695,7 +694,8 @@ 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_request_polled(struct mps_softc *sc, struct mps_command *cm);
int mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t
OpenPOWER on IntegriCloud