Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 12 Aug 2013 13:02:29 -0600
From:      "Kenneth D. Merry" <ken@FreeBSD.org>
To:        Slawa Olhovchenkov <slw@zxy.spb.ru>
Cc:        svn-src-head@FreeBSD.org, svn-src-all@FreeBSD.org, src-committers@FreeBSD.org
Subject:   Re: svn commit: r253550 - head/sys/dev/mps
Message-ID:  <20130812190229.GA24478@nargothrond.kdm.org>
In-Reply-To: <20130812174545.GA3796@zxy.spb.ru>
References:  <201307221841.r6MIfsoQ075667@svn.freebsd.org> <20130810181454.GA47115@zxy.spb.ru> <20130812155647.GA11414@nargothrond.kdm.org> <20130812174545.GA3796@zxy.spb.ru>

next in thread | previous in thread | raw e-mail | index | archive | help

--k1lZvvs/B4yU6o8G
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Mon, Aug 12, 2013 at 21:45:45 +0400, Slawa Olhovchenkov wrote:
> On Mon, Aug 12, 2013 at 09:56:48AM -0600, Kenneth D. Merry wrote:
> 
> > On Sat, Aug 10, 2013 at 22:14:54 +0400, Slawa Olhovchenkov wrote:
> > > On Mon, Jul 22, 2013 at 06:41:54PM +0000, Kenneth D. Merry wrote:
> > > 
> > > > Author: ken
> > > > Date: Mon Jul 22 18:41:53 2013
> > > > New Revision: 253550
> > > > URL: http://svnweb.freebsd.org/changeset/base/253550
> > > > 
> > > > Log:
> > > >   Merge in phase 14+ -> 16 mps driver fixes from LSI:
> > > >   Submitted by:	LSI
> > > >   MFC after:	1 week
> > > 
> > > Not done?
> > 
> > I was waiting for the stable/9 freeze to end.
> 
> Hm?
> 
> Date: Mon Aug  5 23:34:35 2013
> New Revision: 253975
> URL: http://svnweb.freebsd.org/changeset/base/253975
> 
> Log:
>   stable/9 no longer requires re@ approval for commits, now that the
>   releng/9.2 branch is created.
> 
>   Committers are urged to exercise caution with commits to stable/9
>   until the 9.2-RELEASE is finalized.
> 
> Or, can you published patch for 9-STABLE?

If you really want one now, I've attached a patch from stable/9 on June
27th.  It may or may not apply now.

> > Now that it's done, I hope to merge that change to stable/9 this week.
> 
> Also, I see strange behaviour of LSI 9211-8i -- after some activity
> got timeout and HBA put in looped reset.

That's not good.  Try with the newer driver and see whether if affects the
behavior.

Ken
-- 
Kenneth Merry
ken@FreeBSD.ORG

--k1lZvvs/B4yU6o8G
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="mps_scan_stable9.20130627.1.txt"

*** src/sys/cam/cam_ccb.h.orig
--- src/sys/cam/cam_ccb.h
***************
*** 578,583 ****
--- 578,584 ----
  	PIM_NO_6_BYTE	= 0x08,	/* Do not send 6-byte commands */
  	PIM_SEQSCAN	= 0x04,	/* Do bus scans sequentially, not in parallel */
  	PIM_UNMAPPED	= 0x02,
+ 	PIM_NOSCAN	= 0x01	/* SIM does its own scanning */
  } pi_miscflag;
  
  /* Path Inquiry CCB */
*** src/sys/cam/cam_xpt.c.orig
--- src/sys/cam/cam_xpt.c
***************
*** 4012,4026 ****
  
  	/* Notify interested parties */
  	if (sim->path_id != CAM_XPT_PATH_ID) {
- 		union	ccb *scan_ccb;
  
  		xpt_async(AC_PATH_REGISTERED, path, &cpi);
! 		/* Initiate bus rescan. */
! 		scan_ccb = xpt_alloc_ccb_nowait();
! 		scan_ccb->ccb_h.path = path;
! 		scan_ccb->ccb_h.func_code = XPT_SCAN_BUS;
! 		scan_ccb->crcn.flags = 0;
! 		xpt_rescan(scan_ccb);
  	} else
  		xpt_free_path(path);
  	return (CAM_SUCCESS);
--- 4012,4030 ----
  
  	/* Notify interested parties */
  	if (sim->path_id != CAM_XPT_PATH_ID) {
  
  		xpt_async(AC_PATH_REGISTERED, path, &cpi);
! 
! 		if ((cpi.hba_misc & PIM_NOSCAN) == 0) {
! 			union	ccb *scan_ccb;
! 
! 			/* Initiate bus rescan. */
! 			scan_ccb = xpt_alloc_ccb_nowait();
! 			scan_ccb->ccb_h.path = path;
! 			scan_ccb->ccb_h.func_code = XPT_SCAN_BUS;
! 			scan_ccb->crcn.flags = 0;
! 			xpt_rescan(scan_ccb);
! 		}
  	} else
  		xpt_free_path(path);
  	return (CAM_SUCCESS);
*** src/sys/dev/mps/mps.c.orig
--- src/sys/dev/mps/mps.c
***************
*** 51,56 ****
--- 51,57 ----
  #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,66 ****
--- 62,68 ----
  
  #include <dev/pci/pcivar.h>
  
+ #include <cam/cam.h>
  #include <cam/scsi/scsi_all.h>
  
  #include <dev/mps/mpi/mpi2_type.h>
***************
*** 73,85 ****
--- 75,93 ----
  #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_command *cm);
  static void mps_dispatch_event(struct mps_softc *sc, uintptr_t data,
***************
*** 88,93 ****
--- 96,102 ----
  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");
  
***************
*** 148,154 ****
  			    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);
  		else if (sleep_flag == CAN_SLEEP)
  			pause("mpsdiag", hz/10);
  		else
--- 157,164 ----
  			    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);
  		else if (sleep_flag == CAN_SLEEP)
  			pause("mpsdiag", hz/10);
  		else
***************
*** 172,178 ****
  	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);
  		else if (sleep_flag == CAN_SLEEP)
  			pause("mpsdiag", hz/20);
  		else
--- 182,189 ----
  	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);
  		else if (sleep_flag == CAN_SLEEP)
  			pause("mpsdiag", hz/20);
  		else
***************
*** 302,310 ****
  	return (error);
  }
  
  /* 
-  * 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
--- 313,669 ----
  	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);
+ }
+ 
  /* 
   * 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
***************
*** 316,322 ****
  mps_reinit(struct mps_softc *sc)
  {
  	int error;
- 	uint32_t db;
  
  	mps_printf(sc, "%s sc %p\n", __func__, sc);
  
--- 675,680 ----
***************
*** 332,344 ****
  	 */
  	sc->mps_flags |= MPS_FLAGS_DIAGRESET;
  
  	mps_printf(sc, "%s mask interrupts\n", __func__);
  	mps_mask_intr(sc);
  
  	error = mps_diag_reset(sc, CAN_SLEEP);
  	if (error != 0) {
! 		panic("%s hard reset failed with error %d\n",
! 		    __func__, error);
  	}
  
  	/* Restore the PCI state, including the MSI-X registers */
--- 690,704 ----
  	 */
  	sc->mps_flags |= MPS_FLAGS_DIAGRESET;
  
+ 	/*
+ 	 * Mask interrupts here.
+ 	 */
  	mps_printf(sc, "%s mask interrupts\n", __func__);
  	mps_mask_intr(sc);
  
  	error = mps_diag_reset(sc, CAN_SLEEP);
  	if (error != 0) {
! 		panic("%s hard reset failed with error %d\n", __func__, error);
  	}
  
  	/* Restore the PCI state, including the MSI-X registers */
***************
*** 347,395 ****
  	/* 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)
! 		panic("%s transition operational 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.
  	 */
! 	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_printf(sc, "%s doorbell 0x%08x\n", __func__, db);
! 
! 	mps_printf(sc, "%s unmask interrupts post %u free %u\n", __func__,
! 	    sc->replypostindex, sc->replyfreeindex);
! 
  	mps_unmask_intr(sc);
  
! 	mps_printf(sc, "%s restarting post %u free %u\n", __func__,
! 	    sc->replypostindex, sc->replyfreeindex);
  
! 	/* restart will reload the event masks clobbered by the reset, and
  	 * then enable the port.
  	 */
  	mps_reregister_events(sc);
  
  	/* the end of discovery will release the simq, so we're done. */
! 	mps_printf(sc, "%s finished sc %p post %u free %u\n", 
! 	    __func__, sc, 
  	    sc->replypostindex, sc->replyfreeindex);
  
- 	sc->mps_flags &= ~MPS_FLAGS_DIAGRESET;
- 
  	return 0;
  }
  
