summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2001-10-18 20:24:11 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2001-10-18 20:24:11 +0000
commit24abbe046ff63dcc748d3ef22c051f98a72c72c4 (patch)
treecd5d48de677f168e276cf9b2db1b9719b1cba058
parent02bff2e770cf30bed08a68301743697193f5e463 (diff)
solve numerous problems:
- free up ccb before calling scsi_done; - remove bogus tsleep/wakeup ccb availability mechanism; - fix an off by one size reporting in read_capacity. huge 10x to Alan Jones <RAJones@teklinks.com> and teklinks for providing a testbed and his time for testing. tests sustained 34 simultaneous tar zxvp at ldav of 76. however 36 simultaneous bonnies hang the machine, possibly for different reasons though. regardless, this fixed version passes an installation alright.
-rw-r--r--sys/dev/ic/cac.c82
1 files changed, 35 insertions, 47 deletions
diff --git a/sys/dev/ic/cac.c b/sys/dev/ic/cac.c
index 0bb2224ff0d..b1b983556b3 100644
--- a/sys/dev/ic/cac.c
+++ b/sys/dev/ic/cac.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: cac.c,v 1.6 2001/08/16 17:26:51 brad Exp $ */
+/* $OpenBSD: cac.c,v 1.7 2001/10/18 20:24:10 mickey Exp $ */
/* $NetBSD: cac.c,v 1.15 2000/11/08 19:20:35 ad Exp $ */
/*
- * Copyright (c) 2000 Michael Shalayeff
+ * Copyright (c) 2001 Michael Shalayeff
* All rights reserved.
*
* The SCSI emulation layer is derived from gdt(4) driver,
@@ -481,6 +481,7 @@ cac_ccb_done(struct cac_softc *sc, struct cac_ccb *ccb)
printf("%s: invalid request\n", sc->sc_dv.dv_xname);
}
+ cac_ccb_free(sc, ccb);
if (xs) {
if (error)
xs->error = XS_DRIVER_STUFFUP;
@@ -491,7 +492,6 @@ cac_ccb_done(struct cac_softc *sc, struct cac_ccb *ccb)
scsi_done(xs);
}
- cac_ccb_free(sc, ccb);
}
/*
@@ -504,19 +504,10 @@ cac_ccb_alloc(struct cac_softc *sc, int nosleep)
int s;
s = splbio();
-
- for (;;) {
- if ((ccb = SIMPLEQ_FIRST(&sc->sc_ccb_free)) != NULL) {
- SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ccb, ccb_chain);
- break;
- }
- if (nosleep) {
- ccb = NULL;
- break;
- }
- tsleep(&sc->sc_ccb_free, PRIBIO, "cacccb", 0);
- }
-
+ if ((ccb = SIMPLEQ_FIRST(&sc->sc_ccb_free)) != NULL)
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ccb, ccb_chain);
+ else
+ ccb = NULL;
splx(s);
return (ccb);
}
@@ -532,8 +523,6 @@ cac_ccb_free(struct cac_softc *sc, struct cac_ccb *ccb)
ccb->ccb_flags = 0;
s = splbio();
SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ccb, ccb_chain);
- if (SIMPLEQ_NEXT(ccb, ccb_chain) == NULL)
- wakeup(&sc->sc_ccb_free);
splx(s);
}
@@ -599,7 +588,7 @@ cac_scsi_cmd(xs)
u_int32_t blockno, blockcnt, size;
struct scsi_rw *rw;
struct scsi_rw_big *rwb;
- int op, flags, s;
+ int op, flags, s, error;
const char *p;
if (target >= sc->sc_nunits || link->lun != 0) {
@@ -697,7 +686,7 @@ cac_scsi_cmd(xs)
}
bzero(&rcd, sizeof rcd);
_lto4b( CAC_GET2(dinfo->ncylinders) * CAC_GET1(dinfo->nheads) *
- CAC_GET1(dinfo->nsectors), rcd.addr);
+ CAC_GET1(dinfo->nsectors) - 1, rcd.addr);
_lto4b(CAC_SECTOR_SIZE, rcd.length);
cac_copy_internal_data(xs, &rcd, sizeof rcd);
break;
@@ -723,30 +712,26 @@ cac_scsi_cmd(xs)
s = splbio();
flags = 0;
- if (xs->cmd->opcode != SYNCHRONIZE_CACHE) {
- /* A read or write operation. */
- if (xs->cmdlen == 6) {
- rw = (struct scsi_rw *)xs->cmd;
- blockno = _3btol(rw->addr) &
- (SRW_TOPADDR << 16 | 0xffff);
- blockcnt = rw->length ? rw->length : 0x100;
- } else {
- rwb = (struct scsi_rw_big *)xs->cmd;
- blockno = _4btol(rwb->addr);
- blockcnt = _2btol(rwb->length);
- }
- size = CAC_GET2(dinfo->ncylinders) *
- CAC_GET1(dinfo->nheads) *
- CAC_GET1(dinfo->nsectors);
- if (blockno >= size || blockno + blockcnt > size) {
- splx(s);
- printf("%s: out of bounds %u-%u >= %u\n",
- sc->sc_dv.dv_xname, blockno, blockcnt,
- size);
- xs->error = XS_DRIVER_STUFFUP;
- scsi_done(xs);
- return (COMPLETE);
- }
+ /* A read or write operation. */
+ if (xs->cmdlen == 6) {
+ rw = (struct scsi_rw *)xs->cmd;
+ blockno = _3btol(rw->addr) &
+ (SRW_TOPADDR << 16 | 0xffff);
+ blockcnt = rw->length ? rw->length : 0x100;
+ } else {
+ rwb = (struct scsi_rw_big *)xs->cmd;
+ blockno = _4btol(rwb->addr);
+ blockcnt = _2btol(rwb->length);
+ }
+ size = CAC_GET2(dinfo->ncylinders) *
+ CAC_GET1(dinfo->nheads) * CAC_GET1(dinfo->nsectors);
+ if (blockno >= size || blockno + blockcnt > size) {
+ splx(s);
+ printf("%s: out of bounds %u-%u >= %u\n",
+ sc->sc_dv.dv_xname, blockno, blockcnt, size);
+ xs->error = XS_DRIVER_STUFFUP;
+ scsi_done(xs);
+ return (COMPLETE);
}
switch (xs->cmd->opcode) {
@@ -762,11 +747,14 @@ cac_scsi_cmd(xs)
break;
}
- if (cac_cmd(sc, op, xs->data, blockcnt * DEV_BSIZE, target,
- blockno, flags, xs)) {
+ if ((error = cac_cmd(sc, op, xs->data, blockcnt * DEV_BSIZE,
+ target, blockno, flags, xs))) {
splx(s);
- if (xs->flags & SCSI_POLL) {
+ if (error == ENOMEM) {
+ xs->error = XS_DRIVER_STUFFUP;
+ return (TRY_AGAIN_LATER);
+ } else if (xs->flags & SCSI_POLL) {
xs->error = XS_TIMEOUT;
return (TRY_AGAIN_LATER);
} else {