From 8b4b54cb8d1d92e96f12520af6378a8e2486ad78 Mon Sep 17 00:00:00 2001 From: ad Date: Tue, 28 Nov 2006 20:29:14 +0000 Subject: [PATCH] Improve error handling. Related to PR/21900. --- sys/dev/eisa/cac_eisa.c | 8 ++++++-- sys/dev/ic/cac.c | 11 +++++++++-- sys/dev/ic/ld_cac.c | 29 +++++++++++++++++------------ sys/dev/pci/cac_pci.c | 7 +++++-- 4 files changed, 37 insertions(+), 18 deletions(-) diff --git a/sys/dev/eisa/cac_eisa.c b/sys/dev/eisa/cac_eisa.c index d9b3966cb0b7..26a392a63826 100644 --- a/sys/dev/eisa/cac_eisa.c +++ b/sys/dev/eisa/cac_eisa.c @@ -1,4 +1,4 @@ -/* $NetBSD: cac_eisa.c,v 1.15 2006/11/16 01:32:50 christos Exp $ */ +/* $NetBSD: cac_eisa.c,v 1.16 2006/11/28 20:29:14 ad Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -68,7 +68,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: cac_eisa.c,v 1.15 2006/11/16 01:32:50 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cac_eisa.c,v 1.16 2006/11/28 20:29:14 ad Exp $"); #include #include @@ -269,6 +269,10 @@ cac_eisa_l0_completed(struct cac_softc *sc) BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); ccb->ccb_req.error = status; + + if ((off & 3) != 0 && ccb->ccb_req.error == 0) + ccb->ccb_req.error = CAC_RET_CMD_REJECTED; + return (ccb); } diff --git a/sys/dev/ic/cac.c b/sys/dev/ic/cac.c index 147d9bf53df9..b4bd24bebd81 100644 --- a/sys/dev/ic/cac.c +++ b/sys/dev/ic/cac.c @@ -1,4 +1,4 @@ -/* $NetBSD: cac.c,v 1.36 2006/11/16 01:32:51 christos Exp $ */ +/* $NetBSD: cac.c,v 1.37 2006/11/28 20:29:14 ad Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -41,7 +41,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: cac.c,v 1.36 2006/11/16 01:32:51 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cac.c,v 1.37 2006/11/28 20:29:14 ad Exp $"); #include #include @@ -304,9 +304,13 @@ cac_cmd(struct cac_softc *sc, int command, void *data, int datasize, } ccb->ccb_hdr.drive = drive; + ccb->ccb_hdr.priority = 0; ccb->ccb_hdr.size = htole16((sizeof(struct cac_req) + sizeof(struct cac_sgb) * CAC_SG_SIZE) >> 2); + ccb->ccb_req.next = 0; + ccb->ccb_req.error = 0; + ccb->ccb_req.reserved = 0; ccb->ccb_req.bcount = htole16(howmany(size, DEV_BSIZE)); ccb->ccb_req.command = command; ccb->ccb_req.sgcount = nsegs; @@ -520,6 +524,9 @@ cac_l0_completed(struct cac_softc *sc) bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, off, sizeof(struct cac_ccb), BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); + if ((off & 3) != 0 && ccb->ccb_req.error == 0) + ccb->ccb_req.error = CAC_RET_CMD_REJECTED; + return (ccb); } diff --git a/sys/dev/ic/ld_cac.c b/sys/dev/ic/ld_cac.c index a463ccc1b24d..6059ffe58cc9 100644 --- a/sys/dev/ic/ld_cac.c +++ b/sys/dev/ic/ld_cac.c @@ -1,4 +1,4 @@ -/* $NetBSD: ld_cac.c,v 1.15 2006/11/16 01:32:51 christos Exp $ */ +/* $NetBSD: ld_cac.c,v 1.16 2006/11/28 20:29:14 ad Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -41,7 +41,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ld_cac.c,v 1.15 2006/11/16 01:32:51 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ld_cac.c,v 1.16 2006/11/28 20:29:14 ad Exp $"); #include "rnd.h" @@ -190,18 +190,24 @@ ld_cac_done(struct device *dv, void *context, int error) { struct buf *bp; struct ld_cac_softc *sc; + int rv; bp = context; + rv = 0; - if ((error & CAC_RET_HARD_ERROR) != 0) { + if ((error & CAC_RET_CMD_REJECTED) == CAC_RET_CMD_REJECTED) { + printf("%s: command rejected\n", dv->dv_xname); + rv = EIO; + } + if (rv == 0 && (error & CAC_RET_INVAL_BLOCK) != 0) { + printf("%s: invalid request block\n", dv->dv_xname); + rv = EIO; + } + if (rv == 0 && (error & CAC_RET_HARD_ERROR) != 0) { printf("%s: hard error\n", dv->dv_xname); - error = EIO; + rv = EIO; } - if ((error & CAC_RET_CMD_REJECTED) != 0) { - printf("%s: invalid request\n", dv->dv_xname); - error = EIO; - } - if ((error & CAC_RET_SOFT_ERROR) != 0) { + if (rv == 0 && (error & CAC_RET_SOFT_ERROR) != 0) { sc = (struct ld_cac_softc *)dv; sc->sc_serrcnt++; if (ratecheck(&sc->sc_serrtm, &ld_cac_serrintvl)) { @@ -209,12 +215,11 @@ ld_cac_done(struct device *dv, void *context, int error) dv->dv_xname, sc->sc_serrcnt); sc->sc_serrcnt = 0; } - error = 0; } - if (error) { + if (rv) { bp->b_flags |= B_ERROR; - bp->b_error = error; + bp->b_error = rv; bp->b_resid = bp->b_bcount; } else bp->b_resid = 0; diff --git a/sys/dev/pci/cac_pci.c b/sys/dev/pci/cac_pci.c index 003445dbb2fb..0e39e5f330f2 100644 --- a/sys/dev/pci/cac_pci.c +++ b/sys/dev/pci/cac_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: cac_pci.c,v 1.23 2006/11/16 01:33:08 christos Exp $ */ +/* $NetBSD: cac_pci.c,v 1.24 2006/11/28 20:29:14 ad Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -41,7 +41,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: cac_pci.c,v 1.23 2006/11/16 01:33:08 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cac_pci.c,v 1.24 2006/11/28 20:29:14 ad Exp $"); #include #include @@ -260,6 +260,9 @@ cac_pci_l0_completed(struct cac_softc *sc) bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, off, sizeof(struct cac_ccb), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + if ((off & 3) != 0 && ccb->ccb_req.error == 0) + ccb->ccb_req.error = CAC_RET_CMD_REJECTED; + return (ccb); }