svn commit: r254214 - in projects/camlock/sys/cam: . ata scsi

Alexander Motin mav at FreeBSD.org
Sun Aug 11 10:54:19 UTC 2013


Author: mav
Date: Sun Aug 11 10:54:16 2013
New Revision: 254214
URL: http://svnweb.freebsd.org/changeset/base/254214

Log:
  Introduce per-device mutex locks to protect all device and periph states.
  Do not use congested SIM lock for anything except actually talking to SIM.
  
  There are still rough edges around async delivery, missing locking for list
  of LUNs, and targ and CTL are probably broken, but nevertheless my test
  system booted, passed basic tests and can't wait for some preliminary
  benchmarking. ;)

Modified:
  projects/camlock/sys/cam/ata/ata_da.c
  projects/camlock/sys/cam/ata/ata_xpt.c
  projects/camlock/sys/cam/cam_periph.c
  projects/camlock/sys/cam/cam_periph.h
  projects/camlock/sys/cam/cam_xpt.c
  projects/camlock/sys/cam/cam_xpt.h
  projects/camlock/sys/cam/cam_xpt_internal.h
  projects/camlock/sys/cam/scsi/scsi_cd.c
  projects/camlock/sys/cam/scsi/scsi_ch.c
  projects/camlock/sys/cam/scsi/scsi_da.c
  projects/camlock/sys/cam/scsi/scsi_enc.c
  projects/camlock/sys/cam/scsi/scsi_enc_ses.c
  projects/camlock/sys/cam/scsi/scsi_pass.c
  projects/camlock/sys/cam/scsi/scsi_sg.c
  projects/camlock/sys/cam/scsi/scsi_targ_bh.c
  projects/camlock/sys/cam/scsi/scsi_target.c
  projects/camlock/sys/cam/scsi/scsi_xpt.c

Modified: projects/camlock/sys/cam/ata/ata_da.c
==============================================================================
--- projects/camlock/sys/cam/ata/ata_da.c	Sun Aug 11 10:35:38 2013	(r254213)
+++ projects/camlock/sys/cam/ata/ata_da.c	Sun Aug 11 10:54:16 2013	(r254214)
@@ -1334,7 +1334,7 @@ adaregister(struct cam_periph *periph, v
 	 * Schedule a periodic event to occasionally send an
 	 * ordered tag to a device.
 	 */
-	callout_init_mtx(&softc->sendordered_c, periph->sim->mtx, 0);
+	callout_init_mtx(&softc->sendordered_c, cam_periph_mtx(periph), 0);
 	callout_reset(&softc->sendordered_c,
 	    (ada_default_timeout * hz) / ADA_ORDEREDTAG_INTERVAL,
 	    adasendorderedtag, softc);

Modified: projects/camlock/sys/cam/ata/ata_xpt.c
==============================================================================
--- projects/camlock/sys/cam/ata/ata_xpt.c	Sun Aug 11 10:35:38 2013	(r254213)
+++ projects/camlock/sys/cam/ata/ata_xpt.c	Sun Aug 11 10:54:16 2013	(r254214)
@@ -1477,6 +1477,7 @@ ata_scan_lun(struct cam_periph *periph, 
 	cam_status status;
 	struct cam_path *new_path;
 	struct cam_periph *old_periph;
+	int lock;
 
 	CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_scan_lun\n"));
 
@@ -1515,6 +1516,9 @@ ata_scan_lun(struct cam_periph *periph, 
 		request_ccb->crcn.flags = flags;
 	}
 
+	lock = (xpt_path_owned(path) == 0);
+	if (lock)
+		xpt_path_lock(path);
 	if ((old_periph = cam_periph_find(path, "aprobe")) != NULL) {
 		if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) {
 			probe_softc *softc;
@@ -1541,6 +1545,8 @@ ata_scan_lun(struct cam_periph *periph, 
 			xpt_done(request_ccb);
 		}
 	}
+	if (lock)
+		xpt_path_unlock(path);
 }
 
 static void
@@ -1696,15 +1702,8 @@ ata_dev_advinfo(union ccb *start_ccb)
 	start_ccb->ccb_h.status = CAM_REQ_CMP;
 
 	if (cdai->flags & CDAI_FLAG_STORE) {
-		int owned;
-
-		owned = mtx_owned(start_ccb->ccb_h.path->bus->sim->mtx);
-		if (owned == 0)
-			mtx_lock(start_ccb->ccb_h.path->bus->sim->mtx);
 		xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path,
 			  (void *)(uintptr_t)cdai->buftype);
-		if (owned == 0)
-			mtx_unlock(start_ccb->ccb_h.path->bus->sim->mtx);
 	}
 }
 