--- 707,756 ----
  	/* Give the I/O subsystem special priority to get itself prepared */
  	mpssas_handle_reinit(sc);
  
! 	/*
! 	 * 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);
+ 	}
  
! 	/*
! 	 * Mapping structures will be re-allocated after getting IOC Page8, so
! 	 * free these structures here.
  	 */
! 	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);
  
! 	/*
! 	 * 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
  	 * then enable the port.
  	 */
  	mps_reregister_events(sc);
  
  	/* the end of discovery will release the simq, so we're done. */
! 	mps_printf(sc, "%s finished sc %p post %u free %u\n", __func__, sc,
  	    sc->replypostindex, sc->replyfreeindex);
  
  	return 0;
  }
  
***************
*** 634,681 ****
  }
  
  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_dprint(sc, MPS_TRACE, "%s\n", __func__);
- 
- 	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;
  
  	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
  
--- 995,1007 ----
  }
  
  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_dprint(sc, MPS_TRACE, "%s\n", __func__);
  
***************
*** 704,711 ****
  	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);
  
  	error = mps_request_sync(sc, &init, &reply, req_sz, reply_sz, 5);
  	if ((reply.IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
--- 1030,1039 ----
  	init.ReplyDescriptorPostQueueAddress.Low = htole32((uint32_t)sc->post_busaddr);
  	init.ReplyFreeQueueAddress.High = 0;
  	init.ReplyFreeQueueAddress.Low = htole32((uint32_t)sc->free_busaddr);
! 	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)
***************
*** 1119,1125 ****
  int
  mps_attach(struct mps_softc *sc)
  {
! 	int i, error;
  
  	mps_get_tunables(sc);
  
--- 1447,1453 ----
  int
  mps_attach(struct mps_softc *sc)
  {
! 	int error;
  
  	mps_get_tunables(sc);
  
***************
*** 1141,1291 ****
  		 __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.
! 	 */
! 	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);
! 		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);
  
--- 1469,1488 ----
  		 __func__, __LINE__);
  		return (ENOMEM);
  	}
  
  	/*
! 	 * 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.
  	 */
! 	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);
  	}
  
  	/* Start the periodic watchdog check on the IOC Doorbell */
  	mps_periodic(sc);
  
***************
*** 1328,1334 ****
--- 1525,1533 ----
  
  	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);
***************
*** 1411,1418 ****
  int
  mps_free(struct mps_softc *sc)
  {
! 	struct mps_command *cm;
! 	int i, error;
  
  	/* Turn off the watchdog */
  	mps_lock(sc);
--- 1610,1616 ----
  int
  mps_free(struct mps_softc *sc)
  {
! 	int error;
  
  	/* Turn off the watchdog */
  	mps_lock(sc);
***************
*** 1438,1499 ****
  	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);
- 
  	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);
--- 1636,1650 ----
  	if (sc->facts != NULL)
  		free(sc->facts, M_MPT2);
  
! 	/*
! 	 * 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);
  
  	/* Deregister the shutdown function */
  	if (sc->shutdown_eh != NULL)
  		EVENTHANDLER_DEREGISTER(shutdown_final, sc->shutdown_eh);
***************
*** 1914,1920 ****
  
  	/* first, reregister events */
  
!     for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
  		sc->event_mask[i] = -1;
  
  	TAILQ_FOREACH(eh, &sc->event_list, eh_list) {
--- 2065,2071 ----
  
  	/* first, reregister events */
  
! 	for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
  		sc->event_mask[i] = -1;
  
  	TAILQ_FOREACH(eh, &sc->event_list, eh_list) {
***************
*** 1946,1952 ****
  
  	error = mps_map_command(sc, cm);
  
! 	mps_dprint(sc, MPS_TRACE, "%s finished with error %d\n", __func__, error);
  	return (error);
  }
  
--- 2097,2104 ----
  
  	error = mps_map_command(sc, cm);
  
! 	mps_dprint(sc, MPS_TRACE, "%s finished with error %d\n", __func__,
! 	    error);
  	return (error);
  }
  
***************
*** 2325,2350 ****
   * be executed and enqueued automatically.  Other errors come from msleep().
   */
  int
! mps_wait_command(struct mps_softc *sc, struct mps_command *cm, int timeout)
  {
  	int error, rc;
  
! 	mtx_assert(&sc->mps_mtx, MA_OWNED);
! 	
! 	if(sc->mps_flags & MPS_FLAGS_DIAGRESET) 
  		return  EBUSY;
  
  	cm->cm_complete = NULL;
! 	cm->cm_flags |= MPS_CM_FLAGS_WAKEUP;
  	error = mps_map_command(sc, cm);
  	if ((error != 0) && (error != EINPROGRESS))
  		return (error);
! 	error = msleep(cm, &sc->mps_mtx, 0, "mpswait", timeout*hz);
  	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");
  		error = ETIMEDOUT;
  	}
  	return (error);
--- 2477,2526 ----
   * be executed and enqueued automatically.  Other errors come from msleep().
   */
  int
! 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;
  
! 	if (sc->mps_flags & MPS_FLAGS_DIAGRESET) 
  		return  EBUSY;
  
  	cm->cm_complete = NULL;
! 	cm->cm_flags |= (MPS_CM_FLAGS_WAKEUP + MPS_CM_FLAGS_POLLED);
  	error = mps_map_command(sc, cm);
  	if ((error != 0) && (error != EINPROGRESS))
  		return (error);
! 
! 	// 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_pflags & TDP_NOSLEEPING)
! 		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");
  		error = ETIMEDOUT;
  	}
  	return (error);
