summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Peereboom <marco@cvs.openbsd.org>2005-08-31 17:59:10 +0000
committerMarco Peereboom <marco@cvs.openbsd.org>2005-08-31 17:59:10 +0000
commit5f12ab199fa7edf198981ba09a233c19c59e126c (patch)
tree4e4d5c14d3815600f716d40142ef53cc12db5671
parentb850c8825c8e65baaf654d2d40a3bd979aced394 (diff)
Fix some tsleep magic. Code done by krw@
feel free to commit, krw@ ok deraadt@
-rw-r--r--sys/dev/ic/ami.c70
-rw-r--r--sys/dev/ic/amivar.h6
2 files changed, 47 insertions, 29 deletions
diff --git a/sys/dev/ic/ami.c b/sys/dev/ic/ami.c
index d00f651d01e..cd9083d7b26 100644
--- a/sys/dev/ic/ami.c
+++ b/sys/dev/ic/ami.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ami.c,v 1.71 2005/08/31 12:52:36 marco Exp $ */
+/* $OpenBSD: ami.c,v 1.72 2005/08/31 17:59:09 marco Exp $ */
/*
* Copyright (c) 2001 Michael Shalayeff
@@ -160,7 +160,6 @@ ami_get_ccb(sc)
if (ccb) {
TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ccb_link);
ccb->ccb_state = AMI_CCB_READY;
- ccb->ccb_type = 0;
}
return ccb;
}
@@ -172,7 +171,8 @@ ami_put_ccb(ccb)
struct ami_softc *sc = ccb->ccb_sc;
ccb->ccb_state = AMI_CCB_FREE;
- ccb->ccb_type = 0;
+ ccb->ccb_done = NULL;
+ ccb->ami_pt.idata = NULL;
TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link);
}
@@ -1236,9 +1236,6 @@ ami_done(sc, idx)
memcpy(xs->data, ccb->ami_pt.idata +
sizeof(struct ami_passthrough),
xs->datalen);
-
- wakeup(ccb->ami_pt.idata);
- ccb->ami_pt.idata = NULL;
} else {
if (xs->cmd->opcode != PREVENT_ALLOW &&
xs->cmd->opcode != SYNCHRONIZE_CACHE)
@@ -1268,9 +1265,9 @@ ami_done(sc, idx)
}
}
- if (ccb->ccb_type == AMI_MGMT_CCB) {
- wakeup(sc);
- ccb->ccb_type = 0;
+ if (ccb->ccb_done) {
+ *ccb->ccb_done = 1;
+ wakeup((void *)ccb->ccb_done);
}
ami_put_ccb(ccb);
@@ -1328,6 +1325,7 @@ ami_scsi_raw_cmd(xs)
struct ami_passthrough *ps;
int error;
int direction;
+ volatile int done = 0;
ami_lock_t lock;
void *idata;
bus_dmamap_t idatamap;
@@ -1434,6 +1432,7 @@ ami_scsi_raw_cmd(xs)
ccb->ccb_xs = xs;
ccb->ccb_len = xs->datalen;
ccb->ccb_data = NULL;
+ ccb->ccb_done = &done;
ps->apt_param = AMI_PTPARAM(AMI_TIMEOUT_6,1,0);
ps->apt_channel = channel;
@@ -1451,6 +1450,9 @@ ami_scsi_raw_cmd(xs)
if (ccb->ami_pt.dir == AMI_PT_OUT)
memcpy(ccb->ami_pt.idata + sizeof *ps, xs->data, xs->datalen);
+ if (xs->flags & SCSI_POLL)
+ done = 1; /* Don't wait for completion twice. */
+
if ((error = ami_cmd(ccb, ((xs->flags & SCSI_NOSLEEP) ?
BUS_DMA_NOWAIT : BUS_DMA_WAITOK), xs->flags & SCSI_POLL))) {
ami_freemem(ccb->ami_pt.idata, sc->dmat, &idatamap, idataseg,
@@ -1476,8 +1478,10 @@ ami_scsi_raw_cmd(xs)
memcpy(xs->data, idata + sizeof *ps, xs->datalen);
scsi_done(xs);
- } else
- tsleep(ccb->ami_pt.idata, PRIBIO, "ami_pt", 0);
+ }
+
+ while (!done)
+ tsleep((void *)&done, PRIBIO, "ami_pt", 0);
ami_freemem(idata, sc->dmat, &idatamap, idataseg, NBPG, 1, "ami raw");
@@ -1864,18 +1868,24 @@ ami_drv_inq(sc, ch, tg, page, inqbuf)
bus_dma_segment_t idataseg[1];
paddr_t pa;
int error = 0;
+ volatile int done = 0;
+
+ ccb = ami_get_ccb(sc);
+ if (ccb == NULL)
+ return (ENOMEM);
if (!(idata = ami_allocmem(sc->dmat, &idatamap, idataseg, NBPG, 1,
- "ami mgmt")))
+ "ami mgmt"))) {
+ ami_put_ccb(ccb);
return (ENOMEM);
+ }
pa = idataseg[0].ds_addr;
ps = idata;
pp = idata + sizeof *ps;
- ccb = ami_get_ccb(sc);
ccb->ccb_data = NULL;
- ccb->ccb_type = AMI_MGMT_CCB;
+ ccb->ccb_done = &done;
cmd = ccb->ccb_cmd;
cmd->acc_cmd = AMI_PASSTHRU;
@@ -1904,10 +1914,12 @@ ami_drv_inq(sc, ch, tg, page, inqbuf)
ps->apt_datalen = sizeof(struct scsi_inquiry_data);
if (ami_cmd(ccb, BUS_DMA_WAITOK, 0) == 0) {
- if (tsleep(sc, PRIBIO, "ami_drv_inq", 15 * hz) == EWOULDBLOCK) {
- error = EINVAL;
- goto bail;
- }
+ while (!done)
+ if (tsleep((void *)&done, PRIBIO, "ami_drv_inq",
+ 15 * hz) == EWOULDBLOCK) {
+ error = EINVAL;
+ goto bail;
+ }
if (ps->apt_scsistat == 0x00) {
memcpy(inqbuf, pp, sizeof(struct scsi_inquiry_data));
@@ -1946,16 +1958,22 @@ ami_mgmt(sc, opcode, par1, par2, par3, size, buffer)
bus_dma_segment_t idataseg[1];
paddr_t pa;
int error = 0;
+ volatile int done = 0;
+
+ ccb = ami_get_ccb(sc);
+ if (ccb == NULL)
+ return (ENOMEM);
if (!(idata = ami_allocmem(sc->dmat, &idatamap, idataseg, NBPG,
- (size / NBPG) + 1, "ami mgmt")))
+ (size / NBPG) + 1, "ami mgmt"))) {
+ ami_put_ccb(ccb);
return (ENOMEM);
+ }
pa = idataseg[0].ds_addr;
- ccb = ami_get_ccb(sc);
ccb->ccb_data = NULL;
- ccb->ccb_type = AMI_MGMT_CCB;
+ ccb->ccb_done = &done;
cmd = ccb->ccb_cmd;
cmd->acc_cmd = opcode;
@@ -1977,10 +1995,12 @@ ami_mgmt(sc, opcode, par1, par2, par3, size, buffer)
cmd->acc_io.aio_data = htole32(pa);
if (ami_cmd(ccb, BUS_DMA_WAITOK, 0) == 0) {
- if (tsleep(sc, PRIBIO,"ami_mgmt", 15 * hz) == EWOULDBLOCK) {
- error = EINVAL;
- goto bail;
- }
+ while (!done)
+ if (tsleep((void *)&done, PRIBIO,"ami_mgmt",
+ 15 * hz) == EWOULDBLOCK) {
+ error = EINVAL;
+ goto bail;
+ }
/* XXX how do commands fail? */
diff --git a/sys/dev/ic/amivar.h b/sys/dev/ic/amivar.h
index 0d4d28f89a6..13bc4b085a7 100644
--- a/sys/dev/ic/amivar.h
+++ b/sys/dev/ic/amivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: amivar.h,v 1.20 2005/08/31 12:52:36 marco Exp $ */
+/* $OpenBSD: amivar.h,v 1.21 2005/08/31 17:59:09 marco Exp $ */
/*
* Copyright (c) 2001 Michael Shalayeff
@@ -42,9 +42,7 @@ struct ami_ccb {
#define AMI_PT_IN (0x00)
#define AMI_PT_OUT (0x01)
} ami_pt;
- int ccb_type;
-#define AMI_IO_CCB (0x00)
-#define AMI_MGMT_CCB (0x01)
+ volatile int *ccb_done;
TAILQ_ENTRY(ami_ccb) ccb_link;
enum {
AMI_CCB_FREE, AMI_CCB_READY, AMI_CCB_QUEUED, AMI_CCB_PREQUEUED