svn commit: r254226 - projects/camlock/sys/cam

Alexander Motin mav at FreeBSD.org
Sun Aug 11 20:24:01 UTC 2013


Author: mav
Date: Sun Aug 11 20:24:00 2013
New Revision: 254226
URL: http://svnweb.freebsd.org/changeset/base/254226

Log:
  Replace single CAM SWI with set of per-SIM threads for sim_doneq processing.
  Than allows substantially improve SMP scalability with several HBAs.

Modified:
  projects/camlock/sys/cam/cam_sim.c
  projects/camlock/sys/cam/cam_sim.h
  projects/camlock/sys/cam/cam_xpt.c
  projects/camlock/sys/cam/cam_xpt.h

Modified: projects/camlock/sys/cam/cam_sim.c
==============================================================================
--- projects/camlock/sys/cam/cam_sim.c	Sun Aug 11 20:03:12 2013	(r254225)
+++ projects/camlock/sys/cam/cam_sim.c	Sun Aug 11 20:24:00 2013	(r254226)
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/malloc.h>
 #include <sys/kernel.h>
+#include <sys/kthread.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
 
@@ -65,6 +66,7 @@ cam_sim_alloc(sim_action_func sim_action
 	      int max_tagged_dev_transactions, struct cam_devq *queue)
 {
 	struct cam_sim *sim;
+	int error;
 
 	if (mtx == NULL)
 		return (NULL);
@@ -97,7 +99,13 @@ cam_sim_alloc(sim_action_func sim_action
 	}
 	mtx_init(&sim->sim_doneq_mtx, "CAM doneq", NULL, MTX_DEF);
 	TAILQ_INIT(&sim->sim_doneq);
-
+	error = kproc_kthread_add(xpt_done_td, sim, &cam_proc, NULL, 0, 0,
+	    "cam", "%s%d", sim_name, unit);
+	if (error != 0) {
+		mtx_destroy(&sim->sim_doneq_mtx);
+		free(sim, M_CAMSIM);
+		return (NULL);
+	}
 	return (sim);
 }
 
@@ -114,7 +122,12 @@ cam_sim_free(struct cam_sim *sim, int fr
 	}
 
 	KASSERT(sim->refcount == 0, ("sim->refcount == 0"));
-
+	mtx_lock(&sim->sim_doneq_mtx);
+	sim->sim_doneq_flags |= CAM_SIM_DQ_EXIT;
+	wakeup(&sim->sim_doneq);
+	mtx_unlock(&sim->sim_doneq_mtx);
+	while (sim->sim_doneq_flags & CAM_SIM_DQ_EXIT)
+		msleep(&sim->sim_doneq_flags, sim->mtx, PRIBIO, "simfree2", 0);
 	if (free_devq)
 		cam_simq_free(sim->devq);
 	mtx_destroy(&sim->sim_doneq_mtx);