***************
*** 2444,2450 ****
  		cm->cm_complete = mps_config_complete;
  		return (mps_map_command(sc, cm));
  	} else {
! 		error = mps_wait_command(sc, cm, 0);
  		if (error) {
  			mps_dprint(sc, MPS_FAULT,
  			    "Error %d reading config page\n", error);
--- 2620,2626 ----
  		cm->cm_complete = mps_config_complete;
  		return (mps_map_command(sc, cm));
  	} else {
! 		error = mps_wait_command(sc, cm, 0, CAN_SLEEP);
  		if (error) {
  			mps_dprint(sc, MPS_FAULT,
  			    "Error %d reading config page\n", error);
*** src/sys/dev/mps/mps_config.c.orig
--- src/sys/dev/mps/mps_config.c
***************
*** 93,104 ****
  	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);
  	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",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
--- 93,107 ----
  	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;
  	if (error || (reply == NULL)) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
! 		printf("%s: request for header completed with error %d",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
***************
*** 107,113 ****
  	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 */ 
  		printf("%s: header read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
--- 110,119 ----
  	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
  		printf("%s: header read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
***************
*** 144,155 ****
  		goto out;
  	}
  	cm->cm_data = page;
! 	error = mps_request_polled(sc, cm);
  	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",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
--- 150,165 ----
  		goto out;
  	}
  	cm->cm_data = page;
! 
! 	error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
  	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  	if (error || (reply == NULL)) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
! 		printf("%s: request for page completed with error %d",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
***************
*** 158,164 ****
  	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 */ 
  		printf("%s: page read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
--- 168,177 ----
  	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
  		printf("%s: page read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
***************
*** 211,216 ****
--- 224,234 ----
  	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,267 ****
--- 280,290 ----
  		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,572 ****
  	    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);
  	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",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
--- 584,598 ----
  	    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;
  	if (error || (reply == NULL)) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
! 		printf("%s: request for header completed with error %d",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
***************
*** 575,581 ****
  	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 */ 
  		printf("%s: header read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
--- 601,610 ----
  	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
  		printf("%s: header read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
***************
*** 615,626 ****
  		goto out;
  	}
  	cm->cm_data = page;
! 	error = mps_request_polled(sc, cm);
  	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",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
--- 644,658 ----
  		goto out;
  	}
  	cm->cm_data = page;
! 	error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
  	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  	if (error || (reply == NULL)) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
! 		printf("%s: request for page completed with error %d",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
***************
*** 629,635 ****
  	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 */ 
  		printf("%s: page read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
--- 661,670 ----
  	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
  		printf("%s: page read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
***************
*** 685,696 ****
  	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);
  	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",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
--- 720,734 ----
  	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;
  	if (error || (reply == NULL)) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
! 		printf("%s: request for header completed with error %d",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
***************
*** 699,705 ****
  	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 */ 
  		printf("%s: header read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
--- 737,746 ----
  	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
  		printf("%s: header read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
***************
*** 741,752 ****
  	bcopy(config_page, page, MIN(cm->cm_length, 
  	    (sizeof(Mpi2DriverMappingPage0_t))));
  	cm->cm_data = page;
! 	error = mps_request_polled(sc, cm);
  	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",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
--- 782,796 ----
  	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;
  	if (error || (reply == NULL)) {
  		/* FIXME */
! 		/*
! 		 * 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,761 ****
  	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 */ 
  		printf("%s: page written with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
--- 799,808 ----
  	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
  		printf("%s: page written with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
***************
*** 808,819 ****
  	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);
  	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",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
--- 855,869 ----
  	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;
  	if (error || (reply == NULL)) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
! 		printf("%s: request for header completed with error %d",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
***************
*** 822,828 ****
  	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 */ 
  		printf("%s: header read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
--- 872,881 ----
  	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
  		printf("%s: header read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
***************
*** 862,873 ****
  	}
  	cm->cm_data = page;
  
! 	error = mps_request_polled(sc, cm);
  	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",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
--- 915,929 ----
  	}
  	cm->cm_data = page;
  
! 	error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
  	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  	if (error || (reply == NULL)) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
! 		printf("%s: request for page completed with error %d",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
***************
*** 876,882 ****
  	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 */ 
  		printf("%s: page read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
--- 932,941 ----
  	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
  		printf("%s: page read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
***************
*** 928,939 ****
  	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);
  	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",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
--- 987,1001 ----
  	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;
  	if (error || (reply == NULL)) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
! 		printf("%s: request for header completed with error %d",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
***************
*** 942,948 ****
  	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 */ 
  		printf("%s: header read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
--- 1004,1013 ----
  	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
  		printf("%s: header read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
***************
*** 980,991 ****
  	}
  	cm->cm_data = page;
  
! 	error = mps_request_polled(sc, cm);
  	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",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
--- 1045,1059 ----
  	}
  	cm->cm_data = page;
  
! 	error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
  	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  	if (error || (reply == NULL)) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
! 		printf("%s: request for page completed with error %d",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
***************
*** 994,1000 ****
  	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 */ 
  		printf("%s: page read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
--- 1062,1071 ----
  	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
  		printf("%s: page read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
***************
*** 1046,1051 ****
--- 1117,1127 ----
  	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,1104 ****
--- 1175,1184 ----
  	}
  	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,1177 ****
  	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);
  	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",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
--- 1246,1260 ----
  	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;
  	if (error || (reply == NULL)) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
! 		printf("%s: request for header completed with error %d",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
***************
*** 1180,1186 ****
  	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 */ 
  		printf("%s: header read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
--- 1263,1272 ----
  	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
  		printf("%s: header read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
***************
*** 1219,1230 ****
  	}
  	cm->cm_data = page;
  
! 	error = mps_request_polled(sc, cm);
  	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",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
--- 1305,1319 ----
  	}
  	cm->cm_data = page;
  
! 	error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
  	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  	if (error || (reply == NULL)) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
! 		printf("%s: request for page completed with error %d",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
***************
*** 1233,1239 ****
  	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 */ 
  		printf("%s: page read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
--- 1322,1331 ----
  	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  		/* FIXME */
! 		/*
! 		 * If the request returns an error then we need to do a diag
! 		 * reset
! 		 */ 
  		printf("%s: page read with error; iocstatus = 0x%x\n",
  		    __func__, ioc_status);
  		error = ENXIO;
***************
*** 1311,1316 ****
--- 1403,1413 ----
  	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,1369 ****
--- 1461,1470 ----
  	}
  	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)) {
*** src/sys/dev/mps/mps_mapping.c.orig
--- src/sys/dev/mps/mps_mapping.c
***************
*** 1216,1227 ****
  						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__,
  						    phy_change->dev_handle);
  					}
  				} else {
--- 1216,1227 ----
  						phy_change->is_processed = 1;
  					} else {
  						phy_change->is_processed = 1;
! 						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 {
***************
*** 1318,1329 ****
  					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__,
  						    phy_change->dev_handle);
  				}
  			}
--- 1318,1329 ----
  					phy_change->is_processed = 1;
  				} else if (dpm_idx == MPS_DPM_BAD_IDX) {
  						phy_change->is_processed = 1;
! 						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);
  				}
  			}
*** src/sys/dev/mps/mps_sas.c.orig
--- src/sys/dev/mps/mps_sas.c
***************
*** 136,149 ****
  static void mpssas_resetdev_complete(struct mps_softc *, struct mps_command *);
  static int  mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_command *cm);
  static int  mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type);
- static void mpssas_rescan(struct mpssas_softc *sassc, union ccb *ccb);
- static void mpssas_rescan_done(struct cam_periph *periph, union ccb *done_ccb);
- static void mpssas_scanner_thread(void *arg);
- #if __FreeBSD_version >= 1000006
  static void mpssas_async(void *callback_arg, uint32_t code,
  			 struct cam_path *path, void *arg);
! #else
! static void mpssas_check_eedp(struct mpssas_softc *sassc);
  static void mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb);
  #endif
  static int mpssas_send_portenable(struct mps_softc *sc);
--- 136,147 ----
  static void mpssas_resetdev_complete(struct mps_softc *, struct mps_command *);
  static int  mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_command *cm);
  static int  mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type);
  static void mpssas_async(void *callback_arg, uint32_t code,
  			 struct cam_path *path, void *arg);
! #if (__FreeBSD_version < 901503) || \
!     ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006))
! static void mpssas_check_eedp(struct mps_softc *sc, struct cam_path *path,
! 			      struct ccb_getdev *cgd);
  static void mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb);
  #endif
  static int mpssas_send_portenable(struct mps_softc *sc);
***************
*** 198,205 ****
--- 196,208 ----
  			mps_dprint(sassc->sc, MPS_INFO,
  			    "%s releasing simq\n", __func__);
  			sassc->flags &= ~MPSSAS_IN_STARTUP;
+ #if (__FreeBSD_version >= 1000036) || \
+     ((__FreeBSD_version < 1000000) && (__FreeBSD_version >= 9010506))
+ 			xpt_release_boot();
+ #else
  			xpt_release_simq(sassc->sim, 1);
  			mpssas_rescan_target(sassc->sc, NULL);
+ #endif
  		}
  		mps_dprint(sassc->sc, MPS_TRACE, "%s refcount %u\n", __func__,
  		    sassc->startup_refcount);
***************
*** 247,253 ****
  	mps_free_high_priority_command(sc, tm);
  }
  
- 
  void
  mpssas_rescan_target(struct mps_softc *sc, struct mpssas_target *targ)
  {
--- 250,255 ----
***************
*** 272,278 ****
  	}
  
  	if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, pathid,
! 		            targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  		mps_dprint(sc, MPS_FAULT, "unable to create path for rescan\n");
  		xpt_free_ccb(ccb);
  		return;
--- 274,280 ----
  	}
  
  	if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, pathid,
! 	    targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  		mps_dprint(sc, MPS_FAULT, "unable to create path for rescan\n");
  		xpt_free_ccb(ccb);
  		return;
***************
*** 284,290 ****
  		ccb->ccb_h.func_code = XPT_SCAN_TGT;     
  
  	mps_dprint(sc, MPS_TRACE, "%s targetid %u\n", __func__, targetid);
! 	mpssas_rescan(sassc, ccb);
  }
  
  static void
--- 286,292 ----
  		ccb->ccb_h.func_code = XPT_SCAN_TGT;     
  
  	mps_dprint(sc, MPS_TRACE, "%s targetid %u\n", __func__, targetid);
! 	xpt_rescan(ccb);
  }
  
  static void
***************
*** 671,679 ****
  mps_attach_sas(struct mps_softc *sc)
  {
  	struct mpssas_softc *sassc;
- #if __FreeBSD_version >= 1000006
  	cam_status status;
- #endif
  	int unit, error = 0;
  
  	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
--- 673,679 ----
***************
*** 721,736 ****
  	taskqueue_start_threads(&sassc->ev_tq, 1, 255, "%s taskq", 
  	    device_get_nameunit(sc->mps_dev));
  
- 	TAILQ_INIT(&sassc->ccb_scanq);
- 	error = mps_kproc_create(mpssas_scanner_thread, sassc,
- 	    &sassc->rescan_thread, 0, 0, "mps_scan%d", unit);
- 	if (error) {
- 		mps_printf(sc, "Error %d starting rescan thread\n", error);
- 		goto out;
- 	}
- 
  	mps_lock(sc);
- 	sassc->flags |= MPSSAS_SCANTHREAD;
  
  	/*
  	 * XXX There should be a bus for every port on the adapter, but since
--- 721,727 ----
***************
*** 745,756 ****
  	}
  
  	/*
! 	 * Assume that discovery events will start right away.  Freezing
! 	 * the simq will prevent the CAM boottime scanner from running
! 	 * before discovery is complete.
  	 */
  	sassc->flags |= MPSSAS_IN_STARTUP | MPSSAS_IN_DISCOVERY;
  	xpt_freeze_simq(sassc->sim, 1);
  	sc->sassc->startup_refcount = 0;
  
  	callout_init(&sassc->discovery_callout, 1 /*mpsafe*/);
--- 736,752 ----
  	}
  
  	/*
! 	 * Assume that discovery events will start right away.
! 	 *
! 	 * Hold off boot until discovery is complete.
  	 */
  	sassc->flags |= MPSSAS_IN_STARTUP | MPSSAS_IN_DISCOVERY;
