diff options
author | scottl <scottl@FreeBSD.org> | 2004-06-13 09:08:44 +0000 |
---|---|---|
committer | scottl <scottl@FreeBSD.org> | 2004-06-13 09:08:44 +0000 |
commit | 394bdac7dcbab39d03e0a5cdac350d93c81e71d3 (patch) | |
tree | dc50ad89e55871a5e8415c1de2d9fb9d7e36d26a /sys/dev/esp | |
parent | 0e5fdfdf5d24dc2e6902bd9e333e2395beaf9a05 (diff) | |
download | FreeBSD-src-394bdac7dcbab39d03e0a5cdac350d93c81e71d3.zip FreeBSD-src-394bdac7dcbab39d03e0a5cdac350d93c81e71d3.tar.gz |
Get rid of UMA zones and instead allocate all ecb's up front and track them
in a TAILQ. Re-arrange some of the ecb elements so that they can stay
stable through alloc/free cycles while the rest get bzero'd.
- Use the tag_id from the ecb rather than fro the ccb. The latter is only
for target mode.
- Honor the ccb flags for tag_action when deciding whether to do a tagged
or untagged transaction.
- Re-arrange autosense completion so that it works correctly in failure
cases.
- Turn on the PI_TAG_ABLE flag so that CAM will send us tagged transactions.
This enables tagged queueing in the driver.
Diffstat (limited to 'sys/dev/esp')
-rw-r--r-- | sys/dev/esp/ncr53c9x.c | 57 | ||||
-rw-r--r-- | sys/dev/esp/ncr53c9xvar.h | 16 |
2 files changed, 48 insertions, 25 deletions
diff --git a/sys/dev/esp/ncr53c9x.c b/sys/dev/esp/ncr53c9x.c index 7f42c7c..c83cf46 100644 --- a/sys/dev/esp/ncr53c9x.c +++ b/sys/dev/esp/ncr53c9x.c @@ -117,7 +117,6 @@ __FBSDID("$FreeBSD$"); #include <sys/queue.h> #include <sys/time.h> #include <sys/callout.h> -#include <vm/uma.h> #include <cam/cam.h> #include <cam/cam_ccb.h> @@ -185,9 +184,6 @@ static __inline void ncr53c9x_setsync(struct ncr53c9x_softc *, ((ms +0u) * hz) /1000u) #endif -static int ecb_zone_initialized = 0; -static uma_zone_t ecb_zone; - /* * Names for the NCR53c9x variants, correspnding to the variant tags * in ncr53c9xvar.h. @@ -228,6 +224,8 @@ ncr53c9x_attach(struct ncr53c9x_softc *sc) struct cam_devq *devq; struct cam_sim *sim; struct cam_path *path; + struct ncr53c9x_ecb *ecb; + int i; mtx_init(&sc->sc_lock, "ncr", "ncr53c9x lock", MTX_DEF); @@ -304,7 +302,8 @@ ncr53c9x_attach(struct ncr53c9x_softc *sc) return (ENOMEM); sim = cam_sim_alloc(ncr53c9x_action, ncr53c9x_poll, "esp", sc, - device_get_unit(sc->sc_dev), 256, 256, devq); + device_get_unit(sc->sc_dev), 1, + NCR_TAG_DEPTH, devq); if (sim == NULL) { cam_simq_free(devq); return (ENOMEM); @@ -332,6 +331,19 @@ ncr53c9x_attach(struct ncr53c9x_softc *sc) sc->sc_state = 0; ncr53c9x_init(sc, 1); + TAILQ_INIT(&sc->free_list); + if ((sc->ecb_array = malloc(sizeof(struct ncr53c9x_ecb) * NCR_TAG_DEPTH, + M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) { + device_printf(sc->sc_dev, "Cannot allocate ecb array!\n"); + return (ENOMEM); + } + for (i = 0; i < NCR_TAG_DEPTH; i++) { + ecb = &sc->ecb_array[i]; + ecb->sc = sc; + ecb->tag_id = i; + TAILQ_INSERT_HEAD(&sc->free_list, ecb, free_links); + } + callout_reset(&sc->sc_watchdog, 60*hz, ncr53c9x_watch, sc); return (0); @@ -453,14 +465,6 @@ ncr53c9x_init(struct ncr53c9x_softc *sc, int doreset) NCR_MISC(("[NCR_INIT(%d) %d] ", doreset, sc->sc_state)); - if (!ecb_zone_initialized) { - /* All instances share this zone */ - ecb_zone = uma_zcreate("ncr53c9x ecb zone", - sizeof(struct ncr53c9x_ecb), NULL, NULL, - NULL, NULL, 0, 0); - ecb_zone_initialized = 1; - } - if (sc->sc_state == 0) { /* First time through; initialize. */ @@ -791,7 +795,7 @@ ncr53c9x_free_ecb(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb) { ecb->flags = 0; - uma_zfree(ecb_zone, (void *)ecb); + TAILQ_INSERT_TAIL(&sc->free_list, ecb, free_links); return; } @@ -800,11 +804,14 @@ ncr53c9x_get_ecb(struct ncr53c9x_softc *sc) { struct ncr53c9x_ecb *ecb; - ecb = (struct ncr53c9x_ecb *)uma_zalloc(ecb_zone, M_NOWAIT); + ecb = TAILQ_FIRST(&sc->free_list); if (ecb) { - bzero(ecb, sizeof(struct ncr53c9x_ecb)); - ecb->flags |= ECB_ALLOC; - ecb->sc = sc; + if (ecb->flags != 0) + panic("ecb flags not cleared\n"); + TAILQ_REMOVE(&sc->free_list, ecb, free_links); + ecb->flags = ECB_ALLOC; + bzero(&ecb->ccb, sizeof(struct ncr53c9x_ecb) - + offsetof(struct ncr53c9x_ecb, ccb)); } return (ecb); } @@ -847,7 +854,7 @@ ncr53c9x_action(struct cam_sim *sim, union ccb *ccb) struct ccb_pathinq *cpi = &ccb->cpi; cpi->version_num = 1; - cpi->hba_inquiry = PI_SDTR_ABLE/*|PI_TAG_ABLE*/; + cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE; cpi->hba_inquiry |= (sc->sc_rev == NCR_VARIANT_FAS366) ? PI_WIDE_16 : 0; cpi->target_sprt = 0; @@ -1000,6 +1007,7 @@ ncr53c9x_action(struct cam_sim *sim, union ccb *ccb) ti->flags &= ~T_WIDE; ti->width = 0; } + ti->flags |= T_NEGOTIATE; } if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) { @@ -1088,6 +1096,10 @@ ncr53c9x_sched(struct ncr53c9x_softc *sc) tag = 0; else if ((ecb->flags & ECB_SENSE) != 0) tag = 0; + else if ((ecb->ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) == 0) + tag = 0; + else if (ecb->ccb->csio.tag_action == CAM_TAG_ACTION_NONE) + tag = 0; else tag = ecb->ccb->csio.tag_action; @@ -1122,8 +1134,8 @@ ncr53c9x_sched(struct ncr53c9x_softc *sc) } ecb->tag[0] = tag; if (tag != 0) { - li->queued[ecb->ccb->csio.tag_id] = ecb; - ecb->tag[1] = ecb->ccb->csio.tag_id; + li->queued[ecb->tag_id] = ecb; + ecb->tag[1] = ecb->tag_id; li->used++; } if (li->untagged != NULL && (li->busy != 1)) { @@ -1218,7 +1230,8 @@ ncr53c9x_done(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb) if (ccb->ccb_h.status == CAM_REQ_CMP) { if ((ecb->flags & ECB_ABORT) != 0) { ccb->ccb_h.status = CAM_CMD_TIMEOUT; - } else if ((ecb->flags & ECB_SENSE) != 0) { + } else if ((ecb->flags & ECB_SENSE) != 0 && + (ecb->stat != SCSI_STATUS_CHECK_COND)) { ccb->ccb_h.status = CAM_AUTOSNS_VALID; } else if (ecb->stat == SCSI_STATUS_CHECK_COND) { if ((ecb->flags & ECB_SENSE) != 0) diff --git a/sys/dev/esp/ncr53c9xvar.h b/sys/dev/esp/ncr53c9xvar.h index ba44566..be7f148 100644 --- a/sys/dev/esp/ncr53c9xvar.h +++ b/sys/dev/esp/ncr53c9xvar.h @@ -101,6 +101,9 @@ #define NCR_VARIANT_NCR53C90_86C01 10 #define NCR_VARIANT_MAX 11 +/* XXX Max tag depth. Should this be defined in the register header? */ +#define NCR_TAG_DEPTH 256 + /* * ECB. Holds additional information for each SCSI command Comments: We * need a separate scsi command block because we may need to overwrite it @@ -110,10 +113,14 @@ * occasionally xs->retries. */ struct ncr53c9x_ecb { - TAILQ_ENTRY(ncr53c9x_ecb) chain; - union ccb *ccb; /* SCSI xfer ctrl block from above */ + /* These fields are preserved between alloc and free */ struct ncr53c9x_softc *sc; + int tag_id; int flags; + + union ccb *ccb; /* SCSI xfer ctrl block from above */ + TAILQ_ENTRY(ncr53c9x_ecb) free_links; + TAILQ_ENTRY(ncr53c9x_ecb) chain; #define ECB_ALLOC 0x01 #define ECB_READY 0x02 #define ECB_SENSE 0x04 @@ -168,7 +175,7 @@ struct ncr53c9x_linfo { unsigned char avail; /* where to start scanning */ unsigned char busy; struct ncr53c9x_ecb *untagged; - struct ncr53c9x_ecb *queued[256]; + struct ncr53c9x_ecb *queued[NCR_TAG_DEPTH]; }; struct ncr53c9x_tinfo { @@ -348,6 +355,9 @@ struct ncr53c9x_softc { int sc_extended_geom; /* Should we return extended geometry */ struct mtx sc_lock; /* driver mutex */ + + struct ncr53c9x_ecb *ecb_array; + TAILQ_HEAD(,ncr53c9x_ecb) free_list; }; /* values for sc_state */ |