Modified: projects/camlock/sys/cam/cam_sim.h
==============================================================================
--- projects/camlock/sys/cam/cam_sim.h	Sun Aug 11 20:03:12 2013	(r254225)
+++ projects/camlock/sys/cam/cam_sim.h	Sun Aug 11 20:24:00 2013	(r254226)
@@ -97,6 +97,7 @@ struct cam_sim {
 	TAILQ_HEAD(, ccb_hdr)	sim_doneq;
 	struct mtx		sim_doneq_mtx;
 	int			sim_doneq_flags;
+#define	CAM_SIM_DQ_EXIT		0x01
 #define	CAM_SIM_DQ_ONQ		0x04
 #define	CAM_SIM_DQ_POLLED	0x08
 #define	CAM_SIM_DQ_BATCH	0x10

Modified: projects/camlock/sys/cam/cam_xpt.c
==============================================================================
--- projects/camlock/sys/cam/cam_xpt.c	Sun Aug 11 20:03:12 2013	(r254225)
+++ projects/camlock/sys/cam/cam_xpt.c	Sun Aug 11 20:24:00 2013	(r254226)
@@ -156,15 +156,7 @@ TUNABLE_INT("kern.cam.boot_delay", &xsof
 SYSCTL_INT(_kern_cam, OID_AUTO, boot_delay, CTLFLAG_RDTUN,
            &xsoftc.boot_delay, 0, "Bus registration wait time");
 
-/* Queues for our software interrupt handler */
-typedef TAILQ_HEAD(cam_isrq, ccb_hdr) cam_isrq_t;
-typedef TAILQ_HEAD(cam_simq, cam_sim) cam_simq_t;
-static cam_simq_t cam_simq;
-static struct mtx cam_simq_lock;
-
-/* Pointers to software interrupt handlers */
-static void *cambio_ih;
-
+struct proc *cam_proc;
 struct cam_periph *xpt_periph;
 
 static periph_init_t xpt_periph_init;
@@ -249,7 +241,6 @@ static int	 xpt_schedule_dev(struct camq
 static xpt_devicefunc_t xptpassannouncefunc;
 static void	 xptaction(struct cam_sim *sim, union ccb *work_ccb);
 static void	 xptpoll(struct cam_sim *sim);
-static void	 camisr(void *);
 static void	 camisr_runqueue(struct cam_sim *);
 static dev_match_ret	xptbusmatch(struct dev_match_pattern *patterns,
 				    u_int num_patterns, struct cam_eb *bus);
@@ -841,12 +832,10 @@ xpt_init(void *dummy)
 	cam_status status;
 
 	TAILQ_INIT(&xsoftc.xpt_busses);
-	TAILQ_INIT(&cam_simq);
 	TAILQ_INIT(&xsoftc.ccb_scanq);
 	STAILQ_INIT(&xsoftc.highpowerq);
 	xsoftc.num_highpower = CAM_MAX_HIGHPOWER;
 
-	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,
@@ -904,8 +893,6 @@ xpt_init(void *dummy)
 			 path, NULL, 0, xpt_sim);
 	xpt_free_path(path);
 	mtx_unlock(&xsoftc.xpt_lock);
-	/* Install our software interrupt handlers */
-	swi_add(NULL, "cambio", camisr, NULL, SWI_CAMBIO, INTR_MPSAFE, &cambio_ih);
 	/*
 	 * Register a callback for when interrupts are enabled.
 	 */
@@ -4268,7 +4255,7 @@ void
 xpt_done(union ccb *done_ccb)
 {
 	struct cam_sim *sim;
-	int	first;
+	int	run;
 
 	CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("xpt_done\n"));
 	if ((done_ccb->ccb_h.func_code & XPT_FC_QUEUED) != 0) {
@@ -4283,16 +4270,13 @@ xpt_done(union ccb *done_ccb)
 		done_ccb->ccb_h.pinfo.index = CAM_DONEQ_INDEX;
 		if ((sim->sim_doneq_flags & (CAM_SIM_DQ_ONQ |
 		    CAM_SIM_DQ_POLLED | CAM_SIM_DQ_BATCH)) == 0) {
-			mtx_lock(&cam_simq_lock);
-			first = TAILQ_EMPTY(&cam_simq);
-			TAILQ_INSERT_TAIL(&cam_simq, sim, links);
-			mtx_unlock(&cam_simq_lock);
 			sim->sim_doneq_flags |= CAM_SIM_DQ_ONQ;
+			run = 1;
 		} else
-			first = 0;
+			run = 0;
 		mtx_unlock(&sim->sim_doneq_mtx);
-		if (first)
-			swi_sched(cambio_ih, 0);
+		if (run)
+			wakeup(&sim->sim_doneq);
 	}
 }
 
@@ -4799,7 +4783,8 @@ xpt_config(void *arg)
 	callout_reset(&xsoftc.boot_callout, hz * xsoftc.boot_delay / 1000,
 	    xpt_boot_delay, NULL);
 	/* Fire up rescan thread. */
-	if (kproc_create(xpt_scanner_thread, NULL, NULL, 0, 0, "xpt_thrd")) {
+	if (kproc_kthread_add(xpt_scanner_thread, NULL, &cam_proc, NULL, 0, 0,
+	    "cam", "scanner")) {
 		printf("xpt_config: failed to create rescan thread.\n");
 	}
 }
@@ -5025,25 +5010,30 @@ xpt_path_mtx(struct cam_path *path)
 	return (&path->device->device_mtx);
 }
 
-static void
-camisr(void *dummy)
+void
+xpt_done_td(void *arg)
 {
-	cam_simq_t queue;
-	struct cam_sim *sim;
-
-	mtx_lock(&cam_simq_lock);
-	TAILQ_INIT(&queue);
-	while (!TAILQ_EMPTY(&cam_simq)) {
-		TAILQ_CONCAT(&queue, &cam_simq, links);
-		mtx_unlock(&cam_simq_lock);
+	struct cam_sim *sim = arg;
 
-		while ((sim = TAILQ_FIRST(&queue)) != NULL) {
-			TAILQ_REMOVE(&queue, sim, links);
-			camisr_runqueue(sim);
+	mtx_lock(&sim->sim_doneq_mtx);
+	while (1) {
+		if (TAILQ_EMPTY(&sim->sim_doneq)) {
+			if (sim->sim_doneq_flags & CAM_SIM_DQ_EXIT) {
+				mtx_unlock(&sim->sim_doneq_mtx);
+				CAM_SIM_LOCK(sim);
+				sim->sim_doneq_flags &= ~CAM_SIM_DQ_EXIT;
+				wakeup(&sim->sim_doneq_flags);
+				CAM_SIM_UNLOCK(sim);
+				kthread_exit();
+			}
+			msleep(&sim->sim_doneq, &sim->sim_doneq_mtx, PRIBIO,
+			    "-", 0);
+			continue;
 		}
-		mtx_lock(&cam_simq_lock);
+		mtx_unlock(&sim->sim_doneq_mtx);
+		camisr_runqueue(sim);
+		mtx_lock(&sim->sim_doneq_mtx);
 	}
-	mtx_unlock(&cam_simq_lock);
 }
 
 static void

Modified: projects/camlock/sys/cam/cam_xpt.h
==============================================================================
--- projects/camlock/sys/cam/cam_xpt.h	Sun Aug 11 20:03:12 2013	(r254225)
+++ projects/camlock/sys/cam/cam_xpt.h	Sun Aug 11 20:24:00 2013	(r254226)
@@ -62,6 +62,7 @@ struct async_node {
 
 SLIST_HEAD(async_list, async_node);
 SLIST_HEAD(periph_list, cam_periph);
+extern struct proc *cam_proc;
 
 void			xpt_action(union ccb *new_ccb);
 void			xpt_action_default(union ccb *new_ccb);
@@ -123,6 +124,7 @@ void			xpt_copy_path(struct cam_path *ne
 				      struct cam_path *path);
 
 void			xpt_release_path(struct cam_path *path);
+void			xpt_done_td(void *);
 
 #endif /* _KERNEL */
 


More information about the svn-src-projects mailing list