+ #if (__FreeBSD_version >= 1000036) || \
+     ((__FreeBSD_version < 1000000) && (__FreeBSD_version >= 9010506))
+ 	xpt_hold_boot();
+ #else
  	xpt_freeze_simq(sassc->sim, 1);
+ #endif
  	sc->sassc->startup_refcount = 0;
  
  	callout_init(&sassc->discovery_callout, 1 /*mpsafe*/);
***************
*** 758,770 ****
  
  	sassc->tm_count = 0;
  
! #if __FreeBSD_version >= 1000006
! 	status = xpt_register_async(AC_ADVINFO_CHANGED, mpssas_async, sc, NULL);
  	if (status != CAM_REQ_CMP) {
! 		mps_printf(sc, "Error %#x registering async handler for "
! 			   "AC_ADVINFO_CHANGED events\n", status);
  	}
- #endif
  
  	mps_unlock(sc);
  
--- 754,794 ----
  
  	sassc->tm_count = 0;
  
! 	/*
! 	 * Register for async events so we can determine the EEDP
! 	 * capabilities of devices.
! 	 */
! 	status = xpt_create_path(&sassc->path, /*periph*/NULL,
! 	    cam_sim_path(sc->sassc->sim), CAM_TARGET_WILDCARD,
! 	    CAM_LUN_WILDCARD);
! 	if (status != CAM_REQ_CMP) {
! 		mps_printf(sc, "Error %#x creating sim path\n", status);
! 		sassc->path = NULL;
! 	} else {
! 		int event;
! 
! #if (__FreeBSD_version >= 1000006) || \
!     ((__FreeBSD_version >= 901503) && (__FreeBSD_version < 1000000))
! 		event = AC_ADVINFO_CHANGED;
! #else
! 		event = AC_FOUND_DEVICE;
! #endif
! 		status = xpt_register_async(event, mpssas_async, sc,
! 					    sassc->path);
! 		if (status != CAM_REQ_CMP) {
! 			mps_printf(sc, "Error %#x registering async handler "
! 				   "for event type 0x%x\n", status, event);
! 			xpt_free_path(sassc->path);
! 			sassc->path = NULL;
! 		}
! 	}
  	if (status != CAM_REQ_CMP) {
! 		/*
! 		 * EEDP use is the exception, not the rule.
! 		 * Warn the user, but do not fail to attach.
! 		 */
! 		mps_printf(sc, "EEDP capabilities disabled.\n");
  	}
  
  	mps_unlock(sc);
  
***************
*** 803,811 ****
  	mps_lock(sc);
  
  	/* Deregister our async handler */
! #if __FreeBSD_version >= 1000006
! 	xpt_register_async(0, mpssas_async, sc, NULL);
! #endif
  
  	if (sassc->flags & MPSSAS_IN_STARTUP)
  		xpt_release_simq(sassc->sim, 1);
--- 827,837 ----
  	mps_lock(sc);
  
  	/* Deregister our async handler */
! 	if (sassc->path != NULL) {
! 		xpt_register_async(0, mpssas_async, sc, sassc->path);
! 		xpt_free_path(sassc->path);
! 		sassc->path = NULL;
! 	}
  
  	if (sassc->flags & MPSSAS_IN_STARTUP)
  		xpt_release_simq(sassc->sim, 1);
***************
*** 815,829 ****
  		cam_sim_free(sassc->sim, FALSE);
  	}
  
! 	if (sassc->flags & MPSSAS_SCANTHREAD) {
! 		sassc->flags |= MPSSAS_SHUTDOWN;
! 		wakeup(&sassc->ccb_scanq);
! 		
! 		if (sassc->flags & MPSSAS_SCANTHREAD) {
! 			msleep(&sassc->flags, &sc->mps_mtx, PRIBIO,
! 			       "mps_shutdown", 30 * hz);
! 		}
! 	}
  	mps_unlock(sc);
  
  	mps_dprint(sc, MPS_INFO, "%s:%d\n", __func__,__LINE__);
--- 841,847 ----
  		cam_sim_free(sassc->sim, FALSE);
  	}
  
! 	sassc->flags |= MPSSAS_SHUTDOWN;
  	mps_unlock(sc);
  
  	mps_dprint(sc, MPS_INFO, "%s:%d\n", __func__,__LINE__);
***************
*** 914,920 ****
--- 932,943 ----
  		cpi->version_num = 1;
  		cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
  		cpi->target_sprt = 0;
+ #if (__FreeBSD_version >= 1000036) || \
+     ((__FreeBSD_version < 1000000) && (__FreeBSD_version >= 9010506))
+ 		cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED | PIM_NOSCAN;
+ #else
  		cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED;
+ #endif
  		cpi->hba_eng_cnt = 0;
  		cpi->max_target = sassc->sc->facts->MaxTargets - 1;
  		cpi->max_lun = 255;
***************
*** 1580,1586 ****
  
  	csio = &ccb->csio;
  	targ = &sassc->targets[csio->ccb_h.target_id];
! 	mps_dprint(sc, MPS_TRACE, "%s ccb %p target flag %x\n", __func__, ccb, targ->flags);
  	if (targ->handle == 0x0) {
  		mps_dprint(sc, MPS_TRACE, "%s NULL handle for target %u\n", 
  		    __func__, csio->ccb_h.target_id);
--- 1603,1610 ----
  
  	csio = &ccb->csio;
  	targ = &sassc->targets[csio->ccb_h.target_id];
! 	mps_dprint(sc, MPS_TRACE, "%s ccb %p target flag %x\n", __func__, ccb,
! 	    targ->flags);
  	if (targ->handle == 0x0) {
  		mps_dprint(sc, MPS_TRACE, "%s NULL handle for target %u\n", 
  		    __func__, csio->ccb_h.target_id);
***************
*** 1589,1601 ****
  		return;
  	}
  	if (targ->flags & MPS_TARGET_FLAGS_RAID_COMPONENT) {
! 		mps_dprint(sc, MPS_TRACE, "%s Raid component no SCSI IO supported %u\n", 
! 		    __func__, csio->ccb_h.target_id);
  		csio->ccb_h.status = CAM_TID_INVALID;
  		xpt_done(ccb);
  		return;
  	}
  	/*
  	 * If devinfo is 0 this will be a volume.  In that case don't tell CAM
  	 * that the volume has timed out.  We want volumes to be enumerated
  	 * until they are deleted/removed, not just failed.
--- 1613,1636 ----
  		return;
  	}
  	if (targ->flags & MPS_TARGET_FLAGS_RAID_COMPONENT) {
! 		mps_dprint(sc, MPS_TRACE, "%s Raid component no SCSI IO "
! 		    "supported %u\n", __func__, csio->ccb_h.target_id);
  		csio->ccb_h.status = CAM_TID_INVALID;
  		xpt_done(ccb);
  		return;
  	}
  	/*
+ 	 * 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.
***************
*** 1663,1669 ****
  		break;
  	}
   
!   if (csio->cdb_len == 32)
                  mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT;
  	/*
  	 * It looks like the hardware doesn't require an explicit tag
--- 1698,1704 ----
  		break;
  	}
   
! 	if (csio->cdb_len == 32)
                  mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT;
  	/*
  	 * It looks like the hardware doesn't require an explicit tag
***************
*** 1791,1796 ****
--- 1826,1832 ----
  	targ->issued++;
  	targ->outstanding++;
  	TAILQ_INSERT_TAIL(&targ->commands, cm, cm_link);
+ 	ccb->ccb_h.status |= CAM_SIM_QUEUED;
  
  	if ((sc->mps_debug & MPS_TRACE) != 0)
  		mpssas_log_command(cm, "%s cm %p ccb %p outstanding %u\n",
***************
*** 1969,1982 ****
  		strcat(desc_scsi_state, "autosense valid ");
  
  	mps_dprint(sc, MPS_INFO, "\thandle(0x%04x), ioc_status(%s)(0x%04x), \n",
! 		le16toh(mpi_reply->DevHandle),
! 	    desc_ioc_state, ioc_status);
  	/* We can add more detail about underflow data here
  	 * TO-DO
  	 * */
  	mps_dprint(sc, MPS_INFO, "\tscsi_status(%s)(0x%02x), "
! 	    "scsi_state(%s)(0x%02x)\n", desc_scsi_status,
! 	    scsi_status, desc_scsi_state, scsi_state);
  
  	if (sc->mps_debug & MPS_INFO &&
  		scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
--- 2005,2017 ----
  		strcat(desc_scsi_state, "autosense valid ");
  
  	mps_dprint(sc, MPS_INFO, "\thandle(0x%04x), ioc_status(%s)(0x%04x), \n",
! 	    le16toh(mpi_reply->DevHandle), desc_ioc_state, ioc_status);
  	/* We can add more detail about underflow data here
  	 * TO-DO
  	 * */
  	mps_dprint(sc, MPS_INFO, "\tscsi_status(%s)(0x%02x), "
! 	    "scsi_state(%s)(0x%02x)\n", desc_scsi_status, scsi_status,
! 	    desc_scsi_state, scsi_state);
  
  	if (sc->mps_debug & MPS_INFO &&
  		scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
***************
*** 2033,2038 ****
--- 2068,2074 ----
  	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);
***************
*** 2108,2114 ****
  				ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
  				sassc->flags &= ~MPSSAS_QUEUE_FROZEN;
  				mps_dprint(sc, MPS_INFO,
! 					   "Unfreezing SIM queue\n");
  			}
  		} 
  
