summaryrefslogtreecommitdiff
path: root/sys/dev/ic
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 /sys/dev/ic
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.
Diffstat (limited to 'sys/dev/ic')
-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 {