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/sd.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/sd.c')
-rw-r--r-- | sys/scsi/sd.c | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/sys/scsi/sd.c b/sys/scsi/sd.c index d7152397f64..b65b219aead 100644 --- a/sys/scsi/sd.c +++ b/sys/scsi/sd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sd.c,v 1.114 2006/11/28 16:56:50 dlg Exp $ */ +/* $OpenBSD: sd.c,v 1.115 2006/12/12 02:44:36 krw Exp $ */ /* $NetBSD: sd.c,v 1.111 1997/04/02 02:29:41 mycroft Exp $ */ /*- @@ -57,7 +57,7 @@ #include <sys/types.h> #include <sys/param.h> #include <sys/systm.h> -#include <sys/kernel.h> +#include <sys/timeout.h> #include <sys/file.h> #include <sys/stat.h> #include <sys/ioctl.h> @@ -98,6 +98,7 @@ void sdminphys(struct buf *); void sdgetdisklabel(dev_t, struct sd_softc *, struct disklabel *, struct cpu_disklabel *, int); void sdstart(void *); +void sdrestart(void *); void sddone(struct scsi_xfer *); void sd_shutdown(void *); int sd_reassign_blocks(struct sd_softc *, u_long); @@ -209,6 +210,8 @@ sdattach(parent, self, aux) */ printf("\n"); + timeout_set(&sd->sc_timeout, sdrestart, sd); + /* Spin up the unit ready or not. */ scsi_start(sc_link, SSS_START, scsi_autoconf | SCSI_SILENT | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE); @@ -495,6 +498,8 @@ sdclose(dev, flag, fmt, p) sd->sc_link->flags &= ~SDEV_EJECTING; } + + timeout_del(&sd->sc_timeout); } sdunlock(sd); @@ -601,7 +606,7 @@ done: * continues to be drained. * * must be called at the correct (highish) spl level - * sdstart() is called at splbio from sdstrategy and scsi_done + * sdstart() is called at splbio from sdstrategy, sdrestart and scsi_done */ void sdstart(v) @@ -706,14 +711,6 @@ sdstart(v) disk_busy(&sd->sc_dk); /* - * Mark the disk dirty so that the cache will be - * flushed on close. - */ - if ((bp->b_flags & B_READ) == 0) - sd->flags |= SDF_DIRTY; - - - /* * Call the routine that chats with the adapter. * Note: we cannot sleep as we may be an interrupt */ @@ -721,15 +718,45 @@ sdstart(v) (u_char *)bp->b_data, bp->b_bcount, SDRETRIES, 60000, bp, SCSI_NOSLEEP | ((bp->b_flags & B_READ) ? SCSI_DATA_IN : SCSI_DATA_OUT)); - if (error) { + switch (error) { + case 0: + /* + * Mark the disk dirty so that the cache will be + * flushed on close. + */ + if ((bp->b_flags & B_READ) == 0) + sd->flags |= SDF_DIRTY; + timeout_del(&sd->sc_timeout); + break; + case EAGAIN: + /* + * The device can't start another i/o. Try again later. + */ + dp->b_actf = bp; + disk_unbusy(&sd->sc_dk, 0, 0); + timeout_add(&sd->sc_timeout, 1); + return; + default: disk_unbusy(&sd->sc_dk, 0, 0); printf("%s: not queued, error %d\n", sd->sc_dev.dv_xname, error); + break; } } } void +sdrestart(v) + void *v; +{ + int s; + + s = splbio(); + sdstart(v); + splx(s); +} + +void sddone(xs) struct scsi_xfer *xs; { @@ -1036,6 +1063,8 @@ sd_shutdown(arg) */ if ((sd->flags & SDF_DIRTY) != 0) sd_flush(sd, SCSI_AUTOCONF); + + timeout_del(&sd->sc_timeout); } /* |