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