summaryrefslogtreecommitdiffstats
path: root/sys/dev/esp
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2004-06-13 09:08:44 +0000
committerscottl <scottl@FreeBSD.org>2004-06-13 09:08:44 +0000
commit394bdac7dcbab39d03e0a5cdac350d93c81e71d3 (patch)
treedc50ad89e55871a5e8415c1de2d9fb9d7e36d26a /sys/dev/esp
parent0e5fdfdf5d24dc2e6902bd9e333e2395beaf9a05 (diff)
downloadFreeBSD-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.c57
-rw-r--r--sys/dev/esp/ncr53c9xvar.h16
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 */
OpenPOWER on IntegriCloud