--- 2144,2150 ----
  				ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
  				sassc->flags &= ~MPSSAS_QUEUE_FROZEN;
  				mps_dprint(sc, MPS_INFO,
! 				    "Unfreezing SIM queue\n");
  			}
  		} 
  
***************
*** 2335,2341 ****
  		ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
  		sassc->flags &= ~MPSSAS_QUEUE_FROZEN;
  		mps_dprint(sc, MPS_INFO, "Command completed, "
! 			   "unfreezing SIM queue\n");
  	}
  
  	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
--- 2371,2377 ----
  		ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
  		sassc->flags &= ~MPSSAS_QUEUE_FROZEN;
  		mps_dprint(sc, MPS_INFO, "Command completed, "
! 		    "unfreezing SIM queue\n");
  	}
  
  	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
***************
*** 2651,2657 ****
  	sasaddr = le32toh(req->SASAddress.Low);
  	sasaddr |= ((uint64_t)(le32toh(req->SASAddress.High))) << 32;
  
! 	if ((le16toh(rpl->IOCStatus) & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS ||
  	    rpl->SASStatus != MPI2_SASSTATUS_SUCCESS) {
  		mps_dprint(sc, MPS_INFO, "%s: IOCStatus %04x SASStatus %02x\n",
  		    __func__, le16toh(rpl->IOCStatus), rpl->SASStatus);
--- 2687,2694 ----
  	sasaddr = le32toh(req->SASAddress.Low);
  	sasaddr |= ((uint64_t)(le32toh(req->SASAddress.High))) << 32;
  
! 	if ((le16toh(rpl->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
! 	    MPI2_IOCSTATUS_SUCCESS ||
  	    rpl->SASStatus != MPI2_SASSTATUS_SUCCESS) {
  		mps_dprint(sc, MPS_INFO, "%s: IOCStatus %04x SASStatus %02x\n",
  		    __func__, le16toh(rpl->IOCStatus), rpl->SASStatus);
***************
*** 2774,2780 ****
  	    MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE | MPI2_SGLFLAGS_SGL_TYPE_MPI;
  
  	mps_dprint(sc, MPS_INFO, "%s: sending SMP request to SAS "
! 		   "address %#jx\n", __func__, (uintmax_t)sasaddr);
  
  	mpi_init_sge(cm, req, &req->SGL);
  
--- 2811,2817 ----
  	    MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE | MPI2_SGLFLAGS_SGL_TYPE_MPI;
  
  	mps_dprint(sc, MPS_INFO, "%s: sending SMP request to SAS "
! 	    "address %#jx\n", __func__, (uintmax_t)sasaddr);
  
  	mpi_init_sge(cm, req, &req->SGL);
  
***************
*** 2992,2998 ****
  	sc = sassc->sc;
  	tm = mps_alloc_command(sc);
  	if (tm == NULL) {
! 		mps_printf(sc, "comand alloc failure in mpssas_action_resetdev\n");
  		ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
  		xpt_done(ccb);
  		return;
--- 3029,3036 ----
  	sc = sassc->sc;
  	tm = mps_alloc_command(sc);
  	if (tm == NULL) {
! 		mps_printf(sc, "comand alloc failure in "
! 		    "mpssas_action_resetdev\n");
  		ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
  		xpt_done(ccb);
  		return;
***************
*** 3080,3193 ****
  }
  
  static void
- mpssas_rescan_done(struct cam_periph *periph, union ccb *done_ccb)
- {
- 	struct mpssas_softc *sassc;
- 	char path_str[64];
- 
- 	if (done_ccb == NULL)
- 		return;
- 
- 	sassc = (struct mpssas_softc *)done_ccb->ccb_h.ppriv_ptr1;
- 
- 	mtx_assert(&sassc->sc->mps_mtx, MA_OWNED);
- 
- 	xpt_path_string(done_ccb->ccb_h.path, path_str, sizeof(path_str));
- 	mps_dprint(sassc->sc, MPS_INFO, "Completing rescan for %s\n", path_str);
- 
- 	xpt_free_path(done_ccb->ccb_h.path);
- 	xpt_free_ccb(done_ccb);
- 
- #if __FreeBSD_version < 1000006
- 	/*
- 	 * Before completing scan, get EEDP stuff for all of the existing
- 	 * targets.
- 	 */
- 	mpssas_check_eedp(sassc);
- #endif
- 
- }
- 
- /* thread to handle bus rescans */
- static void
- mpssas_scanner_thread(void *arg)
- {
- 	struct mpssas_softc *sassc;
- 	struct mps_softc *sc;
- 	union ccb	*ccb;
- 
- 	sassc = (struct mpssas_softc *)arg;
- 	sc = sassc->sc;
- 
- 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
- 
- 	mps_lock(sc);
- 	for (;;) {
- 		/* Sleep for 1 second and check the queue status*/
- 		msleep(&sassc->ccb_scanq, &sc->mps_mtx, PRIBIO,
- 		       "mps_scanq", 1 * hz);
- 		if (sassc->flags & MPSSAS_SHUTDOWN) {
- 			mps_dprint(sc, MPS_TRACE, "Scanner shutting down\n");
- 			break;
- 		}
- next_work:
- 		// Get first work.
- 		ccb = (union ccb *)TAILQ_FIRST(&sassc->ccb_scanq);
- 		if (ccb == NULL)
- 			continue;
- 		// Got first work.
- 		TAILQ_REMOVE(&sassc->ccb_scanq, &ccb->ccb_h, sim_links.tqe);
- 		xpt_action(ccb);
- 		if (sassc->flags & MPSSAS_SHUTDOWN) {
- 			mps_dprint(sc, MPS_TRACE, "Scanner shutting down\n");
- 			break;
- 		}
- 		goto next_work;
- 	}
- 
- 	sassc->flags &= ~MPSSAS_SCANTHREAD;
- 	wakeup(&sassc->flags);
- 	mps_unlock(sc);
- 	mps_dprint(sc, MPS_TRACE, "Scanner exiting\n");
- 	mps_kproc_exit(0);
- }
- 
- /*
-  * This function will send READ_CAP_16 to find out EEDP protection mode.
-  * It will check inquiry data before sending READ_CAP_16.
-  * Callback for READ_CAP_16 is "mpssas_read_cap_done".
-  * This is insternal scsi command and we need to take care release of devq, if
-  * CAM_DEV_QFRZN is set. Driver needs to release devq if it has frozen any.
-  * xpt_release_devq is called from mpssas_read_cap_done.
-  *
-  * All other commands will be handled by periph layer and there it will 
-  * check for "CAM_DEV_QFRZN" and release of devq will be done.
-  */
- static void
- mpssas_rescan(struct mpssas_softc *sassc, union ccb *ccb)
- {
- 	char path_str[64];
- 
- 	mps_dprint(sassc->sc, MPS_TRACE, "%s\n", __func__);
- 
- 	mtx_assert(&sassc->sc->mps_mtx, MA_OWNED);
- 
- 	if (ccb == NULL)
- 		return;
- 
- 	xpt_path_string(ccb->ccb_h.path, path_str, sizeof(path_str));
- 	mps_dprint(sassc->sc, MPS_INFO, "Queueing rescan for %s\n", path_str);
- 
- 	/* Prepare request */
- 	ccb->ccb_h.ppriv_ptr1 = sassc;
- 	ccb->ccb_h.cbfcnp = mpssas_rescan_done;
- 	xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, MPS_PRIORITY_XPT);
- 	TAILQ_INSERT_TAIL(&sassc->ccb_scanq, &ccb->ccb_h, sim_links.tqe);
- 	wakeup(&sassc->ccb_scanq);
- }
- 
- #if __FreeBSD_version >= 1000006
- static void
  mpssas_async(void *callback_arg, uint32_t code, struct cam_path *path,
  	     void *arg)
  {
--- 3118,3123 ----
***************
*** 3196,3201 ****
--- 3126,3133 ----
  	sc = (struct mps_softc *)callback_arg;
  
  	switch (code) {
+ #if (__FreeBSD_version >= 1000006) || \
+     ((__FreeBSD_version >= 901503) && (__FreeBSD_version < 1000000))
  	case AC_ADVINFO_CHANGED: {
  		struct mpssas_target *target;
  		struct mpssas_softc *sassc;
***************
*** 3218,3230 ****
  			break;
  
  		/*
- 		 * We're only interested in devices that are attached to
- 		 * this controller.
- 		 */
- 		if (xpt_path_path_id(path) != sassc->sim->path_id)
- 			break;
- 
- 		/*
  		 * We should have a handle for this, but check to make sure.
  		 */
  		target = &sassc->targets[xpt_path_target_id(path)];
--- 3150,3155 ----
***************
*** 3275,3452 ****
  		}
  		break;
  	}
  	default:
  		break;
  	}
  }
- #else /* __FreeBSD_version >= 1000006 */
  
  static void
! mpssas_check_eedp(struct mpssas_softc *sassc)
  {
! 	struct mps_softc *sc = sassc->sc;
  	struct ccb_scsiio *csio;
  	struct scsi_read_capacity_16 *scsi_cmd;
  	struct scsi_read_capacity_eedp *rcap_buf;
! 	union ccb *ccb;
! 	path_id_t pathid = cam_sim_path(sassc->sim);
  	target_id_t targetid;
  	lun_id_t lunid;
! 	struct cam_periph *found_periph;
  	struct mpssas_target *target;
  	struct mpssas_lun *lun;
  	uint8_t	found_lun;
- 	struct ccb_getdev cgd;
  	char path_str[64];
  
  	/*
! 	 * Issue a READ CAPACITY 16 command to each LUN of each target.  This
! 	 * info is used to determine if the LUN is formatted for EEDP support.
  	 */
! 	for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) {
! 		target = &sassc->targets[targetid];
! 		if (target->handle == 0x0) {
! 			continue;
! 		}
  
! 		lunid = 0;
! 		do {
! 			ccb = xpt_alloc_ccb_nowait();
! 			if (ccb == NULL) {
! 				mps_dprint(sc, MPS_FAULT, "Unable to alloc CCB "
! 				    "for EEDP support.\n");
! 				return;
! 			}
  
! 			if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
! 			    pathid, targetid, lunid) != CAM_REQ_CMP) {
! 				mps_dprint(sc, MPS_FAULT, "Unable to create "
! 				    "path for EEDP support\n");
! 				xpt_free_ccb(ccb);
! 				return;
! 			}
  
! 			/*
! 			 * If a periph is returned, the LUN exists.  Create an
! 			 * entry in the target's LUN list.
! 			 */
! 			if ((found_periph = cam_periph_find(ccb->ccb_h.path,
! 			    NULL)) != NULL) {
! 				/*
! 				 * If LUN is already in list, don't create a new
! 				 * one.
! 				 */
! 				found_lun = FALSE;
! 				SLIST_FOREACH(lun, &target->luns, lun_link) {
! 					if (lun->lun_id == lunid) {
! 						found_lun = TRUE;
! 						break;
! 					}
! 				}
! 				if (!found_lun) {
! 					lun = malloc(sizeof(struct mpssas_lun),
! 					    M_MPT2, M_NOWAIT | M_ZERO);
! 					if (lun == NULL) {
! 						mps_dprint(sc, MPS_FAULT,
! 						    "Unable to alloc LUN for "
! 						    "EEDP support.\n");
! 						xpt_free_path(ccb->ccb_h.path);
! 						xpt_free_ccb(ccb);
! 						return;
! 					}
! 					lun->lun_id = lunid;
! 					SLIST_INSERT_HEAD(&target->luns, lun,
! 					    lun_link);
! 				}
! 				lunid++;
! 				/* Before Issuing READ CAPACITY 16, 
! 				 * check Device type. 
!  				 */
! 				xpt_setup_ccb(&cgd.ccb_h, ccb->ccb_h.path, 
! 					CAM_PRIORITY_NORMAL);
! 				cgd.ccb_h.func_code = XPT_GDEV_TYPE;
! 				xpt_action((union ccb *)&cgd);
  
! 				/*
! 				 * If this flag is set in the inquiry data, 
! 				 * the device supports protection information,
! 				 * and must support the 16 byte read
! 				 * capacity command, otherwise continue without
! 				 * sending read cap 16
! 				 */
  
! 				xpt_path_string(ccb->ccb_h.path, path_str, 
! 					sizeof(path_str));
  
! 				if ((cgd.inq_data.spc3_flags & 
! 				SPC3_SID_PROTECT) == 0) {
! 					xpt_free_path(ccb->ccb_h.path);
! 					xpt_free_ccb(ccb);
! 					continue;
! 				}
! 				
! 				mps_dprint(sc, MPS_INFO,
! 				"Sending read cap: path %s"
! 				" handle %d\n", path_str, target->handle );
! 			
! 				/*
! 				 * Issue a READ CAPACITY 16 command for the LUN.
! 				 * The mpssas_read_cap_done function will load
! 				 * the read cap info into the LUN struct.
! 				 */
! 				rcap_buf =
! 					malloc(sizeof(struct scsi_read_capacity_eedp),
! 					M_MPT2, M_NOWAIT| M_ZERO);
! 				if (rcap_buf == NULL) {
! 					mps_dprint(sc, MPS_FAULT, "Unable to alloc read "
! 						"capacity buffer for EEDP support.\n");
! 					xpt_free_path(ccb->ccb_h.path);
! 					xpt_free_ccb(ccb);
! 					return;
! 				}
! 				csio = &ccb->csio;
! 				csio->ccb_h.func_code = XPT_SCSI_IO;
! 				csio->ccb_h.flags = CAM_DIR_IN;
! 				csio->ccb_h.retry_count = 4;	
! 				csio->ccb_h.cbfcnp = mpssas_read_cap_done;
! 				csio->ccb_h.timeout = 60000;
! 				csio->data_ptr = (uint8_t *)rcap_buf;
! 				csio->dxfer_len = sizeof(struct
! 				    scsi_read_capacity_eedp);
! 				csio->sense_len = MPS_SENSE_LEN;
! 				csio->cdb_len = sizeof(*scsi_cmd);
! 				csio->tag_action = MSG_SIMPLE_Q_TAG;
  
! 				scsi_cmd = (struct scsi_read_capacity_16 *)
! 				    &csio->cdb_io.cdb_bytes;
! 				bzero(scsi_cmd, sizeof(*scsi_cmd));
! 				scsi_cmd->opcode = 0x9E;
! 				scsi_cmd->service_action = SRC16_SERVICE_ACTION;
! 				((uint8_t *)scsi_cmd)[13] = sizeof(struct
! 				    scsi_read_capacity_eedp);
! 
! 				/*
! 				 * Set the path, target and lun IDs for the READ
! 				 * CAPACITY request.
! 				 */
! 				ccb->ccb_h.path_id =
! 				    xpt_path_path_id(ccb->ccb_h.path);
! 				ccb->ccb_h.target_id =
! 				    xpt_path_target_id(ccb->ccb_h.path);
! 				ccb->ccb_h.target_lun =
! 				    xpt_path_lun_id(ccb->ccb_h.path);
! 
! 				ccb->ccb_h.ppriv_ptr1 = sassc;
! 				xpt_action(ccb);
! 			} else {
! 				xpt_free_path(ccb->ccb_h.path);
! 				xpt_free_ccb(ccb);
! 			}
! 		} while (found_periph);
! 	}
  }
  
- 
  static void
  mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb)
  {
--- 3200,3347 ----
  		}
  		break;
  	}
