Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 Jul 2013 18:37:07 +0000 (UTC)
From:      "Kenneth D. Merry" <ken@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r253549 - in head/sys: cam dev/mps sys
Message-ID:  <201307221837.r6MIb7bX073383@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ken
Date: Mon Jul 22 18:37:07 2013
New Revision: 253549
URL: http://svnweb.freebsd.org/changeset/base/253549

Log:
  CAM and mps(4) driver scanning changes.
  
  Add a PIM_NOSCAN flag to the CAM path inquiry CCB.  This tells CAM
  not to perform a rescan on a bus when it is registered.
  
  We now use this flag in the mps(4) driver.  Since it knows what
  devices it has attached, it is more efficient for it to just issue
  a target rescan on the targets that are attached.
  
  Also, remove the private rescan thread from the mps(4) driver in
  favor of the rescan thread already built into CAM.  Without this
  change, but with the change above, the MPS scanner could run before
  or during CAM's initial setup, which would cause duplicate device
  reprobes and announcements.
  
  sys/param.h:
  	Bump __FreeBSD_version to 1000039 for the inclusion of the
  	PIM_RESCAN CAM path inquiry flag.
  
  sys/cam/cam_ccb.h:
  sys/cam/cam_xpt.c:
  	Added a PIM_NOSCAN flag.  If a SIM sets this in the path
  	inquiry ccb, then CAM won't rescan the bus in
  	xpt_bus_regsister.
  
  sys/dev/mps/mps_sas.c
  	For versions of FreeBSD that have the PIM_NOSCAN path
  	inquiry flag, don't freeze the sim queue during scanning,
  	because CAM won't be scanning this bus.  Instead, hold
  	up the boot.  Don't call mpssas_rescan_target in
  	mpssas_startup_decrement; it's redundant and I don't
  	know why it was in there.
  
  	Set PIM_NOSCAN in path inquiry CCBs.
  
  	Remove methods related to the internal rescan daemon.
  
  	Always use async events to trigger a probe for EEDP support.
  	In older versions of FreeBSD where AC_ADVINFO_CHANGED is
  	not available, use AC_FOUND_DEVICE and issue the
  	necessary READ CAPACITY manually.
  
  	Provide a path to xpt_register_async() so that we only
  	receive events for our own SCSI domain.
  
  	Improve error reporting in cases where setup for EEDP
  	detection fails.
  
  sys/dev/mps/mps_sas.h:
  	Remove softc flags and data related to the scanner thread.
  
  sys/dev/mps/mps_sas_lsi.c:
  	Unconditionally rescan the target whenever a device is added.
  
  Sponsored by:	Spectra Logic
  MFC after:	1 week

Modified:
  head/sys/cam/cam_ccb.h
  head/sys/cam/cam_xpt.c
  head/sys/dev/mps/mps_sas.c
  head/sys/dev/mps/mps_sas.h
  head/sys/dev/mps/mps_sas_lsi.c
  head/sys/sys/param.h

