diff options
Diffstat (limited to 'sys/dev/aic/aic.c')
-rw-r--r-- | sys/dev/aic/aic.c | 106 |
1 files changed, 58 insertions, 48 deletions
diff --git a/sys/dev/aic/aic.c b/sys/dev/aic/aic.c index 4d5b5c3..d83df32 100644 --- a/sys/dev/aic/aic.c +++ b/sys/dev/aic/aic.c @@ -28,6 +28,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> +#include <sys/conf.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/lock.h> @@ -36,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <machine/bus.h> +#include <sys/rman.h> #include <cam/cam.h> #include <cam/cam_ccb.h> @@ -51,6 +53,7 @@ __FBSDID("$FreeBSD$"); static void aic_action(struct cam_sim *sim, union ccb *ccb); static void aic_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error); +static void aic_intr_locked(struct aic_softc *aic); static void aic_start(struct aic_softc *aic); static void aic_select(struct aic_softc *aic); static void aic_selected(struct aic_softc *aic); @@ -71,43 +74,42 @@ static void aic_reset(struct aic_softc *aic, int initiate_reset); devclass_t aic_devclass; -static struct aic_scb *free_scbs; - static struct aic_scb * aic_get_scb(struct aic_softc *aic) { struct aic_scb *scb; - int s = splcam(); - if ((scb = free_scbs) != NULL) - free_scbs = (struct aic_scb *)free_scbs->ccb; - splx(s); + + if (!dumping) + mtx_assert(&aic->lock, MA_OWNED); + if ((scb = SLIST_FIRST(&aic->free_scbs)) != NULL) + SLIST_REMOVE_HEAD(&aic->free_scbs, link); return (scb); } static void aic_free_scb(struct aic_softc *aic, struct aic_scb *scb) { - int s = splcam(); + + if (!dumping) + mtx_assert(&aic->lock, MA_OWNED); if ((aic->flags & AIC_RESOURCE_SHORTAGE) != 0 && (scb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { scb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ; aic->flags &= ~AIC_RESOURCE_SHORTAGE; } scb->flags = 0; - scb->ccb = (union ccb *)free_scbs; - free_scbs = scb; - splx(s); + SLIST_INSERT_HEAD(&aic->free_scbs, scb, link); } static void aic_action(struct cam_sim *sim, union ccb *ccb) { struct aic_softc *aic; - int s; CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("aic_action\n")); aic = (struct aic_softc *)cam_sim_softc(sim); + mtx_assert(&aic->lock, MA_OWNED); switch (ccb->ccb_h.func_code) { case XPT_SCSI_IO: /* Execute the requested I/O operation */ @@ -116,9 +118,7 @@ aic_action(struct cam_sim *sim, union ccb *ccb) struct aic_scb *scb; if ((scb = aic_get_scb(aic)) == NULL) { - s = splcam(); aic->flags |= AIC_RESOURCE_SHORTAGE; - splx(s); xpt_freeze_simq(aic->sim, /*count*/1); ccb->ccb_h.status = CAM_REQUEUE_REQ; xpt_done(ccb); @@ -175,8 +175,6 @@ aic_action(struct cam_sim *sim, union ccb *ccb) struct ccb_trans_settings_spi *spi = &cts->xport_specific.spi; - s = splcam(); - if ((spi->valid & CTS_SPI_VALID_DISC) != 0 && (aic->flags & AIC_DISC_ENABLE) != 0) { if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) @@ -214,7 +212,6 @@ aic_action(struct cam_sim *sim, union ccb *ccb) || (ti->goal.offset != ti->current.offset)) ti->flags |= TINFO_SDTR_NEGO; - splx(s); ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; @@ -235,7 +232,6 @@ aic_action(struct cam_sim *sim, union ccb *ccb) scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; - s = splcam(); if ((ti->flags & TINFO_DISC_ENB) != 0) spi->flags |= CTS_SPI_FLAGS_DISC_ENB; if ((ti->flags & TINFO_TAG_ENB) != 0) @@ -248,7 +244,6 @@ aic_action(struct cam_sim *sim, union ccb *ccb) spi->sync_period = ti->user.period; spi->sync_offset = ti->user.offset; } - splx(s); spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; spi->valid = CTS_SPI_VALID_SYNC_RATE @@ -311,12 +306,10 @@ aic_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) struct aic_scb *scb = (struct aic_scb *)arg; union ccb *ccb = scb->ccb; struct aic_softc *aic = (struct aic_softc *)ccb->ccb_h.ccb_aic_ptr; - int s; - - s = splcam(); + if (!dumping) + mtx_assert(&aic->lock, MA_OWNED); if (ccb->ccb_h.status != CAM_REQ_INPROG) { - splx(s); aic_free_scb(aic, scb); xpt_done(ccb); return; @@ -326,11 +319,10 @@ aic_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) ccb->ccb_h.status |= CAM_SIM_QUEUED; TAILQ_INSERT_TAIL(&aic->pending_ccbs, &ccb->ccb_h, sim_links.tqe); - ccb->ccb_h.timeout_ch = timeout(aic_timeout, (caddr_t)scb, - (ccb->ccb_h.timeout * hz) / 1000); + callout_reset(&scb->timer, (ccb->ccb_h.timeout * hz) / 1000, + aic_timeout, scb); aic_start(aic); - splx(s); } /* @@ -1053,7 +1045,7 @@ aic_done(struct aic_softc *aic, struct aic_scb *scb) ("aic_done - ccb %p status %x resid %d\n", ccb, ccb->ccb_h.status, ccb->csio.resid)); - untimeout(aic_timeout, (caddr_t)scb, ccb->ccb_h.timeout_ch); + callout_stop(&scb->timer); if ((scb->flags & SCB_DEVICE_RESET) != 0 && ccb->ccb_h.func_code != XPT_RESET_DEV) { @@ -1083,9 +1075,9 @@ aic_done(struct aic_softc *aic, struct aic_scb *scb) &pending_scb->ccb->ccb_h, sim_links.tqe); aic_done(aic, pending_scb); } else { - ccb_h->timeout_ch = - timeout(aic_timeout, (caddr_t)pending_scb, - (ccb_h->timeout * hz) / 1000); + callout_reset(&pending_scb->timer, + (ccb_h->timeout * hz) / 1000, aic_timeout, + pending_scb); ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe); } } @@ -1102,9 +1094,9 @@ aic_done(struct aic_softc *aic, struct aic_scb *scb) &nexus_scb->ccb->ccb_h, sim_links.tqe); aic_done(aic, nexus_scb); } else { - ccb_h->timeout_ch = - timeout(aic_timeout, (caddr_t)nexus_scb, - (ccb_h->timeout * hz) / 1000); + callout_reset(&nexus_scb->timer, + (ccb_h->timeout * hz) / 1000, aic_timeout, + nexus_scb); ccb_h = TAILQ_NEXT(ccb_h, sim_links.tqe); } } @@ -1123,7 +1115,7 @@ aic_done(struct aic_softc *aic, struct aic_scb *scb) static void aic_poll(struct cam_sim *sim) { - aic_intr(cam_sim_softc(sim)); + aic_intr_locked(cam_sim_softc(sim)); } static void @@ -1132,18 +1124,15 @@ aic_timeout(void *arg) struct aic_scb *scb = (struct aic_scb *)arg; union ccb *ccb = scb->ccb; struct aic_softc *aic = (struct aic_softc *)ccb->ccb_h.ccb_aic_ptr; - int s; + mtx_assert(&aic->lock, MA_OWNED); xpt_print_path(ccb->ccb_h.path); printf("ccb %p - timed out", ccb); if (aic->nexus && aic->nexus != scb) printf(", nexus %p", aic->nexus->ccb); printf(", phase 0x%x, state %d\n", aic_inb(aic, SCSISIGI), aic->state); - s = splcam(); - if ((scb->flags & SCB_ACTIVE) == 0) { - splx(s); xpt_print_path(ccb->ccb_h.path); printf("ccb %p - timed out already completed\n", ccb); return; @@ -1151,6 +1140,7 @@ aic_timeout(void *arg) if ((scb->flags & SCB_DEVICE_RESET) == 0 && aic->nexus == scb) { struct ccb_hdr *ccb_h = &scb->ccb->ccb_h; + struct aic_scb *pending_scb; if ((ccb_h->status & CAM_RELEASE_SIMQ) == 0) { xpt_freeze_simq(aic->sim, /*count*/1); @@ -1158,18 +1148,17 @@ aic_timeout(void *arg) } TAILQ_FOREACH(ccb_h, &aic->pending_ccbs, sim_links.tqe) { - untimeout(aic_timeout, (caddr_t)ccb_h->ccb_scb_ptr, - ccb_h->timeout_ch); + pending_scb = ccb_h->ccb_scb_ptr; + callout_stop(&pending_scb->timer); } TAILQ_FOREACH(ccb_h, &aic->nexus_ccbs, sim_links.tqe) { - untimeout(aic_timeout, (caddr_t)ccb_h->ccb_scb_ptr, - ccb_h->timeout_ch); + pending_scb = ccb_h->ccb_scb_ptr; + callout_stop(&pending_scb->timer); } scb->flags |= SCB_DEVICE_RESET; - ccb->ccb_h.timeout_ch = - timeout(aic_timeout, (caddr_t)scb, 5 * hz); + callout_reset(&scb->timer, 5 * hz, aic_timeout, scb); aic_sched_msgout(aic, MSG_BUS_DEV_RESET); } else { if (aic->nexus == scb) { @@ -1178,14 +1167,21 @@ aic_timeout(void *arg) } aic_reset(aic, /*initiate_reset*/TRUE); } - - splx(s); } void aic_intr(void *arg) { struct aic_softc *aic = (struct aic_softc *)arg; + + mtx_lock(&aic->lock); + aic_intr_locked(aic); + mtx_unlock(&aic->lock); +} + +void +aic_intr_locked(struct aic_softc *aic) +{ u_int8_t sstat0, sstat1; union ccb *ccb; struct aic_scb *scb; @@ -1434,6 +1430,7 @@ aic_init(struct aic_softc *aic) TAILQ_INIT(&aic->pending_ccbs); TAILQ_INIT(&aic->nexus_ccbs); + SLIST_INIT(&aic->free_scbs); aic->nexus = NULL; aic->state = AIC_IDLE; aic->prev_phase = -1; @@ -1481,10 +1478,10 @@ aic_init(struct aic_softc *aic) aic->max_period = AIC_SYNC_PERIOD; aic->min_period = AIC_MIN_SYNC_PERIOD; - free_scbs = NULL; for (i = 255; i >= 0; i--) { scb = &aic->scbs[i]; scb->tag = i; + callout_init_mtx(&scb->timer, &aic->lock, 0); aic_free_scb(aic, scb); } @@ -1543,14 +1540,16 @@ aic_attach(struct aic_softc *aic) * Construct our SIM entry */ aic->sim = cam_sim_alloc(aic_action, aic_poll, "aic", aic, - aic->unit, &Giant, 2, 256, devq); + device_get_unit(aic->dev), &aic->lock, 2, 256, devq); if (aic->sim == NULL) { cam_simq_free(devq); return (ENOMEM); } + mtx_lock(&aic->lock); if (xpt_bus_register(aic->sim, aic->dev, 0) != CAM_SUCCESS) { cam_sim_free(aic->sim, /*free_devq*/TRUE); + mtx_unlock(&aic->lock); return (ENXIO); } @@ -1559,12 +1558,13 @@ aic_attach(struct aic_softc *aic) CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path(aic->sim)); cam_sim_free(aic->sim, /*free_devq*/TRUE); + mtx_unlock(&aic->lock); return (ENXIO); } aic_init(aic); - printf("aic%d: %s", aic->unit, aic_chip_names[aic->chip_type]); + device_printf(aic->dev, "%s", aic_chip_names[aic->chip_type]); if (aic->flags & AIC_DMA_ENABLE) printf(", dma"); if (aic->flags & AIC_DISC_ENABLE) @@ -1574,15 +1574,25 @@ aic_attach(struct aic_softc *aic) if (aic->flags & AIC_FAST_ENABLE) printf(", fast SCSI"); printf("\n"); + mtx_unlock(&aic->lock); return (0); } int aic_detach(struct aic_softc *aic) { + struct aic_scb *scb; + int i; + + mtx_lock(&aic->lock); xpt_async(AC_LOST_DEVICE, aic->path, NULL); xpt_free_path(aic->path); xpt_bus_deregister(cam_sim_path(aic->sim)); cam_sim_free(aic->sim, /*free_devq*/TRUE); + mtx_unlock(&aic->lock); + for (i = 255; i >= 0; i--) { + scb = &aic->scbs[i]; + callout_drain(&scb->timer); + } return (0); } |