diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2004-01-17 14:40:56 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2004-01-17 14:40:56 +0000 |
commit | ce6c932e534ced3247e5faf28ff1c77eb9664764 (patch) | |
tree | fb56d657ea801967485048690762993ce6ee0b4d | |
parent | c565652eba846e8845339ef4e839de84cdc95944 (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.c | 11 | ||||
-rw-r--r-- | sys/dev/ic/aic7xxx_openbsd.c | 90 | ||||
-rw-r--r-- | sys/dev/ic/aic7xxx_openbsd.h | 21 | ||||
-rw-r--r-- | sys/dev/ic/aic7xxxvar.h | 7 |
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 |