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>