Modified: head/sys/cam/cam_ccb.h
==============================================================================
--- head/sys/cam/cam_ccb.h	Mon Jul 22 18:18:21 2013	(r253548)
+++ head/sys/cam/cam_ccb.h	Mon Jul 22 18:37:07 2013	(r253549)
@@ -571,6 +571,7 @@ typedef enum {
 	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 */

Modified: head/sys/cam/cam_xpt.c
==============================================================================
--- head/sys/cam/cam_xpt.c	Mon Jul 22 18:18:21 2013	(r253548)
+++ head/sys/cam/cam_xpt.c	Mon Jul 22 18:37:07 2013	(r253549)
@@ -3895,18 +3895,23 @@ xpt_bus_register(struct cam_sim *sim, de
 
 	/* 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();
-		if (scan_ccb != NULL) {
-			scan_ccb->ccb_h.path = path;
-			scan_ccb->ccb_h.func_code = XPT_SCAN_BUS;
-			scan_ccb->crcn.flags = 0;
-			xpt_rescan(scan_ccb);
+		if ((cpi.hba_misc & PIM_NOSCAN) == 0) {
+			union	ccb *scan_ccb;
+
+			/* Initiate bus rescan. */
+			scan_ccb = xpt_alloc_ccb_nowait();
+			if (scan_ccb != NULL) {
+				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_print(path,
+					  "Can't allocate CCB to scan bus\n");
 		} else
-			xpt_print(path, "Can't allocate CCB to scan bus\n");
+			xpt_free_path(path);
 	} else
 		xpt_free_path(path);
 	return (CAM_SUCCESS);

Modified: head/sys/dev/mps/mps_sas.c
==============================================================================
--- head/sys/dev/mps/mps_sas.c	Mon Jul 22 18:18:21 2013	(r253548)
+++ head/sys/dev/mps/mps_sas.c	Mon Jul 22 18:37:07 2013	(r253549)
@@ -136,14 +136,12 @@ static void mpssas_action_smpio(struct m
 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);
+#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);
@@ -202,8 +200,12 @@ mpssas_startup_decrement(struct mpssas_s
 			mps_dprint(sassc->sc, MPS_INIT,
 			    "%s releasing simq\n", __func__);
 			sassc->flags &= ~MPSSAS_IN_STARTUP;
+#if __FreeBSD_version >= 1000039
+			xpt_release_boot();
+#else
 			xpt_release_simq(sassc->sim, 1);
 			mpssas_rescan_target(sassc->sc, NULL);
+#endif
 		}
 		mps_dprint(sassc->sc, MPS_INIT, "%s refcount %u\n", __func__,
 		    sassc->startup_refcount);
@@ -254,7 +256,6 @@ mpssas_free_tm(struct mps_softc *sc, str
 	mps_free_high_priority_command(sc, tm);
 }
 
-
 void
 mpssas_rescan_target(struct mps_softc *sc, struct mpssas_target *targ)
 {
@@ -292,7 +293,7 @@ mpssas_rescan_target(struct mps_softc *s
 		ccb->ccb_h.func_code = XPT_SCAN_TGT;     
 
 	mps_dprint(sc, MPS_TRACE, "%s targetid %u\n", __func__, targetid);
-	mpssas_rescan(sassc, ccb);
+	xpt_rescan(ccb);
 }
 
 static void
@@ -690,9 +691,7 @@ int
 mps_attach_sas(struct mps_softc *sc)
 {
 	struct mpssas_softc *sassc;
-#if __FreeBSD_version >= 1000006
 	cam_status status;
-#endif
 	int unit, error = 0;
 
 	MPS_FUNCTRACE(sc);
@@ -740,16 +739,7 @@ mps_attach_sas(struct mps_softc *sc)
 	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
@@ -764,12 +754,16 @@ mps_attach_sas(struct mps_softc *sc)
 	}
 
 	/*
-	 * Assume that discovery events will start right away.  Freezing
-	 * the simq will prevent the CAM boottime scanner from running
-	 * before discovery is complete.
+	 * 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 >= 1000039
+	xpt_hold_boot();
+#else
 	xpt_freeze_simq(sassc->sim, 1);
+#endif
 	sc->sassc->startup_refcount = 0;
 
 	callout_init(&sassc->discovery_callout, 1 /*mpsafe*/);
@@ -777,14 +771,42 @@ mps_attach_sas(struct mps_softc *sc)
 
 	sassc->tm_count = 0;
 
-#if __FreeBSD_version >= 1000006
-	status = xpt_register_async(AC_ADVINFO_CHANGED, mpssas_async, sc, NULL);
+	/*
+	 * 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_dprint(sc, MPS_ERROR,
-		    "Error %#x registering async handler for "
-		    "AC_ADVINFO_CHANGED events\n", status);
-	}
+		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_dprint(sc, MPS_ERROR,
+			    "Error %#x registering async handler for "
+			    "AC_ADVINFO_CHANGED events\n", status);
+			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);
 
@@ -823,9 +845,11 @@ mps_detach_sas(struct mps_softc *sc)
 	mps_lock(sc);
 
 	/* Deregister our async handler */
-#if __FreeBSD_version >= 1000006
-	xpt_register_async(0, mpssas_async, sc, NULL);
-#endif
+	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);
@@ -835,15 +859,7 @@ mps_detach_sas(struct mps_softc *sc)
 		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);
-		}
-	}
+	sassc->flags |= MPSSAS_SHUTDOWN;
 	mps_unlock(sc);
 
 	if (sassc->devq != NULL)
@@ -934,7 +950,11 @@ mpssas_action(struct cam_sim *sim, union
 		cpi->version_num = 1;
 		cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
 		cpi->target_sprt = 0;
+#if __FreeBSD_version >= 1000039
+		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;
@@ -3126,114 +3146,6 @@ mpssas_poll(struct cam_sim *sim)
 }
 
 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_XINFO, "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_FUNCTRACE(sc);
-
-	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_XINFO, "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_XINFO, "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_FUNCTRACE(sassc->sc);
-
-	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_XINFO, "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)
 {
@@ -3242,6 +3154,8 @@ mpssas_async(void *callback_arg, uint32_
 	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;
@@ -3264,13 +3178,6 @@ mpssas_async(void *callback_arg, uint32_
 			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)];
@@ -3321,177 +3228,147 @@ mpssas_async(void *callback_arg, uint32_
 		}
 		break;
 	}
+#else
+	case AC_FOUND_DEVICE: {
+		struct ccb_getdev *cgd;
+
+		cgd = arg;
+		mpssas_check_eedp(sc, path, cgd);
+		break;
+	}
+#endif
 	default:
 		break;
 	}
 }
