summaryrefslogtreecommitdiff
path: root/sys/scsi/sd.c
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2006-12-12 02:44:37 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2006-12-12 02:44:37 +0000
commit3aa62732c5bad060fc283109dc727af10ea5b33b (patch)
treeb2cb582d8d7bea024ca8569003f10753f3e64879 /sys/scsi/sd.c
parentc44c57c509d3c1d486d9862ce728b61791d5d440 (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.c53
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);
}
/*