@@ -2014,7 +2013,7 @@ ata_announce_periph(struct cam_periph *p
 	u_int	speed;
 	u_int	mb;
 
-	mtx_assert(periph->sim->mtx, MA_OWNED);
+	cam_periph_assert(periph, MA_OWNED);
 
 	xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
 	cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;

Modified: projects/camlock/sys/cam/cam_periph.c
==============================================================================
--- projects/camlock/sys/cam/cam_periph.c	Sun Aug 11 10:35:38 2013	(r254213)
+++ projects/camlock/sys/cam/cam_periph.c	Sun Aug 11 10:54:16 2013	(r254214)
@@ -206,7 +206,6 @@ cam_periph_alloc(periph_ctor_t *periph_c
 	periph->refcount = 1;		/* Dropped by invalidation. */
 	periph->sim = sim;
 	SLIST_INIT(&periph->ccb_list);
-	mtx_init(&periph->periph_mtx, "CAM periph lock", NULL, MTX_DEF);
 	status = xpt_create_path(&path, periph, path_id, target_id, lun_id);
 	if (status != CAM_REQ_CMP)
 		goto failure;
@@ -299,7 +298,7 @@ cam_periph_find(struct cam_path *path, c
 		TAILQ_FOREACH(periph, &(*p_drv)->units, unit_links) {
 			if (xpt_path_comp(periph->path, path) == 0) {
 				xpt_unlock_buses();
-				mtx_assert(periph->sim->mtx, MA_OWNED);
+				cam_periph_assert(periph, MA_OWNED);
 				return(periph);
 			}
 		}
@@ -380,7 +379,7 @@ void
 cam_periph_release_locked_buses(struct cam_periph *periph)
 {
 
-	mtx_assert(periph->sim->mtx, MA_OWNED);
+	cam_periph_assert(periph, MA_OWNED);
 	KASSERT(periph->refcount >= 1, ("periph->refcount >= 1"));
 	if (--periph->refcount == 0)
 		camperiphfree(periph);
@@ -401,16 +400,16 @@ cam_periph_release_locked(struct cam_per
 void
 cam_periph_release(struct cam_periph *periph)
 {
-	struct cam_sim *sim;
+	struct mtx *mtx;
 
 	if (periph == NULL)
 		return;
 	
-	sim = periph->sim;
-	mtx_assert(sim->mtx, MA_NOTOWNED);
-	mtx_lock(sim->mtx);
+	cam_periph_assert(periph, MA_NOTOWNED);
+	mtx = cam_periph_mtx(periph);
+	mtx_lock(mtx);
 	cam_periph_release_locked(periph);
-	mtx_unlock(sim->mtx);
+	mtx_unlock(mtx);
 }
 
 int
@@ -428,10 +427,10 @@ cam_periph_hold(struct cam_periph *perip
 	if (cam_periph_acquire(periph) != CAM_REQ_CMP)
 		return (ENXIO);
 
-	mtx_assert(periph->sim->mtx, MA_OWNED);
+	cam_periph_assert(periph, MA_OWNED);
 	while ((periph->flags & CAM_PERIPH_LOCKED) != 0) {
 		periph->flags |= CAM_PERIPH_LOCK_WANTED;
-		if ((error = mtx_sleep(periph, periph->sim->mtx, priority,
+		if ((error = cam_periph_sleep(periph, periph, priority,
 		    "caplck", 0)) != 0) {
 			cam_periph_release_locked(periph);
 			return (error);
@@ -450,7 +449,7 @@ void
 cam_periph_unhold(struct cam_periph *periph)
 {
 
-	mtx_assert(periph->sim->mtx, MA_OWNED);
+	cam_periph_assert(periph, MA_OWNED);
 
 	periph->flags &= ~CAM_PERIPH_LOCKED;
 	if ((periph->flags & CAM_PERIPH_LOCK_WANTED) != 0) {
@@ -578,7 +577,7 @@ void
 cam_periph_invalidate(struct cam_periph *periph)
 {
 
-	mtx_assert(periph->sim->mtx, MA_OWNED);
+	cam_periph_assert(periph, MA_OWNED);
 	/*
 	 * We only call this routine the first time a peripheral is
 	 * invalidated.
@@ -599,7 +598,7 @@ camperiphfree(struct cam_periph *periph)
 {
 	struct periph_driver **p_drv;
 
-	mtx_assert(periph->sim->mtx, MA_OWNED);
+	cam_periph_assert(periph, MA_OWNED);
 	for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) {
 		if (strcmp((*p_drv)->driver_name, periph->periph_name) == 0)
 			break;
@@ -676,7 +675,6 @@ camperiphfree(struct cam_periph *periph)
 					  periph->path, arg);
 	}
 	xpt_free_path(periph->path);
-	mtx_destroy(&periph->periph_mtx);
 	free(periph, M_CAMPERIPH);
 	xpt_lock_buses();
 }
@@ -947,12 +945,11 @@ cam_periph_unmapmem(union ccb *ccb, stru
 void
 cam_periph_ccbwait(union ccb *ccb)
 {
-	struct cam_sim *sim;
 
-	sim = xpt_path_sim(ccb->ccb_h.path);
 	if ((ccb->ccb_h.pinfo.index != CAM_UNQUEUED_INDEX)
 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG))
-		mtx_sleep(&ccb->ccb_h.cbfcnp, sim->mtx, PRIBIO, "cbwait", 0);
+		xpt_path_sleep(ccb->ccb_h.path, &ccb->ccb_h.cbfcnp, PRIBIO,
+		    "cbwait", 0);
 }
 
 int
@@ -1033,12 +1030,10 @@ cam_periph_runccb(union ccb *ccb,
 		  cam_flags camflags, u_int32_t sense_flags,
 		  struct devstat *ds)
 {
-	struct cam_sim *sim;
 	int error;
  
 	error = 0;
-	sim = xpt_path_sim(ccb->ccb_h.path);
-	mtx_assert(sim->mtx, MA_OWNED);
+	xpt_path_assert(ccb->ccb_h.path, MA_OWNED);
 
 	/*
 	 * If the user has supplied a stats structure, and if we understand

Modified: projects/camlock/sys/cam/cam_periph.h
==============================================================================
--- projects/camlock/sys/cam/cam_periph.h	Sun Aug 11 10:35:38 2013	(r254213)
+++ projects/camlock/sys/cam/cam_periph.h	Sun Aug 11 10:54:16 2013	(r254214)
@@ -130,7 +130,6 @@ struct cam_periph {
 	TAILQ_ENTRY(cam_periph)  unit_links;
 	ac_callback_t		*deferred_callback; 
 	ac_code			 deferred_ac;
-	struct mtx		 periph_mtx;
 };
 
 #define CAM_PERIPH_MAXMAPS	2
@@ -190,26 +189,38 @@ int		cam_periph_error(union ccb *ccb, ca
 static __inline void
 cam_periph_lock(struct cam_periph *periph)
 {
-	mtx_lock(periph->sim->mtx);
+	xpt_path_lock(periph->path);
 }
 
 static __inline void
 cam_periph_unlock(struct cam_periph *periph)
 {
-	mtx_unlock(periph->sim->mtx);
+	xpt_path_unlock(periph->path);
 }
 
 static __inline int
 cam_periph_owned(struct cam_periph *periph)
 {
-	return (mtx_owned(periph->sim->mtx));
+	return (xpt_path_owned(periph->path));
+}
+
+static __inline void
+cam_periph_assert(struct cam_periph *periph, int what)
+{
+	mtx_assert(xpt_path_mtx(periph->path), what);
 }
 
 static __inline int
 cam_periph_sleep(struct cam_periph *periph, void *chan, int priority,
 		 const char *wmesg, int timo)
 {
-	return (msleep(chan, periph->sim->mtx, priority, wmesg, timo));
+	return (xpt_path_sleep(periph->path, chan, priority, wmesg, timo));
+}
+
+static __inline struct mtx *
+cam_periph_mtx(struct cam_periph *periph)
+{
+	return (xpt_path_mtx(periph->path));
 }
 
 static inline struct cam_periph *
@@ -232,7 +243,7 @@ cam_periph_acquire_next(struct cam_perip
 {
 	struct cam_periph *periph = pperiph;
 
-	mtx_assert(pperiph->sim->mtx, MA_NOTOWNED);
+	cam_periph_assert(pperiph, MA_NOTOWNED);
 	xpt_lock_buses();
 	do {
 		periph = TAILQ_NEXT(periph, unit_links);

Modified: projects/camlock/sys/cam/cam_xpt.c
==============================================================================
--- projects/camlock/sys/cam/cam_xpt.c	Sun Aug 11 10:35:38 2013	(r254213)
+++ projects/camlock/sys/cam/cam_xpt.c	Sun Aug 11 10:54:16 2013	(r254214)
@@ -117,6 +117,7 @@ struct xpt_softc {
 
 	struct mtx		xpt_topo_lock;
 	struct mtx		xpt_lock;
+	struct taskqueue	*xpt_taskq;
 };
 
 typedef enum {
@@ -450,8 +451,6 @@ xptdoioctl(struct cdev *dev, u_long cmd,
 
 			ccb = xpt_alloc_ccb();
 
-			CAM_SIM_LOCK(bus->sim);
-
 			/*
 			 * Create a path using the bus, target, and lun the
 			 * user passed in.
@@ -470,11 +469,12 @@ xptdoioctl(struct cdev *dev, u_long cmd,
 			xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path,
 				      inccb->ccb_h.pinfo.priority);
 			xpt_merge_ccb(ccb, inccb);
+			xpt_path_lock(ccb->ccb_h.path);
 			cam_periph_runccb(ccb, NULL, 0, 0, NULL);
+			xpt_path_unlock(ccb->ccb_h.path);
 			bcopy(ccb, inccb, sizeof(union ccb));
 			xpt_free_path(ccb->ccb_h.path);
 			xpt_free_ccb(ccb);
-			CAM_SIM_UNLOCK(bus->sim);
 			break;
 
 		case XPT_DEBUG: {
@@ -485,8 +485,6 @@ xptdoioctl(struct cdev *dev, u_long cmd,
 			 * allocate it on the stack.
 			 */
 
-			CAM_SIM_LOCK(bus->sim);
-
 			/*
 			 * Create a path using the bus, target, and lun the
 			 * user passed in.
@@ -507,7 +505,6 @@ xptdoioctl(struct cdev *dev, u_long cmd,
 			xpt_action(&ccb);
 			bcopy(&ccb, inccb, sizeof(union ccb));
 			xpt_free_path(ccb.ccb_h.path);
-			CAM_SIM_UNLOCK(bus->sim);
 			break;
 
 		}
@@ -555,9 +552,7 @@ xptdoioctl(struct cdev *dev, u_long cmd,
 			/*
 			 * This is an immediate CCB, we can send it on directly.
 			 */
-			CAM_SIM_LOCK(xpt_path_sim(xpt_periph->path));
 			xpt_action(inccb);
-			CAM_SIM_UNLOCK(xpt_path_sim(xpt_periph->path));
 
 			/*
 			 * Map the buffers back into user space.
@@ -775,7 +770,6 @@ static void
 xpt_scanner_thread(void *dummy)
 {
 	union ccb	*ccb;
-	struct cam_sim	*sim;
 
 	xpt_lock_buses();
 	for (;;) {
@@ -786,10 +780,7 @@ xpt_scanner_thread(void *dummy)
 			TAILQ_REMOVE(&xsoftc.ccb_scanq, &ccb->ccb_h, sim_links.tqe);
 			xpt_unlock_buses();
 
-			sim = ccb->ccb_h.path->bus->sim;
-			CAM_SIM_LOCK(sim);
 			xpt_action(ccb);
-			CAM_SIM_UNLOCK(sim);
 
 			xpt_lock_buses();
 		}
@@ -858,6 +849,8 @@ xpt_init(void *dummy)
 	mtx_init(&cam_simq_lock, "CAM SIMQ lock", NULL, MTX_DEF);
 	mtx_init(&xsoftc.xpt_lock, "XPT lock", NULL, MTX_DEF);
 	mtx_init(&xsoftc.xpt_topo_lock, "XPT topology lock", NULL, MTX_DEF);
+	xsoftc.xpt_taskq = taskqueue_create("CAM XPT task", M_WAITOK,
+	    taskqueue_thread_enqueue, /*context*/&xsoftc.xpt_taskq);
 
 #ifdef CAM_BOOT_DELAY
 	/*
@@ -1001,7 +994,7 @@ xpt_announce_periph(struct cam_periph *p
 {
 	struct	cam_path *path = periph->path;
 
-	mtx_assert(periph->sim->mtx, MA_OWNED);
+	cam_periph_assert(periph, MA_OWNED);
 
 	printf("%s%d at %s%d bus %d scbus%d target %d lun %d\n",
 	       periph->periph_name, periph->unit_number,
@@ -1057,7 +1050,7 @@ xpt_getattr(char *buf, size_t len, const
 	struct ccb_dev_advinfo cdai;
 	struct scsi_vpd_id_descriptor *idd;
 
-	mtx_assert(path->bus->sim->mtx, MA_OWNED);
+	xpt_path_assert(path, MA_OWNED);
 
 	memset(&cdai, 0, sizeof(cdai));
 	xpt_setup_ccb(&cdai.ccb_h, path, CAM_PRIORITY_NORMAL);
@@ -2026,9 +2019,7 @@ xptbustraverse(struct cam_eb *start_bus,
 		xpt_unlock_buses();
 	}
 	for (; bus != NULL; bus = next_bus) {
-		CAM_SIM_LOCK(bus->sim);
 		retval = tr_func(bus, arg);
-		CAM_SIM_UNLOCK(bus->sim);
 		if (retval == 0) {
 			xpt_release_bus(bus);
 			break;
@@ -2102,7 +2093,9 @@ xptdevicetraverse(struct cam_et *target,
 		mtx_unlock(&bus->eb_mtx);
 	}
 	for (; device != NULL; device = next_device) {
+		mtx_lock(&device->device_mtx);
 		retval = tr_func(device, arg);
+		mtx_unlock(&device->device_mtx);
 		if (retval == 0) {
 			xpt_release_device(device);
 			break;
@@ -2200,7 +2193,6 @@ xptpdperiphtraverse(struct periph_driver
 		    xpt_periphfunc_t *tr_func, void *arg)
 {
 	struct cam_periph *periph, *next_periph;
-	struct cam_sim *sim;
 	int retval;
 
 	retval = 1;
@@ -2220,10 +2212,9 @@ xptpdperiphtraverse(struct periph_driver
 		xpt_unlock_buses();
 	}
 	for (; periph != NULL; periph = next_periph) {
-		sim = periph->sim;
-		CAM_SIM_LOCK(sim);
+		cam_periph_lock(periph);
 		retval = tr_func(periph, arg);
-		CAM_SIM_UNLOCK(sim);
+		cam_periph_unlock(periph);
 		if (retval == 0) {
 			cam_periph_release(periph);
 			break;
@@ -2409,6 +2400,7 @@ xpt_action_default(union ccb *start_ccb)
 {
 	struct cam_path *path;
 	struct cam_sim *sim;
+	int lock;
 
 	path = start_ccb->ccb_h.path;
 	CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_action_default\n"));
@@ -2562,7 +2554,12 @@ xpt_action_default(union ccb *start_ccb)
 	case XPT_PATH_INQ:
 call_sim:
 		sim = path->bus->sim;
+		lock = (mtx_owned(sim->mtx) == 0);
+		if (lock)
+			CAM_SIM_LOCK(sim);
 		(*(sim->sim_action))(sim, start_ccb);
+		if (lock)
+			CAM_SIM_UNLOCK(sim);
 		break;
 	case XPT_PATH_STATS:
 		start_ccb->cpis.last_reset = path->bus->last_reset;
@@ -2725,11 +2722,6 @@ call_sim:
 				position_type = CAM_DEV_POS_PDRV;
 		}
 
-		/*
-		 * Note that we drop the SIM lock here, because the EDT
-		 * traversal code needs to do its own locking.
-		 */
-		CAM_SIM_UNLOCK(xpt_path_sim(cdm->ccb_h.path));
 		switch(position_type & CAM_DEV_POS_TYPEMASK) {
 		case CAM_DEV_POS_EDT:
 			xptedtmatch(cdm);
@@ -2741,7 +2733,6 @@ call_sim:
 			cdm->status = CAM_DEV_MATCH_ERROR;
 			break;
 		}
-		CAM_SIM_LOCK(xpt_path_sim(cdm->ccb_h.path));
 
 		if (cdm->status == CAM_DEV_MATCH_ERROR)
 			start_ccb->ccb_h.status = CAM_REQ_CMP_ERR;
@@ -2891,7 +2882,6 @@ call_sim:
 	}
 	case XPT_DEBUG: {
 		struct cam_path *oldpath;
-		struct cam_sim *oldsim;
 
 		/* Check that all request bits are supported. */
 		if (start_ccb->cdbg.flags & ~(CAM_DEBUG_COMPILE)) {
@@ -2901,15 +2891,9 @@ call_sim:
 
 		cam_dflags = CAM_DEBUG_NONE;
 		if (cam_dpath != NULL) {
-			/* To release the old path we must hold proper lock. */
 			oldpath = cam_dpath;
 			cam_dpath = NULL;
-			oldsim = xpt_path_sim(oldpath);
-			CAM_SIM_UNLOCK(xpt_path_sim(start_ccb->ccb_h.path));
-			CAM_SIM_LOCK(oldsim);
 			xpt_free_path(oldpath);
-			CAM_SIM_UNLOCK(oldsim);
-			CAM_SIM_LOCK(xpt_path_sim(start_ccb->ccb_h.path));
 		}
 		if (start_ccb->cdbg.flags != CAM_DEBUG_NONE) {
 			if (xpt_create_path(&cam_dpath, NULL,
@@ -3567,11 +3551,6 @@ xpt_path_string(struct cam_path *path, c
 {
 	struct sbuf sb;
 
-#ifdef INVARIANTS
-	if (path != NULL && path->bus != NULL)
-		mtx_assert(path->bus->sim->mtx, MA_OWNED);
-#endif
-
 	sbuf_new(&sb, str, str_len, 0);
 
 	if (path == NULL)
@@ -3639,8 +3618,8 @@ xpt_path_sim(struct cam_path *path)
 struct cam_periph*
 xpt_path_periph(struct cam_path *path)
 {
-	mtx_assert(path->bus->sim->mtx, MA_OWNED);
 
+	xpt_path_assert(path, MA_OWNED);
 	return (path->periph);
 }
 
@@ -3989,7 +3968,7 @@ xpt_async_process(struct cam_periph *per
 	path = ccb->ccb_h.path;
 	async_code = ccb->casync.async_code;
 	async_arg = ccb->casync.async_arg_ptr;
-	mtx_assert(path->bus->sim->mtx, MA_OWNED);
+//	mtx_assert(path->bus->sim->mtx, MA_OWNED);
 	CAM_DEBUG(path, CAM_DEBUG_TRACE | CAM_DEBUG_INFO,
 	    ("xpt_async(%s)\n", xpt_async_string(async_code)));
 
@@ -4535,6 +4514,16 @@ xpt_alloc_device_default(struct cam_eb *
 	return (device);
 }
 
+static void
+xpt_destroy_device(void *context, int pending)
+{
+	struct cam_ed	*device = context;
+
+	mtx_lock(&device->device_mtx);
+	mtx_destroy(&device->device_mtx);
+	free(device, M_CAMDEV);
+}
+
 struct cam_ed *
 xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
 {
@@ -4579,7 +4568,9 @@ xpt_alloc_device(struct cam_eb *bus, str
 	device->tag_delay_count = 0;
 	device->tag_saved_openings = 0;
 	device->refcount = 1;
+	mtx_init(&device->device_mtx, "CAM device lock", NULL, MTX_DEF);
 	callout_init_mtx(&device->callout, bus->sim->mtx, 0);
+	TASK_INIT(&device->device_destroy_task, 0, xpt_destroy_device, device);
 	/*
 	 * Hold a reference to our parent bus so it
 	 * will not go away before we do.
@@ -4651,7 +4642,7 @@ xpt_release_device(struct cam_ed *device
 	free(device->physpath, M_CAMXPT);
 	free(device->rcap_buf, M_CAMXPT);
 	free(device->serial_num, M_CAMXPT);
-	free(device, M_CAMDEV);
+	taskqueue_enqueue(xsoftc.xpt_taskq, &device->device_destroy_task);
 }
 
 u_int32_t
@@ -5004,6 +4995,49 @@ xpt_assert_buses(int what)
 	mtx_assert(&xsoftc.xpt_topo_lock, what);
 }
 
+void
+xpt_path_lock(struct cam_path *path)
+{
+
+	mtx_lock(&path->device->device_mtx);
+}
+
+void
+xpt_path_unlock(struct cam_path *path)
+{
+
+	mtx_unlock(&path->device->device_mtx);
+}
+
+void
+xpt_path_assert(struct cam_path *path, int what)
+{
+
+	mtx_assert(&path->device->device_mtx, what);
+}
+
+int
+xpt_path_owned(struct cam_path *path)
+{
+
+	return (mtx_owned(&path->device->device_mtx));
+}
+
+int
+xpt_path_sleep(struct cam_path *path, void *chan, int priority,
+    const char *wmesg, int timo)
+{
+
+	return (msleep(chan, &path->device->device_mtx, priority, wmesg, timo));
+}
+
+struct mtx *
+xpt_path_mtx(struct cam_path *path)
+{
+
+	return (&path->device->device_mtx);
+}
+
 static void
 camisr(void *dummy)
 {
@@ -5029,6 +5063,7 @@ static void
 camisr_runqueue(struct cam_sim *sim)
 {
 	struct	ccb_hdr *ccb_h;
+	struct mtx *mtx;
 
 	mtx_lock(&sim->sim_doneq_mtx);
 	while ((ccb_h = TAILQ_FIRST(&sim->sim_doneq)) != NULL) {
@@ -5069,6 +5104,9 @@ camisr_runqueue(struct cam_sim *sim)
 				mtx_unlock(&xsoftc.xpt_lock);
 		}
 
+		mtx = xpt_path_mtx(ccb_h->path);
+		mtx_lock(mtx);
+
 		if ((ccb_h->func_code & XPT_FC_USER_CCB) == 0) {
 			struct cam_ed *dev;
 
@@ -5098,11 +5136,8 @@ camisr_runqueue(struct cam_sim *sim)
 			mtx_unlock(&sim->devq->send_mtx);
 
 			if ((dev->flags & CAM_DEV_TAG_AFTER_COUNT) != 0
-			 && (--dev->tag_delay_count == 0)) {
-				CAM_SIM_LOCK(sim);
+			 && (--dev->tag_delay_count == 0))
 				xpt_start_tags(ccb_h->path);
-				CAM_SIM_UNLOCK(sim);
-			}
 		}
 
 		if (ccb_h->status & CAM_RELEASE_SIMQ) {
@@ -5118,9 +5153,8 @@ camisr_runqueue(struct cam_sim *sim)
 		}
 
 		/* Call the peripheral driver's callback */
-		CAM_SIM_LOCK(sim);
 		(*ccb_h->cbfcnp)(ccb_h->path->periph, (union ccb *)ccb_h);
-		CAM_SIM_UNLOCK(sim);
+		mtx_unlock(mtx);
 		mtx_lock(&sim->sim_doneq_mtx);
 	}
 	sim->sim_doneq_flags &= ~CAM_SIM_DQ_ONQ;

Modified: projects/camlock/sys/cam/cam_xpt.h
==============================================================================
--- projects/camlock/sys/cam/cam_xpt.h	Sun Aug 11 10:35:38 2013	(r254213)
+++ projects/camlock/sys/cam/cam_xpt.h	Sun Aug 11 10:54:16 2013	(r254214)
@@ -103,6 +103,14 @@ void			xpt_release_boot(void);
 void			xpt_lock_buses(void);
 void			xpt_unlock_buses(void);
 void			xpt_assert_buses(int what);
+void			xpt_path_lock(struct cam_path *path);
+void			xpt_path_unlock(struct cam_path *path);
+void			xpt_path_assert(struct cam_path *path, int what);
+int			xpt_path_owned(struct cam_path *path);
+int			xpt_path_sleep(struct cam_path *path, void *chan,
+				       int priority, const char *wmesg,
+				       int timo);
+struct mtx *		xpt_path_mtx(struct cam_path *path);
 cam_status		xpt_register_async(int event, ac_callback_t *cbfunc,
 					   void *cbarg, struct cam_path *path);
 cam_status		xpt_compile_path(struct cam_path *new_path,

Modified: projects/camlock/sys/cam/cam_xpt_internal.h
==============================================================================
--- projects/camlock/sys/cam/cam_xpt_internal.h	Sun Aug 11 10:35:38 2013	(r254213)
+++ projects/camlock/sys/cam/cam_xpt_internal.h	Sun Aug 11 10:54:16 2013	(r254214)
@@ -29,6 +29,8 @@
 #ifndef _CAM_CAM_XPT_INTERNAL_H
 #define _CAM_CAM_XPT_INTERNAL_H 1
 
+#include <sys/taskqueue.h>
+
 /* Forward Declarations */
 struct cam_eb;
 struct cam_et;
@@ -125,6 +127,8 @@ struct cam_ed {
 	u_int32_t	 refcount;
 	struct callout	 callout;
 	STAILQ_ENTRY(cam_ed) highpowerq_entry;
+	struct mtx	 device_mtx;
+	struct task	 device_destroy_task;
 };
 
 /*

Modified: projects/camlock/sys/cam/scsi/scsi_cd.c
==============================================================================
--- projects/camlock/sys/cam/scsi/scsi_cd.c	Sun Aug 11 10:35:38 2013	(r254213)
+++ projects/camlock/sys/cam/scsi/scsi_cd.c	Sun Aug 11 10:54:16 2013	(r254214)
@@ -982,9 +982,9 @@ cdregister(struct cam_periph *periph, vo
 			STAILQ_INIT(&nchanger->chluns);
 
 			callout_init_mtx(&nchanger->long_handle,
-			    periph->sim->mtx, 0);
+			    cam_periph_mtx(periph), 0);
 			callout_init_mtx(&nchanger->short_handle,
-			    periph->sim->mtx, 0);
+			    cam_periph_mtx(periph), 0);
 
 			mtx_lock(&changerq_mtx);
 			num_changers++;
@@ -1053,7 +1053,7 @@ cdregister(struct cam_periph *periph, vo
 	/*
 	 * Schedule a periodic media polling events.
 	 */
-	callout_init_mtx(&softc->mediapoll_c, periph->sim->mtx, 0);
+	callout_init_mtx(&softc->mediapoll_c, cam_periph_mtx(periph), 0);
 	if ((softc->flags & CD_FLAG_DISC_REMOVABLE) &&
 	    (softc->flags & CD_FLAG_CHANGER) == 0 &&
 	    (cgd->inq_flags & SID_AEN) == 0 &&

Modified: projects/camlock/sys/cam/scsi/scsi_ch.c
==============================================================================
--- projects/camlock/sys/cam/scsi/scsi_ch.c	Sun Aug 11 10:35:38 2013	(r254213)
+++ projects/camlock/sys/cam/scsi/scsi_ch.c	Sun Aug 11 10:54:16 2013	(r254214)
@@ -247,20 +247,19 @@ chinit(void)
 static void
 chdevgonecb(void *arg)
 {
-	struct cam_sim	  *sim;
 	struct ch_softc   *softc;
 	struct cam_periph *periph;
+	struct mtx *mtx;
 	int i;
 
 	periph = (struct cam_periph *)arg;
-	sim = periph->sim;
-	softc = (struct ch_softc *)periph->softc;
+	mtx = cam_periph_mtx(periph);
+	mtx_lock(mtx);
 
+	softc = (struct ch_softc *)periph->softc;
 	KASSERT(softc->open_count >= 0, ("Negative open count %d",
 		softc->open_count));
 
-	mtx_lock(sim->mtx);
-
 	/*
 	 * When we get this callback, we will get no more close calls from
 	 * devfs.  So if we have any dangling opens, we need to release the
@@ -277,13 +276,13 @@ chdevgonecb(void *arg)
 	cam_periph_release_locked(periph);
 
 	/*
-	 * We reference the SIM lock directly here, instead of using
+	 * We reference the lock directly here, instead of using
 	 * cam_periph_unlock().  The reason is that the final call to
 	 * cam_periph_release_locked() above could result in the periph
 	 * getting freed.  If that is the case, dereferencing the periph
 	 * with a cam_periph_unlock() call would cause a page fault.
 	 */
-	mtx_unlock(sim->mtx);
+	mtx_unlock(mtx);
 }
 
 static void
@@ -507,25 +506,23 @@ chopen(struct cdev *dev, int flags, int 
 static int
 chclose(struct cdev *dev, int flag, int fmt, struct thread *td)
 {
-	struct	cam_sim *sim;
 	struct	cam_periph *periph;
 	struct  ch_softc *softc;
+	struct mtx *mtx;
 
 	periph = (struct cam_periph *)dev->si_drv1;
 	if (periph == NULL)
 		return(ENXIO);
+	mtx = cam_periph_mtx(periph);
+	mtx_lock(mtx);
 
-	sim = periph->sim;
 	softc = (struct ch_softc *)periph->softc;
-
-	mtx_lock(sim->mtx);
-
 	softc->open_count--;
 
 	cam_periph_release_locked(periph);
 
 	/*
-	 * We reference the SIM lock directly here, instead of using
+	 * We reference the lock directly here, instead of using
 	 * cam_periph_unlock().  The reason is that the call to
 	 * cam_periph_release_locked() above could result in the periph
 	 * getting freed.  If that is the case, dereferencing the periph
@@ -536,7 +533,7 @@ chclose(struct cdev *dev, int flag, int 
 	 * protect the open count and avoid another lock acquisition and
 	 * release.
 	 */
-	mtx_unlock(sim->mtx);
+	mtx_unlock(mtx);
 
 	return(0);
 }
@@ -1715,10 +1712,8 @@ chscsiversion(struct cam_periph *periph)
 	struct scsi_inquiry_data *inq_data;
 	struct ccb_getdev *cgd;
 	int dev_scsi_version;
-	struct cam_sim *sim;
 
-	sim = xpt_path_sim(periph->path);
-	mtx_assert(sim->mtx, MA_OWNED);
+	cam_periph_assert(periph, MA_OWNED);
 	if ((cgd = (struct ccb_getdev *)xpt_alloc_ccb_nowait()) == NULL)
 		return (-1);
 	/*

Modified: projects/camlock/sys/cam/scsi/scsi_da.c
==============================================================================
--- projects/camlock/sys/cam/scsi/scsi_da.c	Sun Aug 11 10:35:38 2013	(r254213)
+++ projects/camlock/sys/cam/scsi/scsi_da.c	Sun Aug 11 10:54:16 2013	(r254214)
@@ -2037,7 +2037,7 @@ daregister(struct cam_periph *periph, vo
 	 * Schedule a periodic event to occasionally send an
 	 * ordered tag to a device.
 	 */
-	callout_init_mtx(&softc->sendordered_c, periph->sim->mtx, 0);
+	callout_init_mtx(&softc->sendordered_c, cam_periph_mtx(periph), 0);
 	callout_reset(&softc->sendordered_c,
 	    (da_default_timeout * hz) / DA_ORDEREDTAG_INTERVAL,
 	    dasendorderedtag, softc);
@@ -2157,7 +2157,7 @@ daregister(struct cam_periph *periph, vo
 	/*
 	 * Schedule a periodic media polling events.
 	 */
-	callout_init_mtx(&softc->mediapoll_c, periph->sim->mtx, 0);
+	callout_init_mtx(&softc->mediapoll_c, cam_periph_mtx(periph), 0);
 	if ((softc->flags & DA_FLAG_PACK_REMOVABLE) &&
 	    (cgd->inq_flags & SID_AEN) == 0 &&
 	    da_poll_period != 0)

Modified: projects/camlock/sys/cam/scsi/scsi_enc.c
==============================================================================
--- projects/camlock/sys/cam/scsi/scsi_enc.c	Sun Aug 11 10:35:38 2013	(r254213)
+++ projects/camlock/sys/cam/scsi/scsi_enc.c	Sun Aug 11 10:54:16 2013	(r254214)
@@ -110,17 +110,16 @@ enc_init(void)
 static void
 enc_devgonecb(void *arg)
 {
-	struct cam_sim    *sim;
 	struct cam_periph *periph;
 	struct enc_softc  *enc;
+	struct mtx *mtx;
 	int i;
 
 	periph = (struct cam_periph *)arg;
-	sim = periph->sim;
+	mtx = cam_periph_mtx(periph);
+	mtx_lock(mtx);
 	enc = (struct enc_softc *)periph->softc;
 
-	mtx_lock(sim->mtx);
-
 	/*
 	 * When we get this callback, we will get no more close calls from
 	 * devfs.  So if we have any dangling opens, we need to release the
@@ -137,13 +136,13 @@ enc_devgonecb(void *arg)
 	cam_periph_release_locked(periph);
 
 	/*
-	 * We reference the SIM lock directly here, instead of using
+	 * We reference the lock directly here, instead of using
 	 * cam_periph_unlock().  The reason is that the final call to
 	 * cam_periph_release_locked() above could result in the periph
 	 * getting freed.  If that is the case, dereferencing the periph
 	 * with a cam_periph_unlock() call would cause a page fault.
 	 */
-	mtx_unlock(sim->mtx);
+	mtx_unlock(mtx);
 }
 
 static void
@@ -301,25 +300,23 @@ out:
 static int
 enc_close(struct cdev *dev, int flag, int fmt, struct thread *td)
 {
-	struct cam_sim    *sim;
 	struct cam_periph *periph;
 	struct enc_softc  *enc;
+	struct mtx *mtx;
 
 	periph = (struct cam_periph *)dev->si_drv1;
 	if (periph == NULL)
 		return (ENXIO);
+	mtx = cam_periph_mtx(periph);
+	mtx_lock(mtx);
 
-	sim = periph->sim;
 	enc = periph->softc;
-
-	mtx_lock(sim->mtx);
-
 	enc->open_count--;
 
 	cam_periph_release_locked(periph);
 
 	/*
-	 * We reference the SIM lock directly here, instead of using
+	 * We reference the lock directly here, instead of using
 	 * cam_periph_unlock().  The reason is that the call to
 	 * cam_periph_release_locked() above could result in the periph
 	 * getting freed.  If that is the case, dereferencing the periph
@@ -330,7 +327,7 @@ enc_close(struct cdev *dev, int flag, in
 	 * protect the open count and avoid another lock acquisition and
 	 * release.
 	 */
-	mtx_unlock(sim->mtx);
+	mtx_unlock(mtx);
 
 	return (0);
 }
@@ -865,7 +862,7 @@ enc_kproc_init(enc_softc_t *enc)
 {
 	int result;
 
-	callout_init_mtx(&enc->status_updater, enc->periph->sim->mtx, 0);
+	callout_init_mtx(&enc->status_updater, cam_periph_mtx(enc->periph), 0);
 
 	if (cam_periph_acquire(enc->periph) != CAM_REQ_CMP)
 		return (ENXIO);

Modified: projects/camlock/sys/cam/scsi/scsi_enc_ses.c
==============================================================================
--- projects/camlock/sys/cam/scsi/scsi_enc_ses.c	Sun Aug 11 10:35:38 2013	(r254213)
+++ projects/camlock/sys/cam/scsi/scsi_enc_ses.c	Sun Aug 11 10:54:16 2013	(r254214)
@@ -915,10 +915,8 @@ ses_path_iter_devid_callback(enc_softc_t
 	cdm.matches         = &match_result;
 
 	sim = xpt_path_sim(cdm.ccb_h.path);
-	CAM_SIM_LOCK(sim);
 	xpt_action((union ccb *)&cdm);
 	xpt_free_path(cdm.ccb_h.path);
-	CAM_SIM_UNLOCK(sim);
 
 	if ((cdm.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP
 	 || (cdm.status != CAM_DEV_MATCH_LAST
@@ -935,10 +933,7 @@ ses_path_iter_devid_callback(enc_softc_t
 
 	args->callback(enc, elem, cdm.ccb_h.path, args->callback_arg);
 
-	sim = xpt_path_sim(cdm.ccb_h.path);
-	CAM_SIM_LOCK(sim);
 	xpt_free_path(cdm.ccb_h.path);
-	CAM_SIM_UNLOCK(sim);
 }
 
 /**

Modified: projects/camlock/sys/cam/scsi/scsi_pass.c
==============================================================================
--- projects/camlock/sys/cam/scsi/scsi_pass.c	Sun Aug 11 10:35:38 2013	(r254213)
+++ projects/camlock/sys/cam/scsi/scsi_pass.c	Sun Aug 11 10:54:16 2013	(r254214)
@@ -139,20 +139,19 @@ passinit(void)
 static void
 passdevgonecb(void *arg)
 {
-	struct cam_sim    *sim;
 	struct cam_periph *periph;
+	struct mtx *mtx;
 	struct pass_softc *softc;
 	int i;
 
 	periph = (struct cam_periph *)arg;
-	sim = periph->sim;
-	softc = (struct pass_softc *)periph->softc;
+	mtx = cam_periph_mtx(periph);
+	mtx_lock(mtx);
 
+	softc = (struct pass_softc *)periph->softc;
 	KASSERT(softc->open_count >= 0, ("Negative open count %d",
 		softc->open_count));
 
-	mtx_lock(sim->mtx);
-
 	/*
 	 * When we get this callback, we will get no more close calls from
 	 * devfs.  So if we have any dangling opens, we need to release the
@@ -169,13 +168,13 @@ passdevgonecb(void *arg)
 	cam_periph_release_locked(periph);
 
 	/*
-	 * We reference the SIM lock directly here, instead of using
+	 * We reference the lock directly here, instead of using
 	 * cam_periph_unlock().  The reason is that the final call to
 	 * cam_periph_release_locked() above could result in the periph
 	 * getting freed.  If that is the case, dereferencing the periph
 	 * with a cam_periph_unlock() call would cause a page fault.
 	 */
-	mtx_unlock(sim->mtx);
+	mtx_unlock(mtx);
 }
 
 static void
@@ -501,25 +500,23 @@ passopen(struct cdev *dev, int flags, in
 static int
 passclose(struct cdev *dev, int flag, int fmt, struct thread *td)
 {
-	struct  cam_sim    *sim;
 	struct 	cam_periph *periph;
 	struct  pass_softc *softc;
+	struct mtx *mtx;
 
 	periph = (struct cam_periph *)dev->si_drv1;
 	if (periph == NULL)
 		return (ENXIO);	
+	mtx = cam_periph_mtx(periph);
+	mtx_lock(mtx);
 
-	sim = periph->sim;
 	softc = periph->softc;
-
-	mtx_lock(sim->mtx);
-
 	softc->open_count--;
 
 	cam_periph_release_locked(periph);
 
 	/*
-	 * We reference the SIM lock directly here, instead of using
+	 * We reference the lock directly here, instead of using
 	 * cam_periph_unlock().  The reason is that the call to
 	 * cam_periph_release_locked() above could result in the periph
 	 * getting freed.  If that is the case, dereferencing the periph
@@ -530,7 +527,7 @@ passclose(struct cdev *dev, int flag, in
 	 * protect the open count and avoid another lock acquisition and
 	 * release.
 	 */
-	mtx_unlock(sim->mtx);
+	mtx_unlock(mtx);
 
 	return (0);
 }

Modified: projects/camlock/sys/cam/scsi/scsi_sg.c
==============================================================================
--- projects/camlock/sys/cam/scsi/scsi_sg.c	Sun Aug 11 10:35:38 2013	(r254213)
+++ projects/camlock/sys/cam/scsi/scsi_sg.c	Sun Aug 11 10:54:16 2013	(r254214)
@@ -170,20 +170,19 @@ sginit(void)
 static void
 sgdevgonecb(void *arg)
 {
-	struct cam_sim    *sim;
 	struct cam_periph *periph;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-projects mailing list