Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 12 Oct 2013 14:21:04 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r256378 - in projects/camlock/sys: cam dev/ahci dev/mvs dev/siis
Message-ID:  <201310121421.r9CEL4l3051545@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Sat Oct 12 14:21:04 2013
New Revision: 256378
URL: http://svnweb.freebsd.org/changeset/base/256378

Log:
  Deprecate and remove old batch CCB completion mechanism xpt_batch_start() /
  xpt_batch_done() as not enough flexible and requiring extra locking.
  
  Instead declare new function xpt_done_direct() to allow SIM hint CAM that
  it holds no locks, reenterable, etc. and this request completion can be
  processed just now in place.  The new KPI may be a bit more complicated for
  use by SIM then previous, but it is more effcient and allows SIM to have
  several completion threads (interrupt vectors).

Modified:
  projects/camlock/sys/cam/cam_xpt.c
  projects/camlock/sys/cam/cam_xpt_sim.h
  projects/camlock/sys/dev/ahci/ahci.c
  projects/camlock/sys/dev/ahci/ahci.h
  projects/camlock/sys/dev/mvs/mvs.c
  projects/camlock/sys/dev/siis/siis.c

Modified: projects/camlock/sys/cam/cam_xpt.c
==============================================================================
--- projects/camlock/sys/cam/cam_xpt.c	Sat Oct 12 12:57:57 2013	(r256377)
+++ projects/camlock/sys/cam/cam_xpt.c	Sat Oct 12 14:21:04 2013	(r256378)
@@ -159,7 +159,8 @@ SYSCTL_INT(_kern_cam, OID_AUTO, boot_del
 
 struct cam_doneq {
 	struct mtx_padalign	cam_doneq_mtx;
-	TAILQ_HEAD(, ccb_hdr)	cam_doneq;
+	STAILQ_HEAD(, ccb_hdr)	cam_doneq;
+	int			cam_doneq_sleep;
 };
 
 static struct cam_doneq cam_doneqs[MAXCPU];
@@ -924,7 +925,7 @@ xpt_init(void *dummy)
 	for (i = 0; i < cam_num_doneqs; i++) {
 		mtx_init(&cam_doneqs[i].cam_doneq_mtx, "CAM doneq", NULL,
 		    MTX_DEF);
-		TAILQ_INIT(&cam_doneqs[i].cam_doneq);
+		STAILQ_INIT(&cam_doneqs[i].cam_doneq);
 		error = kproc_kthread_add(xpt_done_td, &cam_doneqs[i],
 		    &cam_proc, NULL, 0, 0, "cam", "doneq%d", i);
 		if (error != 0) {
@@ -4412,71 +4413,34 @@ xpt_release_simq_timeout(void *arg)
 void
 xpt_done(union ccb *done_ccb)
 {
-	struct cam_sim *sim;
 	struct cam_doneq *queue;
 	int	run, hash;
 
 	CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("xpt_done\n"));
-	if ((done_ccb->ccb_h.func_code & XPT_FC_QUEUED) != 0) {
-		/*
-		 * Queue up the request for handling by our SWI handler
-		 * any of the "non-immediate" type of ccbs.
-		 */
-		sim = done_ccb->ccb_h.path->bus->sim;
-		mtx_lock(&sim->sim_doneq_mtx);
-		if (sim->sim_doneq_flags & CAM_SIM_DQ_BATCH) {
-			TAILQ_INSERT_TAIL(&sim->sim_doneq, &done_ccb->ccb_h,
-			    sim_links.tqe);
-			done_ccb->ccb_h.pinfo.index = CAM_DONEQ_INDEX;
-			mtx_unlock(&sim->sim_doneq_mtx);
-			return;
-		}
-		run = ((sim->sim_doneq_flags & CAM_SIM_DQ_POLLED) == 0);
-		mtx_unlock(&sim->sim_doneq_mtx);
-		hash = (done_ccb->ccb_h.path_id + done_ccb->ccb_h.target_id +
-		    done_ccb->ccb_h.target_lun) % cam_num_doneqs;
-		queue = &cam_doneqs[hash];
-		mtx_lock(&queue->cam_doneq_mtx);
-		if (!TAILQ_EMPTY(&queue->cam_doneq))
-			run = 0;
-		TAILQ_INSERT_TAIL(&queue->cam_doneq, &done_ccb->ccb_h,
-		    sim_links.tqe);
-		done_ccb->ccb_h.pinfo.index = CAM_DONEQ_INDEX;
-		mtx_unlock(&queue->cam_doneq_mtx);
-		if (run)
-			wakeup(&queue->cam_doneq);
-	}
-}
-
-void
-xpt_batch_start(struct cam_sim *sim)
-{
+	if ((done_ccb->ccb_h.func_code & XPT_FC_QUEUED) == 0)
+		return;
 
-	mtx_lock(&sim->sim_doneq_mtx);
-	KASSERT((sim->sim_doneq_flags & CAM_SIM_DQ_BATCH) == 0,
-	    ("Batch flag already set"));
-	sim->sim_doneq_flags |= CAM_SIM_DQ_BATCH;
-	mtx_unlock(&sim->sim_doneq_mtx);
+	hash = (done_ccb->ccb_h.path_id + done_ccb->ccb_h.target_id +
+	    done_ccb->ccb_h.target_lun) % cam_num_doneqs;
+	queue = &cam_doneqs[hash];
+	mtx_lock(&queue->cam_doneq_mtx);
+	run = (queue->cam_doneq_sleep && STAILQ_EMPTY(&queue->cam_doneq));
+	STAILQ_INSERT_TAIL(&queue->cam_doneq, &done_ccb->ccb_h, sim_links.stqe);
+	done_ccb->ccb_h.pinfo.index = CAM_DONEQ_INDEX;
+	mtx_unlock(&queue->cam_doneq_mtx);
+	if (run)
+		wakeup(&queue->cam_doneq);
 }
 
 void
-xpt_batch_done(struct cam_sim *sim)
+xpt_done_direct(union ccb *done_ccb)
 {
-	struct ccb_hdr *ccb_h;
 
-	mtx_assert(sim->mtx, MA_NOTOWNED);
-	mtx_lock(&sim->sim_doneq_mtx);
-	KASSERT((sim->sim_doneq_flags & CAM_SIM_DQ_BATCH) != 0,
-	    ("Batch flag was not set"));
-	sim->sim_doneq_flags &= ~CAM_SIM_DQ_BATCH;
-	while ((ccb_h = TAILQ_FIRST(&sim->sim_doneq)) != NULL) {
-		TAILQ_REMOVE(&sim->sim_doneq, ccb_h, sim_links.tqe);
-		mtx_unlock(&sim->sim_doneq_mtx);
-		ccb_h->pinfo.index = CAM_UNQUEUED_INDEX;
-		xpt_done_process(ccb_h);
-		mtx_lock(&sim->sim_doneq_mtx);
-	}
-	mtx_unlock(&sim->sim_doneq_mtx);
+	CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("xpt_done_direct\n"));
+	if ((done_ccb->ccb_h.func_code & XPT_FC_QUEUED) == 0)
+		return;
+
+	xpt_done_process(&done_ccb->ccb_h);
 }
 
 union ccb *
@@ -5265,18 +5229,26 @@ xpt_done_td(void *arg)
 {
 	struct cam_doneq *queue = arg;
 	struct ccb_hdr *ccb_h;
+	STAILQ_HEAD(, ccb_hdr)	doneq;
 
+	STAILQ_INIT(&doneq);
 	mtx_lock(&queue->cam_doneq_mtx);
 	while (1) {
-		if ((ccb_h = TAILQ_FIRST(&queue->cam_doneq)) == NULL) {
+		while (STAILQ_EMPTY(&queue->cam_doneq)) {
+			queue->cam_doneq_sleep = 1;
 			msleep(&queue->cam_doneq, &queue->cam_doneq_mtx,
 			    PRIBIO, "-", 0);
-			continue;
+			queue->cam_doneq_sleep = 0;
 		}
-		TAILQ_REMOVE(&queue->cam_doneq, ccb_h, sim_links.tqe);
+		STAILQ_CONCAT(&doneq, &queue->cam_doneq);
 		mtx_unlock(&queue->cam_doneq_mtx);
-		ccb_h->pinfo.index = CAM_UNQUEUED_INDEX;
-		xpt_done_process(ccb_h);
+
+		while ((ccb_h = STAILQ_FIRST(&doneq)) != NULL) {
+			STAILQ_REMOVE_HEAD(&doneq, sim_links.stqe);
+			ccb_h->pinfo.index = CAM_UNQUEUED_INDEX;
+			xpt_done_process(ccb_h);
+		}
+
 		mtx_lock(&queue->cam_doneq_mtx);
 	}
 }
@@ -5304,8 +5276,8 @@ camisr_runqueue(struct cam_sim *sim)
 	for (i = 0; i < cam_num_doneqs; i++) {
 		queue = &cam_doneqs[i];
 		mtx_lock(&queue->cam_doneq_mtx);
-		while ((ccb_h = TAILQ_FIRST(&queue->cam_doneq)) != NULL) {
-			TAILQ_REMOVE(&queue->cam_doneq, ccb_h, sim_links.tqe);
+		while ((ccb_h = STAILQ_FIRST(&queue->cam_doneq)) != NULL) {
+			STAILQ_REMOVE_HEAD(&queue->cam_doneq, sim_links.stqe);
 			mtx_unlock(&queue->cam_doneq_mtx);
 			ccb_h->pinfo.index = CAM_UNQUEUED_INDEX;
 			xpt_done_process(ccb_h);

Modified: projects/camlock/sys/cam/cam_xpt_sim.h
==============================================================================
--- projects/camlock/sys/cam/cam_xpt_sim.h	Sat Oct 12 12:57:57 2013	(r256377)
+++ projects/camlock/sys/cam/cam_xpt_sim.h	Sat Oct 12 14:21:04 2013	(r256378)
@@ -46,8 +46,7 @@ u_int32_t	xpt_freeze_devq(struct cam_pat
 void		xpt_release_devq(struct cam_path *path,
 		    u_int count, int run_queue);
 void		xpt_done(union ccb *done_ccb);
-void		xpt_batch_start(struct cam_sim *sim);
-void		xpt_batch_done(struct cam_sim *sim);
+void		xpt_done_direct(union ccb *done_ccb);
 #endif
 
 #endif /* _CAM_CAM_XPT_SIM_H */

Modified: projects/camlock/sys/dev/ahci/ahci.c
==============================================================================
--- projects/camlock/sys/dev/ahci/ahci.c	Sat Oct 12 12:57:57 2013	(r256377)
+++ projects/camlock/sys/dev/ahci/ahci.c	Sat Oct 12 14:21:04 2013	(r256378)
@@ -1000,6 +1000,7 @@ ahci_ch_attach(device_t dev)
 	mtx_init(&ch->mtx, "AHCI channel lock", NULL, MTX_DEF);
 	resource_int_value(device_get_name(dev),
 	    device_get_unit(dev), "pm_level", &ch->pm_level);
+	STAILQ_INIT(&ch->doneq);
 	if (ch->pm_level > 3)
 		callout_init_mtx(&ch->pm_timer, &ch->mtx, 0);
 	callout_init_mtx(&ch->reset_timer, &ch->mtx, 0);
@@ -1465,16 +1466,35 @@ ahci_notify_events(device_t dev, u_int32
 }
 
 static void
+ahci_done(struct ahci_channel *ch, union ccb *ccb)
+{
+
+	mtx_assert(&ch->mtx, MA_OWNED);
+	if ((ccb->ccb_h.func_code & XPT_FC_QUEUED) == 0 ||
+	    ch->batch == 0) {
+		xpt_done(ccb);
+		return;
+	}
+
+	STAILQ_INSERT_TAIL(&ch->doneq, &ccb->ccb_h, sim_links.stqe);
+}
+
+static void
 ahci_ch_intr_locked(void *data)
 {
 	device_t dev = (device_t)data;
 	struct ahci_channel *ch = device_get_softc(dev);
+	struct ccb_hdr *ccb_h;
 
-	xpt_batch_start(ch->sim);
 	mtx_lock(&ch->mtx);
+	ch->batch = 1;
 	ahci_ch_intr(data);
+	ch->batch = 0;
 	mtx_unlock(&ch->mtx);
-	xpt_batch_done(ch->sim);
+	while ((ccb_h = STAILQ_FIRST(&ch->doneq)) != NULL) {
+		STAILQ_REMOVE_HEAD(&ch->doneq, sim_links.stqe);
+		xpt_done_direct((union ccb *)ccb_h);
+	}
 }
 
 static void
@@ -1598,7 +1618,7 @@ ahci_ch_intr(void *data)
 				xpt_freeze_devq(fccb->ccb_h.path, 1);
 				fccb->ccb_h.status |= CAM_DEV_QFRZN;
 			}
-			xpt_done(fccb);
+			ahci_done(ch, fccb);
 		}
 		for (i = 0; i < ch->numslots; i++) {
 			/* XXX: reqests in loading state. */
@@ -2007,7 +2027,7 @@ ahci_timeout(struct ahci_slot *slot)
 			xpt_freeze_devq(fccb->ccb_h.path, 1);
 			fccb->ccb_h.status |= CAM_DEV_QFRZN;
 		}
-		xpt_done(fccb);
+		ahci_done(ch, fccb);
 	}
 	if (!ch->fbs_enabled && !ch->wrongccs) {
 		/* Without FBS we know real timeout source. */
@@ -2213,7 +2233,7 @@ ahci_end_transaction(struct ahci_slot *s
 		ch->hold[slot->slot] = ccb;
 		ch->numhslots++;
 	} else
-		xpt_done(ccb);
+		ahci_done(ch, ccb);
 	/* If we have no other active commands, ... */
 	if (ch->rslots == 0) {
 		/* if there was fatal error - reset port. */
@@ -2273,7 +2293,7 @@ completeall:
 				continue;
 			ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK;
 			ch->hold[i]->ccb_h.status |= CAM_RESRC_UNAVAIL;
-			xpt_done(ch->hold[i]);
+			ahci_done(ch, ch->hold[i]);
 			ch->hold[i] = NULL;
 			ch->numhslots--;
 		}
@@ -2361,7 +2381,7 @@ ahci_process_read_log(device_t dev, unio
 				ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK;
 				ch->hold[i]->ccb_h.status |= CAM_REQUEUE_REQ;
 			}
-			xpt_done(ch->hold[i]);
+			ahci_done(ch, ch->hold[i]);
 			ch->hold[i] = NULL;
 			ch->numhslots--;
 		}
@@ -2376,7 +2396,7 @@ ahci_process_read_log(device_t dev, unio
 				continue;
 			if (ch->hold[i]->ccb_h.func_code != XPT_ATA_IO)
 				continue;
-			xpt_done(ch->hold[i]);
+			ahci_done(ch, ch->hold[i]);
 			ch->hold[i] = NULL;
 			ch->numhslots--;
 		}
@@ -2401,7 +2421,7 @@ ahci_process_request_sense(device_t dev,
 		ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK;
 		ch->hold[i]->ccb_h.status |= CAM_AUTOSENSE_FAIL;
 	}
-	xpt_done(ch->hold[i]);
+	ahci_done(ch, ch->hold[i]);
 	ch->hold[i] = NULL;
 	ch->numhslots--;
 	xpt_free_ccb(ccb);
@@ -2585,7 +2605,7 @@ ahci_reset(device_t dev)
 			xpt_freeze_devq(fccb->ccb_h.path, 1);
 			fccb->ccb_h.status |= CAM_DEV_QFRZN;
 		}
-		xpt_done(fccb);
+		ahci_done(ch, fccb);
 	}
 	/* Kill the engine and requeue all running commands. */
 	ahci_stop(dev);
@@ -2599,7 +2619,7 @@ ahci_reset(device_t dev)
 	for (i = 0; i < ch->numslots; i++) {
 		if (!ch->hold[i])
 			continue;
-		xpt_done(ch->hold[i]);
+		ahci_done(ch, ch->hold[i]);
 		ch->hold[i] = NULL;
 		ch->numhslots--;
 	}
@@ -2795,12 +2815,12 @@ ahci_check_ids(device_t dev, union ccb *
 
 	if (ccb->ccb_h.target_id > ((ch->caps & AHCI_CAP_SPM) ? 15 : 0)) {
 		ccb->ccb_h.status = CAM_TID_INVALID;
-		xpt_done(ccb);
+		ahci_done(ch, ccb);
 		return (-1);
 	}
 	if (ccb->ccb_h.target_lun != 0) {
 		ccb->ccb_h.status = CAM_LUN_INVALID;
-		xpt_done(ccb);
+		ahci_done(ch, ccb);
 		return (-1);
 	}
 	return (0);
@@ -2992,7 +3012,7 @@ ahciaction(struct cam_sim *sim, union cc
 		ccb->ccb_h.status = CAM_REQ_INVALID;
 		break;
 	}
-	xpt_done(ccb);
+	ahci_done(ch, ccb);
 }
 
 static void

Modified: projects/camlock/sys/dev/ahci/ahci.h
==============================================================================
--- projects/camlock/sys/dev/ahci/ahci.h	Sat Oct 12 12:57:57 2013	(r256377)
+++ projects/camlock/sys/dev/ahci/ahci.h	Sat Oct 12 14:21:04 2013	(r256378)
@@ -409,6 +409,8 @@ struct ahci_channel {
 	struct ahci_slot	slot[AHCI_MAX_SLOTS];
 	union ccb		*hold[AHCI_MAX_SLOTS];
 	struct mtx		mtx;		/* state lock */
+	STAILQ_HEAD(, ccb_hdr)	doneq;		/* queue of completed CCBs */
+	int			batch;		/* doneq is in use */
 	int			devices;        /* What is present */
 	int			pm_present;	/* PM presence reported */
 	int			fbs_enabled;	/* FIS-based switching enabled */

Modified: projects/camlock/sys/dev/mvs/mvs.c
==============================================================================
--- projects/camlock/sys/dev/mvs/mvs.c	Sat Oct 12 12:57:57 2013	(r256377)
+++ projects/camlock/sys/dev/mvs/mvs.c	Sat Oct 12 14:21:04 2013	(r256378)
@@ -653,11 +653,9 @@ mvs_ch_intr_locked(void *data)
 	device_t dev = (device_t)arg->arg;
 	struct mvs_channel *ch = device_get_softc(dev);
 
-	xpt_batch_start(ch->sim);
 	mtx_lock(&ch->mtx);
 	mvs_ch_intr(data);
 	mtx_unlock(&ch->mtx);
-	xpt_batch_done(ch->sim);
 }
 
 static void

Modified: projects/camlock/sys/dev/siis/siis.c
==============================================================================
--- projects/camlock/sys/dev/siis/siis.c	Sat Oct 12 12:57:57 2013	(r256377)
+++ projects/camlock/sys/dev/siis/siis.c	Sat Oct 12 14:21:04 2013	(r256378)
@@ -837,11 +837,9 @@ siis_ch_intr_locked(void *data)
 	device_t dev = (device_t)data;
 	struct siis_channel *ch = device_get_softc(dev);
 
-	xpt_batch_start(ch->sim);
 	mtx_lock(&ch->mtx);
 	siis_ch_intr(data);
 	mtx_unlock(&ch->mtx);
-	xpt_batch_done(ch->sim);
 }
 
 static void



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