svn commit: r256378 - in projects/camlock/sys: cam dev/ahci dev/mvs dev/siis
Alexander Motin
mav at FreeBSD.org
Sat Oct 12 14:21:05 UTC 2013
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
More information about the svn-src-projects
mailing list