+ #else
+ 	case AC_FOUND_DEVICE: {
+ 		struct ccb_getdev *cgd;
+ 
+ 		cgd = arg;
+ 		mpssas_check_eedp(sc, path, cgd);
+ 		break;
+ 	}
+ #endif
  	default:
  		break;
  	}
  }
  
+ #if (__FreeBSD_version < 901503) || \
+     ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006))
  static void
! mpssas_check_eedp(struct mps_softc *sc, struct cam_path *path,
! 		  struct ccb_getdev *cgd)
  {
! 	struct mpssas_softc *sassc = sc->sassc;
  	struct ccb_scsiio *csio;
  	struct scsi_read_capacity_16 *scsi_cmd;
  	struct scsi_read_capacity_eedp *rcap_buf;
! 	path_id_t pathid;
  	target_id_t targetid;
  	lun_id_t lunid;
! 	union ccb *ccb;
! 	struct cam_path *local_path;
  	struct mpssas_target *target;
  	struct mpssas_lun *lun;
  	uint8_t	found_lun;
  	char path_str[64];
  
+ 	sassc = sc->sassc;
+ 	pathid = cam_sim_path(sassc->sim);
+ 	targetid = xpt_path_target_id(path);
+ 	lunid = xpt_path_lun_id(path);
+ 
+ 	target = &sassc->targets[targetid];
+ 	if (target->handle == 0x0)
+ 		return;
+ 
  	/*
! 	 * Determine if the device is EEDP capable.
! 	 *
! 	 * If this flag is set in the inquiry data, 
! 	 * the device supports protection information,
! 	 * and must support the 16 byte read
! 	 * capacity command, otherwise continue without
! 	 * sending read cap 16
  	 */
! 	if ((cgd->inq_data.spc3_flags & SPC3_SID_PROTECT) == 0)
! 		return;
  
! 	/*
! 	 * Issue a READ CAPACITY 16 command.  This info
! 	 * is used to determine if the LUN is formatted
! 	 * for EEDP support.
! 	 */
! 	ccb = xpt_alloc_ccb_nowait();
! 	if (ccb == NULL) {
! 		mps_dprint(sc, MPS_FAULT,
! 		    "Unable to alloc CCB for EEDP support.\n");
! 		return;
! 	}
  
! 	if (xpt_create_path(&local_path, xpt_periph,
! 	    pathid, targetid, lunid) != CAM_REQ_CMP) {
! 		mps_dprint(sc, MPS_FAULT,
! 		    "Unable to create path for EEDP support\n");
! 		xpt_free_ccb(ccb);
! 		return;
! 	}
  
! 	/*
! 	 * If LUN is already in list, don't create a new
! 	 * one.
! 	 */
! 	found_lun = FALSE;
! 	SLIST_FOREACH(lun, &target->luns, lun_link) {
! 		if (lun->lun_id == lunid) {
! 			found_lun = TRUE;
! 			break;
! 		}
! 	}
! 	if (!found_lun) {
! 		lun = malloc(sizeof(struct mpssas_lun), M_MPT2,
! 		    M_NOWAIT | M_ZERO);
! 		if (lun == NULL) {
! 			mps_dprint(sc, MPS_FAULT,
! 			    "Unable to alloc LUN for EEDP support.\n");
! 			xpt_free_path(local_path);
! 			xpt_free_ccb(ccb);
! 			return;
! 		}
! 		lun->lun_id = lunid;
! 		SLIST_INSERT_HEAD(&target->luns, lun,
! 		    lun_link);
! 	}
  
! 	xpt_path_string(local_path, path_str, sizeof(path_str));
! 	mps_dprint(sc, MPS_INFO, "Sending read cap: path %s handle %d\n",
! 	    path_str, target->handle);
  
! 	/*
! 	 * Issue a READ CAPACITY 16 command for the LUN.
! 	 * The mpssas_read_cap_done function will load
! 	 * the read cap info into the LUN struct.
! 	 */
! 	rcap_buf = malloc(sizeof(struct scsi_read_capacity_eedp),
! 	    M_MPT2, M_NOWAIT | M_ZERO);
! 	if (rcap_buf == NULL) {
! 		mps_dprint(sc, MPS_FAULT,
! 		    "Unable to alloc read capacity buffer for EEDP support.\n");
! 		xpt_free_path(ccb->ccb_h.path);
! 		xpt_free_ccb(ccb);
! 		return;
! 	}
! 	xpt_setup_ccb(&ccb->ccb_h, local_path, CAM_PRIORITY_XPT);
! 	csio = &ccb->csio;
! 	csio->ccb_h.func_code = XPT_SCSI_IO;
! 	csio->ccb_h.flags = CAM_DIR_IN;
! 	csio->ccb_h.retry_count = 4;	
! 	csio->ccb_h.cbfcnp = mpssas_read_cap_done;
! 	csio->ccb_h.timeout = 60000;
! 	csio->data_ptr = (uint8_t *)rcap_buf;
! 	csio->dxfer_len = sizeof(struct scsi_read_capacity_eedp);
! 	csio->sense_len = MPS_SENSE_LEN;
! 	csio->cdb_len = sizeof(*scsi_cmd);
! 	csio->tag_action = MSG_SIMPLE_Q_TAG;
  
! 	scsi_cmd = (struct scsi_read_capacity_16 *)&csio->cdb_io.cdb_bytes;
! 	bzero(scsi_cmd, sizeof(*scsi_cmd));
! 	scsi_cmd->opcode = 0x9E;
! 	scsi_cmd->service_action = SRC16_SERVICE_ACTION;
! 	((uint8_t *)scsi_cmd)[13] = sizeof(struct scsi_read_capacity_eedp);
  
! 	ccb->ccb_h.ppriv_ptr1 = sassc;
! 	xpt_action(ccb);
  }
  
  static void
  mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb)
  {
***************
*** 3499,3504 ****
--- 3394,3403 ----
  		}
  
  		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);
  		}
