summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2004-01-17 14:40:56 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2004-01-17 14:40:56 +0000
commitce6c932e534ced3247e5faf28ff1c77eb9664764 (patch)
treefb56d657ea801967485048690762993ce6ee0b4d
parentc565652eba846e8845339ef4e839de84cdc95944 (diff)
Major stability improvement. Fix a variety of systems and problems
by dealing with various error conditions. Testing by Marco Peereboom, Olivier Cherrier, Alex Holst, Daniel Lucq, deraadt@, beck@ and others. ok deraadt@.
-rw-r--r--sys/dev/ic/aic7xxx.c11
-rw-r--r--sys/dev/ic/aic7xxx_openbsd.c90
-rw-r--r--sys/dev/ic/aic7xxx_openbsd.h21
-rw-r--r--sys/dev/ic/aic7xxxvar.h7
4 files changed, 61 insertions, 68 deletions
diff --git a/sys/dev/ic/aic7xxx.c b/sys/dev/ic/aic7xxx.c
index 955cdadee2d..bb823d5f31d 100644
--- a/sys/dev/ic/aic7xxx.c
+++ b/sys/dev/ic/aic7xxx.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aic7xxx.c,v 1.52 2003/12/24 22:45:45 krw Exp $ */
+/* $OpenBSD: aic7xxx.c,v 1.53 2004/01/17 14:40:55 krw Exp $ */
/* $NetBSD: aic7xxx.c,v 1.108 2003/11/02 11:07:44 wiz Exp $ */
/*
@@ -40,7 +40,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: aic7xxx.c,v 1.52 2003/12/24 22:45:45 krw Exp $
+ * $Id: aic7xxx.c,v 1.53 2004/01/17 14:40:55 krw Exp $
*
* //depot/aic7xxx/aic7xxx/aic7xxx.c#112 $
*
@@ -559,8 +559,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
* errors will be reported before any data
* phases occur.
*/
- if (ahc_get_transfer_length(scb) > 0 &&
- ahc_get_residual(scb)
+ if (ahc_get_residual(scb)
== ahc_get_transfer_length(scb)) {
ahc_update_neg_request(ahc, &devinfo,
tstate, targ_info,
@@ -2004,7 +2003,7 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
ahc_send_async(ahc, devinfo->channel, devinfo->target,
CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
- if (1 /*bootverbose*/ ) {
+ if (1 /*bootverbose*/) {
if (offset != 0) {
printf("%s: target %d synchronous at %sMHz%s, "
"offset = 0x%x\n", ahc_name(ahc),
@@ -2074,7 +2073,7 @@ ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
ahc_send_async(ahc, devinfo->channel, devinfo->target,
CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
- if (bootverbose) {
+ if (1 /*bootverbose*/) {
printf("%s: target %d using %dbit transfers\n",
ahc_name(ahc), devinfo->target,
8 * (0x01 << width));
diff --git a/sys/dev/ic/aic7xxx_openbsd.c b/sys/dev/ic/aic7xxx_openbsd.c
index e1f8dd20c63..540ca9beb66 100644
--- a/sys/dev/ic/aic7xxx_openbsd.c
+++ b/sys/dev/ic/aic7xxx_openbsd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aic7xxx_openbsd.c,v 1.19 2004/01/17 04:56:33 krw Exp $ */
+/* $OpenBSD: aic7xxx_openbsd.c,v 1.20 2004/01/17 14:40:55 krw Exp $ */
/* $NetBSD: aic7xxx_osm.c,v 1.14 2003/11/02 11:07:44 wiz Exp $ */
/*
@@ -51,16 +51,14 @@
#endif
-int32_t ahc_action(struct scsi_xfer *);
-int ahc_execute_scb(void *, bus_dma_segment_t *, int);
-int ahc_poll(struct ahc_softc *, int);
-int ahc_setup_data(struct ahc_softc *, struct scsi_xfer *,
- struct scb *);
-void ahc_set_recoveryscb(struct ahc_softc *, struct scb *);
-
-static void ahc_minphys(struct buf *);
-void ahc_adapter_req_set_xfer_mode(struct ahc_softc *, struct scb *);
+int ahc_action(struct scsi_xfer *);
+int ahc_execute_scb(void *, bus_dma_segment_t *, int);
+int ahc_poll(struct ahc_softc *, int);
+int ahc_setup_data(struct ahc_softc *, struct scsi_xfer *, struct scb *);
+void ahc_set_recoveryscb(struct ahc_softc *, struct scb *);
+void ahc_minphys(struct buf *);
+void ahc_adapter_req_set_xfer_mode(struct ahc_softc *, struct scb *);
struct cfdriver ahc_cd = {
@@ -244,7 +242,32 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
switch (xs->error) {
case CAM_REQ_INPROG:
case CAM_REQ_CMP:
- xs->error = XS_NOERROR;
+ switch (xs->status) {
+ case SCSI_TASKSET_FULL:
+ /* SCSI Layer won't requeue, so we force infinite
+ * retries until queue space is available. XS_BUSY
+ * is dangerous because if the NOSLEEP flag is set
+ * it can cause the I/O to return EIO. XS_BUSY code
+ * falls through to XS_TIMEOUT anyway.
+ */
+ xs->error = XS_TIMEOUT;
+ xs->retries++;
+ break;
+ case SCSI_BUSY:
+ xs->error = XS_BUSY;
+ break;
+ case SCSI_CHECK:
+ case SCSI_TERMINATED:
+ if ((scb->flags & SCB_SENSE) == 0) {
+ /* CHECK on CHECK? */
+ xs->error = XS_DRIVER_STUFFUP;
+ } else
+ xs->error = XS_NOERROR;
+ break;
+ default:
+ xs->error = XS_NOERROR;
+ break;
+ }
break;
case CAM_BUSY:
xs->error = XS_BUSY;
@@ -254,8 +277,10 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
break;
case CAM_BDR_SENT:
case CAM_SCSI_BUS_RESET:
- case CAM_REQUEUE_REQ:
xs->error = XS_RESET;
+ case CAM_REQUEUE_REQ:
+ xs->error = XS_TIMEOUT;
+ xs->retries++;
break;
case CAM_SEL_TIMEOUT:
xs->error = XS_SELTIMEOUT;
@@ -296,7 +321,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
scsi_done(xs);
}
-static void
+void
ahc_minphys(bp)
struct buf *bp;
{
@@ -377,7 +402,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
struct ahc_tmode_tstate *tstate;
u_int mask;
- int s, target;
+ int s;
scb = (struct scb *)arg;
xs = scb->xs;
@@ -475,7 +500,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
}
if ((tstate->tagenable & mask) != 0)
- ahc_set_transaction_tag(scb, TRUE, MSG_SIMPLE_TASK);
+ scb->hscb->control |= TAG_ENB;
bus_dmamap_sync(ahc->parent_dmat, ahc->scb_data->hscb_dmamap,
0, ahc->scb_data->hscb_dmamap->dm_mapsize,
@@ -529,6 +554,17 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
}
if (!(xs->flags & SCSI_POLL)) {
+ if (ahc->inited_target[xs->sc_link->target] == 0) {
+ struct ahc_devinfo devinfo;
+
+ ahc_adapter_req_set_xfer_mode(ahc, scb);
+ ahc_scb_devinfo(ahc, &devinfo, scb);
+ ahc_update_neg_request(ahc, &devinfo, tstate, tinfo,
+ AHC_NEG_IF_NON_ASYNC);
+
+ ahc->inited_target[xs->sc_link->target] = 1;
+ }
+
ahc_unlock(ahc, &s);
return (SUCCESSFULLY_QUEUED);
}
@@ -539,23 +575,6 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
poll:
SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_poll\n"));
- target = xs->sc_link->target;
- if (ahc->inited_target[target] == INITED_TARGET_INQUIRYOK) {
- struct ahc_initiator_tinfo *tinfo;
- struct ahc_tmode_tstate *tstate;
- struct ahc_devinfo devinfo;
-
- ahc_adapter_req_set_xfer_mode(ahc, scb);
-
- ahc_scb_devinfo(ahc, &devinfo, scb);
- tinfo = ahc_fetch_transinfo(ahc, devinfo.channel,
- devinfo.our_scsiid, devinfo.target, &tstate);
- ahc_update_neg_request(ahc, &devinfo, tstate, tinfo,
- AHC_NEG_IF_NON_ASYNC);
-
- ahc->inited_target[target] = INITED_TARGET_MODEOK;
- }
-
do {
if (ahc_poll(ahc, xs->timeout)) {
if (!(xs->flags & SCSI_SILENT))
@@ -565,11 +584,6 @@ poll:
}
} while (!(xs->flags & ITSDONE));
- if (ahc->inited_target[target] == INITED_TARGET_START) {
- if ((xs->cmd->opcode == INQUIRY) && (xs->error == XS_NOERROR))
- ahc->inited_target[target] = INITED_TARGET_INQUIRYOK;
- }
-
ahc_unlock(ahc, &s);
return (COMPLETE);
}
@@ -610,6 +624,7 @@ ahc_setup_data(struct ahc_softc *ahc, struct scsi_xfer *xs,
ahc_lock(ahc, &s);
ahc_free_scb(ahc, scb);
ahc_unlock(ahc, &s);
+ xs->flags |= ITSDONE;
scsi_done(xs);
return (COMPLETE);
}
@@ -637,6 +652,7 @@ ahc_setup_data(struct ahc_softc *ahc, struct scsi_xfer *xs,
ahc_name(ahc), error);
#endif
xs->error = XS_BUSY;
+ xs->flags |= ITSDONE;
scsi_done(xs);
return (TRY_AGAIN_LATER); /* XXX fvdl */
}
diff --git a/sys/dev/ic/aic7xxx_openbsd.h b/sys/dev/ic/aic7xxx_openbsd.h
index 9c9519e3cf5..e764513d3c7 100644
--- a/sys/dev/ic/aic7xxx_openbsd.h
+++ b/sys/dev/ic/aic7xxx_openbsd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: aic7xxx_openbsd.h,v 1.10 2003/12/28 21:29:27 krw Exp $ */
+/* $OpenBSD: aic7xxx_openbsd.h,v 1.11 2004/01/17 14:40:55 krw Exp $ */
/* $NetBSD: aic7xxx_osm.h,v 1.7 2003/11/02 11:07:44 wiz Exp $ */
/*
@@ -325,25 +325,6 @@ uint32_t ahc_get_scsi_status(struct scb *scb)
static __inline
void ahc_set_transaction_tag(struct scb *scb, int enabled, u_int type)
{
- /*
- * Assume that enabled == 0, or tstate->tagenable has already
- * been checked and found to be set.
- */
- switch (scb->xs->cmd->opcode) {
- case INQUIRY:
- case TEST_UNIT_READY:
- case REQUEST_SENSE:
- /* Don't use tagged i/o on these commands. */
- enabled = 0;
- break;
- default:
- break;
- }
-
- if (enabled)
- scb->hscb->control |= TAG_ENB;
- else
- scb->hscb->control &= ~TAG_ENB;
}
static __inline
diff --git a/sys/dev/ic/aic7xxxvar.h b/sys/dev/ic/aic7xxxvar.h
index 314708746c3..4533bf3e0c2 100644
--- a/sys/dev/ic/aic7xxxvar.h
+++ b/sys/dev/ic/aic7xxxvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: aic7xxxvar.h,v 1.17 2003/12/24 23:10:21 krw Exp $ */
+/* $OpenBSD: aic7xxxvar.h,v 1.18 2004/01/17 14:40:55 krw Exp $ */
/*
* Core definitions and data structures shareable across OS platforms.
*
@@ -38,7 +38,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: aic7xxxvar.h,v 1.17 2003/12/24 23:10:21 krw Exp $
+ * $Id: aic7xxxvar.h,v 1.18 2004/01/17 14:40:55 krw Exp $
*
* $FreeBSD: /repoman/r/ncvs/src/sys/dev/aic7xxx/aic7xxx.h,v 1.44 2003/01/20 20:44:55 gibbs Exp $
*/
@@ -1020,9 +1020,6 @@ struct ahc_softc {
struct ahc_tmode_tstate *enabled_targets[AHC_NUM_TARGETS];
char inited_target[AHC_NUM_TARGETS];
-#define INITED_TARGET_START 0
-#define INITED_TARGET_INQUIRYOK 1
-#define INITED_TARGET_MODEOK 2
/*
* The black hole device responsible for handling requests for