summaryrefslogtreecommitdiff
path: root/sys/scsi
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2010-01-04 00:45:59 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2010-01-04 00:45:59 +0000
commit3c37e6c54ab0766909685e5fddd89f66190567ad (patch)
tree5b1407f0c8e0493aff980e61cbed9b5051980775 /sys/scsi
parentdd5aca9cf1071d4d2efdd8f2401cf52b7c6d896d (diff)
introduce scsi_xs_sync. this will synchronously execute a scsi_xfer
and do the appropriate sleeps, retries, error processing, and finally returns an errno style value to the caller. this cuts scsi_scsi_cmd, the ioctl code, sd_flush, and scsi_inquiry over to scsi_xs_sync. ok krw@
Diffstat (limited to 'sys/scsi')
-rw-r--r--sys/scsi/scsi_base.c178
-rw-r--r--sys/scsi/scsi_ioctl.c11
-rw-r--r--sys/scsi/scsiconf.h3
-rw-r--r--sys/scsi/sd.c23
4 files changed, 99 insertions, 116 deletions
diff --git a/sys/scsi/scsi_base.c b/sys/scsi/scsi_base.c
index 3b70483db52..10ece4311e6 100644
--- a/sys/scsi/scsi_base.c
+++ b/sys/scsi/scsi_base.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsi_base.c,v 1.149 2010/01/01 07:06:27 dlg Exp $ */
+/* $OpenBSD: scsi_base.c,v 1.150 2010/01/04 00:45:58 dlg Exp $ */
/* $NetBSD: scsi_base.c,v 1.43 1997/04/02 02:29:36 mycroft Exp $ */
/*
@@ -52,10 +52,10 @@
static __inline void asc2ascii(u_int8_t, u_int8_t ascq, char *result,
size_t len);
-int sc_err1(struct scsi_xfer *);
+int scsi_xs_error(struct scsi_xfer *);
char *scsi_decode_sense(struct scsi_sense_data *, int);
-void scsi_xs_done(struct scsi_xfer *);
+void scsi_xs_sync_done(struct scsi_xfer *);
/* Values for flag parameter to scsi_decode_sense. */
#define DECODE_SENSE_KEY 1
@@ -210,7 +210,7 @@ scsi_xs_get(struct scsi_link *link, int flags)
xs->flags = flags;
xs->sc_link = link;
xs->retries = SCSI_RETRIES;
- xs->timeout = 0;
+ xs->timeout = 10000;
bzero(&xs->cmdstore, sizeof(xs->cmdstore));
xs->cmd = &xs->cmdstore;
xs->cmdlen = 0;
@@ -334,32 +334,43 @@ scsi_test_unit_ready(struct scsi_link *sc_link, int retries, int flags)
* Use the scsi_cmd routine in the switch table.
*/
int
-scsi_inquire(struct scsi_link *sc_link, struct scsi_inquiry_data *inqbuf,
+scsi_inquire(struct scsi_link *link, struct scsi_inquiry_data *inqbuf,
int flags)
{
- struct scsi_inquiry scsi_cmd;
- int length;
- int error;
+ struct scsi_xfer *xs;
+ struct scsi_inquiry *cdb;
+ size_t length;
+ int error;
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.opcode = INQUIRY;
+ xs = scsi_xs_get(link, flags);
+ if (xs == NULL)
+ return (EBUSY);
- bzero(inqbuf, sizeof(*inqbuf));
+ /*
+ * Ask for only the basic 36 bytes of SCSI2 inquiry information. This
+ * avoids problems with devices that choke trying to supply more.
+ */
+ length = SID_INQUIRY_HDR + SID_SCSI2_ALEN;
+
+ cdb = (struct scsi_inquiry *)xs->cmd;
+ cdb->opcode = INQUIRY;
+ _lto2b(length, cdb->length);
+
+ xs->cmdlen = sizeof(*cdb);
+ xs->flags |= SCSI_DATA_IN;
+ xs->data = (void *)inqbuf;
+ xs->datalen = length;
+
+ bzero(inqbuf, sizeof(*inqbuf));
memset(&inqbuf->vendor, ' ', sizeof inqbuf->vendor);
memset(&inqbuf->product, ' ', sizeof inqbuf->product);
memset(&inqbuf->revision, ' ', sizeof inqbuf->revision);
memset(&inqbuf->extra, ' ', sizeof inqbuf->extra);
- /*
- * Ask for only the basic 36 bytes of SCSI2 inquiry information. This
- * avoids problems with devices that choke trying to supply more.
- */
- length = SID_INQUIRY_HDR + SID_SCSI2_ALEN;
- _lto2b(length, scsi_cmd.length);
- error = scsi_scsi_cmd(sc_link, (struct scsi_generic *)&scsi_cmd,
- sizeof(scsi_cmd), (u_char *)inqbuf, length, 2, 10000, NULL,
- SCSI_DATA_IN | flags);
+ error = scsi_xs_sync(xs);
+
+ scsi_xs_put(xs);
return (error);
}
@@ -764,6 +775,49 @@ scsi_done(struct scsi_xfer *xs)
xs->done(xs);
}
+int
+scsi_xs_sync(struct scsi_xfer *xs)
+{
+ struct mutex cookie = MUTEX_INITIALIZER(IPL_BIO);
+ int error;
+
+ /*
+ * If we cant sleep while waiting for completion, get the adapter to
+ * complete it for us.
+ */
+ if (ISSET(xs->flags, SCSI_NOSLEEP))
+ SET(xs->flags, SCSI_POLL);
+
+ xs->done = scsi_xs_sync_done;
+
+ do {
+ xs->cookie = &cookie;
+
+ scsi_xs_exec(xs);
+
+ mtx_enter(&cookie);
+ while (xs->cookie != NULL)
+ msleep(xs, &cookie, PRIBIO, "syncxs", 0);
+ mtx_leave(&cookie);
+
+ error = scsi_xs_error(xs);
+ } while (error == ERESTART);
+
+ return (error);
+}
+
+void
+scsi_xs_sync_done(struct scsi_xfer *xs)
+{
+ struct mutex *cookie = xs->cookie;
+
+ mtx_enter(cookie);
+ xs->cookie = NULL;
+ if (!ISSET(xs->flags, SCSI_NOSLEEP))
+ wakeup_one(xs);
+ mtx_leave(cookie);
+}
+
/*
* ask the scsi driver to perform a command for us.
* tell it where to read/write the data, and how
@@ -795,19 +849,7 @@ scsi_scsi_cmd(struct scsi_link *link, struct scsi_generic *scsi_cmd,
xs->retries = retries;
xs->timeout = timeout;
- xs->done = scsi_xs_done;
-
- do {
- scsi_xs_exec(xs);
- if (!ISSET(xs->flags, SCSI_POLL)) {
- s = splbio();
- while (!ISSET(xs->flags, ITSDONE))
- tsleep(xs, PRIBIO, "scsicmd", 0);
- splx(s);
- }
-
- error = sc_err1(xs);
- } while (error == ERESTART);
+ error = scsi_xs_sync(xs);
if (error != EAGAIN) {
if (bp != NULL) {
@@ -841,82 +883,48 @@ scsi_scsi_cmd(struct scsi_link *link, struct scsi_generic *scsi_cmd,
return (error);
}
-void
-scsi_xs_done(struct scsi_xfer *xs)
-{
- if (!ISSET(xs->flags, SCSI_POLL))
- wakeup_one(xs);
-}
-
int
-sc_err1(struct scsi_xfer *xs)
+scsi_xs_error(struct scsi_xfer *xs)
{
- int error;
+ int error = EIO;
- SC_DEBUG(xs->sc_link, SDEV_DB3, ("sc_err1,err = 0x%x\n", xs->error));
+ SC_DEBUG(xs->sc_link, SDEV_DB3, ("scsi_xs_error,err = 0x%x\n",
+ xs->error));
- /*
- * If it has a buf, we might be working with
- * a request from the buffer cache or some other
- * piece of code that requires us to process
- * errors at interrupt time. We have probably
- * been called by scsi_done()
- */
switch (xs->error) {
case XS_NOERROR: /* nearly always hit this one */
- error = 0;
+ return (0);
+ break;
+
+ case XS_NO_CCB:
+ return (EAGAIN);
break;
case XS_SENSE:
case XS_SHORTSENSE:
- if ((error = scsi_interpret_sense(xs)) == ERESTART)
- goto retry;
+ error = scsi_interpret_sense(xs);
SC_DEBUG(xs->sc_link, SDEV_DB3,
("scsi_interpret_sense returned %#x\n", error));
- break;
- case XS_BUSY:
- if (xs->retries) {
- if ((error = scsi_delay(xs, 1)) == EIO)
- goto lose;
- }
+ if (error != ERESTART)
+ xs->retries = 0;
+
/* FALLTHROUGH */
+ case XS_BUSY:
case XS_TIMEOUT:
- retry:
- if (xs->retries--) {
- xs->error = XS_NOERROR;
- xs->flags &= ~ITSDONE;
- return ERESTART;
- }
+ case XS_RESET:
+ if (xs->retries--)
+ return (ERESTART);
+
/* FALLTHROUGH */
case XS_DRIVER_STUFFUP:
- lose:
- error = EIO;
- break;
-
case XS_SELTIMEOUT:
- /* XXX Disable device? */
- error = EIO;
- break;
-
- case XS_RESET:
- if (xs->retries) {
- SC_DEBUG(xs->sc_link, SDEV_DB3,
- ("restarting command destroyed by reset\n"));
- goto retry;
- }
- error = EIO;
- break;
-
- case XS_NO_CCB:
- error = EAGAIN;
break;
default:
sc_print_addr(xs->sc_link);
printf("unknown error category (0x%x) from scsi driver\n",
xs->error);
- error = EIO;
break;
}
diff --git a/sys/scsi/scsi_ioctl.c b/sys/scsi/scsi_ioctl.c
index bda32e3516b..a65c41e1fc5 100644
--- a/sys/scsi/scsi_ioctl.c
+++ b/sys/scsi/scsi_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsi_ioctl.c,v 1.38 2009/12/01 01:40:02 dlg Exp $ */
+/* $OpenBSD: scsi_ioctl.c,v 1.39 2010/01/04 00:45:58 dlg Exp $ */
/* $NetBSD: scsi_ioctl.c,v 1.23 1996/10/12 23:23:17 christos Exp $ */
/*
@@ -100,7 +100,6 @@ scsi_ioc_cmd(struct scsi_link *link, scsireq_t *screq)
{
struct scsi_xfer *xs;
int err = 0;
- int s;
if (screq->cmdlen > sizeof(struct scsi_generic))
return (EFAULT);
@@ -132,13 +131,7 @@ scsi_ioc_cmd(struct scsi_link *link, scsireq_t *screq)
xs->timeout = screq->timeout;
xs->retries = 0; /* user must do the retries *//* ignored */
- xs->done = (void (*)(struct scsi_xfer *))wakeup;
-
- scsi_xs_exec(xs);
- s = splbio();
- while (!ISSET(xs->flags, ITSDONE))
- tsleep(xs, PRIBIO, "scsiioc", 0);
- splx(s);
+ scsi_xs_sync(xs);
screq->retsts = 0;
screq->status = xs->status;
diff --git a/sys/scsi/scsiconf.h b/sys/scsi/scsiconf.h
index e4f46398645..46419776443 100644
--- a/sys/scsi/scsiconf.h
+++ b/sys/scsi/scsiconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsiconf.h,v 1.116 2010/01/01 06:30:27 dlg Exp $ */
+/* $OpenBSD: scsiconf.h,v 1.117 2010/01/04 00:45:58 dlg Exp $ */
/* $NetBSD: scsiconf.h,v 1.35 1997/04/02 02:29:38 mycroft Exp $ */
/*
@@ -579,6 +579,7 @@ extern const u_int8_t version_to_spc[];
struct scsi_xfer * scsi_xs_get(struct scsi_link *, int);
void scsi_xs_exec(struct scsi_xfer *);
+int scsi_xs_sync(struct scsi_xfer *);
void scsi_xs_put(struct scsi_xfer *);
/*
diff --git a/sys/scsi/sd.c b/sys/scsi/sd.c
index 824729f8cb2..405e3b111e3 100644
--- a/sys/scsi/sd.c
+++ b/sys/scsi/sd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sd.c,v 1.173 2009/12/07 00:09:27 krw Exp $ */
+/* $OpenBSD: sd.c,v 1.174 2010/01/04 00:45:58 dlg Exp $ */
/* $NetBSD: sd.c,v 1.111 1997/04/02 02:29:41 mycroft Exp $ */
/*-
@@ -1471,8 +1471,6 @@ validate:
return (SDGP_RESULT_OK);
}
-void
-sd_flush_done(struct scsi_xfer *xs);
void
sd_flush(struct sd_softc *sc, int flags)
@@ -1502,17 +1500,7 @@ sd_flush(struct sd_softc *sc, int flags)
xs->cmdlen = sizeof(*cmd);
xs->timeout = 100000;
- xs->done = sd_flush_done;
-
- do {
- scsi_xs_exec(xs);
- if (!ISSET(xs->flags, SCSI_POLL)) {
- while (!ISSET(xs->flags, ITSDONE))
- tsleep(xs, PRIBIO, "sdflush", 0);
- }
- } while (xs->status == XS_NO_CCB);
-
- if (xs->error == XS_NOERROR)
+ if (scsi_xs_sync(xs) == 0)
sc->flags &= ~SDF_DIRTY;
else
SC_DEBUG(link, SDEV_DB1, ("cache sync failed\n"));
@@ -1520,13 +1508,6 @@ sd_flush(struct sd_softc *sc, int flags)
scsi_xs_put(xs);
}
-void
-sd_flush_done(struct scsi_xfer *xs)
-{
- if (!ISSET(xs->flags, SCSI_POLL))
- wakeup_one(xs);
-}
-
/*
* Remove unprocessed buffers from queue.
*/