-#else /* __FreeBSD_version >= 1000006 */
 
+#if (__FreeBSD_version < 901503) || \
+    ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006))
 static void
-mpssas_check_eedp(struct mpssas_softc *sassc)
+mpssas_check_eedp(struct mps_softc *sc, struct cam_path *path,
+		  struct ccb_getdev *cgd)
 {
-	struct mps_softc *sc = sassc->sc;
+	struct mpssas_softc *sassc = sc->sassc;
 	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);
+	path_id_t pathid;
 	target_id_t targetid;
 	lun_id_t lunid;
-	struct cam_periph *found_periph;
+	union ccb *ccb;
+	struct cam_path *local_path;
 	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_ERROR, "Unable to alloc CCB "
-				    "for EEDP support.\n");
-				return;
-			}
+	sassc = sc->sassc;
+	pathid = cam_sim_path(sassc->sim);
+	targetid = xpt_path_target_id(path);
+	lunid = xpt_path_lun_id(path);
 
-			if (xpt_create_path(&ccb->ccb_h.path, NULL,
-			    pathid, targetid, lunid) != CAM_REQ_CMP) {
-				mps_dprint(sc, MPS_ERROR, "Unable to create "
-				    "path for EEDP support\n");
-				xpt_free_ccb(ccb);
-				return;
-			}
+	target = &sassc->targets[targetid];
+	if (target->handle == 0x0)
+		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_ERROR,
-						    "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);
+	/*
+	 * 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;
 
-				/*
-				 * 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
-				 */
+	/*
+	 * 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_ERROR, "Unable to alloc CCB "
+		    "for EEDP support.\n");
+		return;
+	}
 
-				xpt_path_string(ccb->ccb_h.path, path_str, 
-					sizeof(path_str));
+	if (xpt_create_path(&local_path, xpt_periph,
+	    pathid, targetid, lunid) != CAM_REQ_CMP) {
+		mps_dprint(sc, MPS_ERROR, "Unable to create "
+		    "path for EEDP support\n");
+		xpt_free_ccb(ccb);
+		return;
+	}
 
-				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_XINFO,
-				"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_ERROR, "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);
+	/*
+	 * 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_ERROR,
+			    "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);
+	}
 
-				/*
-				 * 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);
+	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);
 
-				ccb->ccb_h.ppriv_ptr1 = sassc;
-				xpt_action(ccb);
-			} else {
-				xpt_free_path(ccb->ccb_h.path);
-				xpt_free_ccb(ccb);
-			}
-		} while (found_periph);
+	/*
+	 * 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)
@@ -3556,7 +3433,8 @@ mpssas_read_cap_done(struct cam_periph *
 	xpt_free_path(done_ccb->ccb_h.path);
 	xpt_free_ccb(done_ccb);
 }
-#endif /* __FreeBSD_version >= 1000006 */
+#endif /* (__FreeBSD_version < 901503) || \
+          ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) */
 
 int
 mpssas_startup(struct mps_softc *sc)

Modified: head/sys/dev/mps/mps_sas.h
==============================================================================
--- head/sys/dev/mps/mps_sas.h	Mon Jul 22 18:18:21 2013	(r253548)
+++ head/sys/dev/mps/mps_sas.h	Mon Jul 22 18:37:07 2013	(r253549)
@@ -87,7 +87,6 @@ struct mpssas_softc {
 #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;
@@ -101,9 +100,6 @@ struct mpssas_softc {
 	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;

Modified: head/sys/dev/mps/mps_sas_lsi.c
==============================================================================
--- head/sys/dev/mps/mps_sas_lsi.c	Mon Jul 22 18:18:21 2013	(r253548)
+++ head/sys/dev/mps/mps_sas_lsi.c	Mon Jul 22 18:37:07 2013	(r253549)
@@ -699,7 +699,10 @@ mpssas_add_device(struct mps_softc *sc, 
 	mps_dprint(sc, MPS_MAPPING, "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 < 1000039
 	if ((sassc->flags & MPSSAS_IN_STARTUP) == 0)
+#endif
 		mpssas_rescan_target(sc, targ);
 	mps_dprint(sc, MPS_MAPPING, "Target id 0x%x added\n", targ->tid);
 out:

Modified: head/sys/sys/param.h
==============================================================================
--- head/sys/sys/param.h	Mon Jul 22 18:18:21 2013	(r253548)
+++ head/sys/sys/param.h	Mon Jul 22 18:37:07 2013	(r253549)
@@ -58,7 +58,7 @@
  *		in the range 5 to 9.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 1000038	/* Master, propagated to newvers */
+#define __FreeBSD_version 1000039	/* Master, propagated to newvers */
 
 /*
  * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,



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