***************
*** 3510,3516 ****
  	xpt_free_path(done_ccb->ccb_h.path);
  	xpt_free_ccb(done_ccb);
  }
! #endif /* __FreeBSD_version >= 1000006 */
  
  int
  mpssas_startup(struct mps_softc *sc)
--- 3409,3416 ----
  	xpt_free_path(done_ccb->ccb_h.path);
  	xpt_free_ccb(done_ccb);
  }
! #endif /* (__FreeBSD_version < 901503) || \
!           ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) */
  
  int
  mpssas_startup(struct mps_softc *sc)
*** src/sys/dev/mps/mps_sas.h.orig
--- src/sys/dev/mps/mps_sas.h
***************
*** 87,93 ****
  #define MPSSAS_DISCOVERY_TIMEOUT_PENDING	(1 << 2)
  #define MPSSAS_QUEUE_FROZEN	(1 << 3)
  #define	MPSSAS_SHUTDOWN		(1 << 4)
- #define	MPSSAS_SCANTHREAD	(1 << 5)
  	struct mpssas_target	*targets;
  	struct cam_devq		*devq;
  	struct cam_sim		*sim;
--- 87,92 ----
***************
*** 101,109 ****
  	u_int                   tm_count;
  	struct proc             *sysctl_proc;
  
- 	TAILQ_HEAD(, ccb_hdr) ccb_scanq;
- 	struct proc		*rescan_thread;
- 
  	struct taskqueue	*ev_tq;
  	struct task		ev_task;
  	TAILQ_HEAD(, mps_fw_event_work)	ev_queue;
--- 100,105 ----
*** src/sys/dev/mps/mps_sas_lsi.c.orig
--- src/sys/dev/mps/mps_sas_lsi.c
***************
*** 699,705 ****
--- 699,709 ----
  	mps_dprint(sc, MPS_INFO, "Found device <%s> <%s> <0x%04x> <%d/%d>\n", devstring,
  	    mps_describe_table(mps_linkrate_names, targ->linkrate),
  	    targ->handle, targ->encl_handle, targ->encl_slot);
+ 
+ #if ((__FreeBSD_version < 9010506) || \
+      ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000036)))
  	if ((sassc->flags & MPSSAS_IN_STARTUP) == 0)
+ #endif
  		mpssas_rescan_target(sc, targ);
  	mps_dprint(sc, MPS_INFO, "Target id 0x%x added\n", targ->tid);
  out:
***************
*** 818,829 ****
  	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);
  	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",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
--- 822,836 ----
  	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  	cm->cm_data = buffer;
  	cm->cm_length = htole32(sz);
