Date: Sun, 11 Aug 2013 20:24:00 +0000 (UTC) From: Alexander Motin <mav@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r254226 - projects/camlock/sys/cam Message-ID: <201308112024.r7BKO0AF014817@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201308112024.r7BKO0AF014817>