diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2006-12-12 02:44:37 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2006-12-12 02:44:37 +0000 |
commit | 3aa62732c5bad060fc283109dc727af10ea5b33b (patch) | |
tree | b2cb582d8d7bea024ca8569003f10753f3e64879 /sys/scsi/st.c | |
parent | c44c57c509d3c1d486d9862ce728b61791d5d440 (diff) |
Give the SCSI layer the ability to requeue i/o's rejected by a driver
using the new NO_CCB result. Currently a no-op since no driver produces
that result.
ok dlg@ marco@ deraadt@
Diffstat (limited to 'sys/scsi/st.c')
-rw-r--r-- | sys/scsi/st.c | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/sys/scsi/st.c b/sys/scsi/st.c index 9386aba68fe..f7a08483410 100644 --- a/sys/scsi/st.c +++ b/sys/scsi/st.c @@ -1,4 +1,4 @@ -/* $OpenBSD: st.c,v 1.68 2006/11/28 16:56:50 dlg Exp $ */ +/* $OpenBSD: st.c,v 1.69 2006/12/12 02:44:36 krw Exp $ */ /* $NetBSD: st.c,v 1.71 1997/02/21 23:03:49 thorpej Exp $ */ /* @@ -57,6 +57,7 @@ #include <sys/types.h> #include <sys/param.h> #include <sys/systm.h> +#include <sys/timeout.h> #include <sys/fcntl.h> #include <sys/errno.h> #include <sys/ioctl.h> @@ -214,6 +215,7 @@ struct st_softc { #define BLKSIZE_SET_BY_QUIRK 0x08 /*--------------------storage for sense data returned by the drive------------*/ struct buf buf_queue; /* the queue of pending IO operations */ + struct timeout sc_timeout; }; @@ -225,6 +227,7 @@ int st_mount_tape(dev_t, int); void st_unmount(struct st_softc *, int, int); int st_decide_mode(struct st_softc *, int); void ststart(void *); +void strestart(void *); int st_read(struct st_softc *, char *, int, int); int st_read_block_limits(struct st_softc *, int); int st_mode_sense(struct st_softc *, int); @@ -323,6 +326,8 @@ stattach(parent, self, aux) st_identify_drive(st, sa->sa_inqbuf); printf("\n"); + timeout_set(&st->sc_timeout, strestart, st); + /* * Set up the buf queue for this device */ @@ -499,6 +504,7 @@ stclose(dev, flags, mode, p) break; } st->sc_link->flags &= ~SDEV_OPEN; + timeout_del(&st->sc_timeout); return 0; } @@ -834,7 +840,7 @@ done: * This routine is also called after other non-queued requests * have been made of the scsi driver, to ensure that the queue * continues to be drained. - * ststart() is called at splbio + * ststart() is called at splbio from ststrategy, strestart and scsi_done() */ void ststart(v) @@ -844,7 +850,7 @@ ststart(v) struct scsi_link *sc_link = st->sc_link; struct buf *bp, *dp; struct scsi_rw_tape cmd; - int flags; + int flags, error; SC_DEBUG(sc_link, SDEV_DB2, ("ststart\n")); @@ -958,13 +964,38 @@ ststart(v) /* * go ask the adapter to do all this for us */ - if (scsi_scsi_cmd(sc_link, (struct scsi_generic *) &cmd, + error = scsi_scsi_cmd(sc_link, (struct scsi_generic *) &cmd, sizeof(cmd), (u_char *) bp->b_data, bp->b_bcount, 0, - ST_IO_TIME, bp, flags | SCSI_NOSLEEP)) + ST_IO_TIME, bp, flags | SCSI_NOSLEEP); + switch (error) { + case 0: + timeout_del(&st->sc_timeout); + break; + case EAGAIN: + /* + * The device can't start another i/o. Try again later. + */ + dp->b_actf = bp; + timeout_add(&st->sc_timeout, 1); + return; + default: printf("%s: not queued\n", st->sc_dev.dv_xname); + break; + } } /* go back and see if we can cram more work in.. */ } +void +strestart(v) + void *v; +{ + int s; + + s = splbio(); + ststart(v); + splx(s); +} + int stread(dev, uio, iomode) dev_t dev; |