!  	error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
  	reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply;
  	if (error || (reply == NULL)) {
  		/* FIXME */
!  		/*
!  		 * If the request returns an error then we need to do a diag
!  		 * reset
!  		 */ 
!  		printf("%s: request for page completed with error %d",
  		    __func__, error);
  		error = ENXIO;
  		goto out;
***************
*** 955,961 ****
  	action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
  	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  	mps_lock(sc);
! 	mps_request_polled(sc, cm);
  	mps_unlock(sc);
  
  	/*
--- 962,968 ----
  	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_unlock(sc);
  
  	/*
*** src/sys/dev/mps/mps_user.c.orig
--- src/sys/dev/mps/mps_user.c
***************
*** 672,678 ****
  	cm = mps_alloc_command(sc);
  
  	if (cm == NULL) {
! 		mps_printf(sc, "mps_user_command: no mps requests\n");
  		err = ENOMEM;
  		goto Ret;
  	}
--- 672,678 ----
  	cm = mps_alloc_command(sc);
  
  	if (cm == NULL) {
! 		mps_printf(sc, "%s: no mps requests\n", __func__);
  		err = ENOMEM;
  		goto Ret;
  	}
***************
*** 680,687 ****
  
  	hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;
  
! 	mps_dprint(sc, MPS_INFO, "mps_user_command: req %p %d  rpl %p %d\n",
! 		    cmd->req, cmd->req_len, cmd->rpl, cmd->rpl_len );
  
  	if (cmd->req_len > (int)sc->facts->IOCRequestFrameSize * 4) {
  		err = EINVAL;
--- 680,687 ----
  
  	hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;
  
! 	mps_dprint(sc, MPS_INFO, "%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;
***************
*** 691,698 ****
  	if (err != 0)
  		goto RetFreeUnlocked;
  
! 	mps_dprint(sc, MPS_INFO, "mps_user_command: Function %02X  "
! 	    "MsgFlags %02X\n", hdr->Function, hdr->MsgFlags );
  
  	err = mps_user_setup_request(cm, cmd);
  	if (err != 0) {
--- 691,698 ----
  	if (err != 0)
  		goto RetFreeUnlocked;
  
! 	mps_dprint(sc, MPS_INFO, "%s: Function %02X MsgFlags %02X\n", __func__,
! 	    hdr->Function, hdr->MsgFlags);
  
  	err = mps_user_setup_request(cm, cmd);
  	if (err != 0) {
***************
*** 718,725 ****
  	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE;
  	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  
  	mps_lock(sc);
! 	err = mps_wait_command(sc, cm, 30);
  
  	if (err) {
  		mps_printf(sc, "%s: invalid request: error %d\n",
--- 718,734 ----
  	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE;
  	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  
+ 	err = mps_user_setup_request(cm, cmd);
+ 	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, CAN_SLEEP);
  
  	if (err) {
  		mps_printf(sc, "%s: invalid request: error %d\n",
***************
*** 731,740 ****
  	sz = rpl->MsgLength * 4;
  	
  	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;
  		sz = cmd->rpl_len;
  	}	
  
--- 740,747 ----
  	sz = rpl->MsgLength * 4;
  	
  	if (sz > cmd->rpl_len) {
! 		mps_printf(sc, "%s: user reply buffer (%d) smaller than "
! 		    "returned buffer (%d)\n", __func__, cmd->rpl_len, sz);
  		sz = cmd->rpl_len;
  	}	
  
***************
*** 742,748 ****
  	copyout(rpl, cmd->rpl, sz);
  	if (buf != NULL)
  		copyout(buf, cmd->buf, cmd->len);
! 	mps_dprint(sc, MPS_INFO, "mps_user_command: reply size %d\n", sz );
  
  RetFreeUnlocked:
  	mps_lock(sc);
--- 749,755 ----
  	copyout(rpl, cmd->rpl, sz);
  	if (buf != NULL)
  		copyout(buf, cmd->buf, cmd->len);
! 	mps_dprint(sc, MPS_INFO, "%s: reply size %d\n", __func__, sz);
  
  RetFreeUnlocked:
  	mps_lock(sc);
***************
*** 849,855 ****
  		cm->cm_complete = NULL;
  		cm->cm_complete_data = NULL;
  
! 		err = mps_wait_command(sc, cm, 30);
  
  		if (err != 0) {
  			err = EIO;
--- 856,862 ----
  		cm->cm_complete = NULL;
  		cm->cm_complete_data = NULL;
  
! 		err = mps_wait_command(sc, cm, 30, CAN_SLEEP);
  
  		if (err != 0) {
  			err = EIO;
***************
*** 864,878 ****
  			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);
  			}
  		}
  		mpssas_free_tm(sc, cm);
  		goto Ret;
--- 871,884 ----
  			sz = rpl->MsgLength * 4;
  	
  			if (sz > data->ReplySize) {
! 				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,992 ****
  
  	mps_lock(sc);
  
! 	err = mps_wait_command(sc, cm, 30);
  
  	if (err) {
  		mps_printf(sc, "%s: invalid request: error %d\n", __func__,
--- 992,998 ----
  
  	mps_lock(sc);
  
! 	err = mps_wait_command(sc, cm, 30, CAN_SLEEP);
  
  	if (err) {
  		mps_printf(sc, "%s: invalid request: error %d\n", __func__,
***************
*** 1025,1039 ****
  		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);
  		}
  
  		if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
  		    (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
--- 1031,1043 ----
  		sz = rpl->MsgLength * 4;
  
  		if (sz > data->ReplySize) {
! 			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,1209 ****
  	/*
  	 * Send command synchronously.
  	 */
! 	status = mps_wait_command(sc, cm, 30);
  	if (status) {
  		mps_printf(sc, "%s: invalid request: error %d\n", __func__,
  		    status);
--- 1207,1213 ----
  	/*
  	 * Send command synchronously.
  	 */
! 	status = mps_wait_command(sc, cm, 30, CAN_SLEEP);
  	if (status) {
  		mps_printf(sc, "%s: invalid request: error %d\n", __func__,
  		    status);
***************
*** 1252,1259 ****
  	 */
  	*return_code = MPS_FW_DIAG_ERROR_RELEASE_FAILED;
  	if (!pBuffer->enabled) {
! 		mps_dprint(sc, MPS_INFO, "%s: This buffer type is not supported "
! 		    "by the IOC", __func__);
  		return (MPS_DIAG_FAILURE);
  	}
  
--- 1256,1263 ----
  	 */
  	*return_code = MPS_FW_DIAG_ERROR_RELEASE_FAILED;
  	if (!pBuffer->enabled) {
! 		mps_dprint(sc, MPS_INFO, "%s: This buffer type is not "
! 		    "supported by the IOC", __func__);
  		return (MPS_DIAG_FAILURE);
  	}
  
***************
*** 1287,1293 ****
  	/*
  	 * Send command synchronously.
  	 */
! 	status = mps_wait_command(sc, cm, 30);
  	if (status) {
  		mps_printf(sc, "%s: invalid request: error %d\n", __func__,
  		    status);
--- 1291,1297 ----
  	/*
  	 * Send command synchronously.
  	 */
! 	status = mps_wait_command(sc, cm, 30, CAN_SLEEP);
  	if (status) {
  		mps_printf(sc, "%s: invalid request: error %d\n", __func__,
  		    status);
*** src/sys/dev/mps/mpsvar.h.orig
--- src/sys/dev/mps/mpsvar.h
***************
*** 26,38 ****
   *
   * LSI MPT-Fusion Host Adapter FreeBSD
   *
!  * $FreeBSD: stable/9/sys/dev/mps/mpsvar.h 251874 2013-06-18 00:36:53Z scottl $
   */
  
  #ifndef _MPSVAR_H
  #define _MPSVAR_H
  
! #define MPS_DRIVER_VERSION	"14.00.00.01-fbsd"
  
  #define MPS_DB_MAX_WAIT		2500
  
--- 26,38 ----
   *
   * LSI MPT-Fusion Host Adapter FreeBSD
   *
!  * $FreeBSD: head/sys/dev/mps/mpsvar.h 246713 2013-02-12 16:57:20Z kib $
   */
  
  #ifndef _MPSVAR_H
  #define _MPSVAR_H
  
! #define MPS_DRIVER_VERSION	"16.00.00.00-fbsd"
  
  #define MPS_DB_MAX_WAIT		2500
  
***************
*** 304,310 ****
  	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 */
--- 304,309 ----
***************
*** 628,642 ****
  static __inline void
  mps_from_u64(uint64_t data, U64 *mps)
  {
! 	(mps)->High = (uint32_t)((data) >> 32);
! 	(mps)->Low = (uint32_t)((data) & 0xffffffff);
  }
  
  static __inline uint64_t
  mps_to_u64(U64 *data)
  {
  
! 	return (((uint64_t)data->High << 32) | data->Low);
  }
  
  static __inline void
--- 627,641 ----
  static __inline void
  mps_from_u64(uint64_t data, U64 *mps)
  {
! 	(mps)->High = htole32((uint32_t)((data) >> 32));
! 	(mps)->Low = htole32((uint32_t)((data) & 0xffffffff));
  }
  
  static __inline uint64_t
  mps_to_u64(U64 *data)
  {
  
! 	return (((uint64_t)le32toh(data->High) << 32) | le32toh(data->Low));
  }
  
  static __inline void
***************
*** 686,692 ****
      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_request_polled(struct mps_softc *sc, struct mps_command *cm);
  
  int mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t
--- 685,692 ----
      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 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
*** src/sys/sys/param.h.orig
--- src/sys/sys/param.h
***************
*** 58,64 ****
   *		in the range 5 to 9.
   */
  #undef __FreeBSD_version
! #define __FreeBSD_version 901505	/* Master, propagated to newvers */
  
  /*
   * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
--- 58,64 ----
   *		in the range 5 to 9.
   */
  #undef __FreeBSD_version
! #define __FreeBSD_version 901506	/* Master, propagated to newvers */
  
  /*
   * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,

--k1lZvvs/B4yU6o8G--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20130812190229.GA24478>