diff options
| author | jdolecek <jdolecek@NetBSD.org> | 2017-02-27 21:32:33 +0000 |
|---|---|---|
| committer | jdolecek <jdolecek@NetBSD.org> | 2017-02-27 21:32:33 +0000 |
| commit | 141e580a02b235aaa20bbecb460d1fc77d187cac (patch) | |
| tree | 75c6d3c8c744246fdeba54a67d3494dc34e5dee1 /sys/dev | |
| parent | cb85970f3b66566d3f60953f906df56cd379af92 (diff) | |
refactor the ld(4) DIOCCACHESYNC hook into general ioctl hook, so that attachments
would be able to implement arbitrary other ioctls
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/i2o/ld_iop.c | 31 | ||||
| -rw-r--r-- | sys/dev/ic/ld_icp.c | 30 | ||||
| -rw-r--r-- | sys/dev/ic/ld_nvme.c | 33 | ||||
| -rw-r--r-- | sys/dev/ld.c | 65 | ||||
| -rw-r--r-- | sys/dev/ldvar.h | 7 | ||||
| -rw-r--r-- | sys/dev/pci/ld_twa.c | 29 | ||||
| -rw-r--r-- | sys/dev/pci/ld_twe.c | 31 | ||||
| -rw-r--r-- | sys/dev/pci/ld_virtio.c | 5 |
8 files changed, 169 insertions, 62 deletions
diff --git a/sys/dev/i2o/ld_iop.c b/sys/dev/i2o/ld_iop.c index 6e2526a5dcc..51d13bd359c 100644 --- a/sys/dev/i2o/ld_iop.c +++ b/sys/dev/i2o/ld_iop.c @@ -1,4 +1,4 @@ -/* $NetBSD: ld_iop.c,v 1.36 2016/09/16 15:20:50 jdolecek Exp $ */ +/* $NetBSD: ld_iop.c,v 1.37 2017/02/27 21:32:33 jdolecek Exp $ */ /*- * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ld_iop.c,v 1.36 2016/09/16 15:20:50 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ld_iop.c,v 1.37 2017/02/27 21:32:33 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -73,7 +73,8 @@ static void ld_iop_adjqparam(device_t, int); static void ld_iop_attach(device_t, device_t, void *); static int ld_iop_detach(device_t, int); static int ld_iop_dump(struct ld_softc *, void *, int, int); -static int ld_iop_flush(struct ld_softc *, int); +static int ld_iop_flush(struct ld_softc *, bool); +static int ld_iop_ioctl(struct ld_softc *, u_long, void *, int32_t, bool); static void ld_iop_intr(device_t, struct iop_msg *, void *); static void ld_iop_intr_event(device_t, struct iop_msg *, void *); static int ld_iop_match(device_t, cfdata_t, void *); @@ -168,7 +169,7 @@ ld_iop_attach(device_t parent, device_t self, void *aux) ld->sc_maxxfer = IOP_MAX_XFER; ld->sc_dump = ld_iop_dump; - ld->sc_flush = ld_iop_flush; + ld->sc_ioctl = ld_iop_ioctl; ld->sc_start = ld_iop_start; /* Say what the device is. */ @@ -437,7 +438,7 @@ ld_iop_dump(struct ld_softc *ld, void *data, int blkno, int blkcnt) } static int -ld_iop_flush(struct ld_softc *ld, int flags) +ld_iop_flush(struct ld_softc *ld, bool poll) { struct iop_msg *im; struct iop_softc *iop; @@ -461,7 +462,25 @@ ld_iop_flush(struct ld_softc *ld, int flags) return (rv); } -void +static int +ld_iop_ioctl(struct ld_softc *ld, u_long cmd, void *addr, int32_t flag, bool poll) +{ + int error; + + switch (cmd) { + case DIOCCACHESYNC: + error = ld_iop_flush(ld, poll); + break; + + default: + error = EPASSTHROUGH; + break; + } + + return error; +} + +static void ld_iop_intr(device_t dv, struct iop_msg *im, void *reply) { struct i2o_rbs_reply *rb; diff --git a/sys/dev/ic/ld_icp.c b/sys/dev/ic/ld_icp.c index ed3e688e76c..4ef3359cd1d 100644 --- a/sys/dev/ic/ld_icp.c +++ b/sys/dev/ic/ld_icp.c @@ -1,4 +1,4 @@ -/* $NetBSD: ld_icp.c,v 1.30 2017/02/26 23:06:36 jdolecek Exp $ */ +/* $NetBSD: ld_icp.c,v 1.31 2017/02/27 21:32:33 jdolecek Exp $ */ /*- * Copyright (c) 2002 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ld_icp.c,v 1.30 2017/02/26 23:06:36 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ld_icp.c,v 1.31 2017/02/27 21:32:33 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -65,7 +65,8 @@ static int ld_icp_detach(device_t, int); static int ld_icp_dobio(struct ld_icp_softc *, void *, int, int, int, struct buf *); static int ld_icp_dump(struct ld_softc *, void *, int, int); -static int ld_icp_flush(struct ld_softc *, int); +static int ld_icp_flush(struct ld_softc *, bool); +static int ld_icp_ioctl(struct ld_softc *, u_long, void *, int32_t, bool); static void ld_icp_intr(struct icp_ccb *); static int ld_icp_match(device_t, cfdata_t, void *); static int ld_icp_start(struct ld_softc *, struct buf *); @@ -110,7 +111,7 @@ ld_icp_attach(device_t parent, device_t self, void *aux) ld->sc_secsize = ICP_SECTOR_SIZE; ld->sc_start = ld_icp_start; ld->sc_dump = ld_icp_dump; - ld->sc_flush = ld_icp_flush; + ld->sc_ioctl = ld_icp_ioctl; ld->sc_secperunit = cd->cd_size; ld->sc_flags = LDF_ENABLED; ld->sc_maxqueuecnt = icp->icp_openings; @@ -254,8 +255,9 @@ ld_icp_dump(struct ld_softc *ld, void *data, int blkno, int blkcnt) blkcnt * ld->sc_secsize, blkno, 1, NULL)); } +/* ARGSUSED */ static int -ld_icp_flush(struct ld_softc *ld, int flags) +ld_icp_flush(struct ld_softc *ld, bool poll) { struct ld_icp_softc *sc; struct icp_softc *icp; @@ -285,6 +287,24 @@ ld_icp_flush(struct ld_softc *ld, int flags) return (rv); } +static int +ld_icp_ioctl(struct ld_softc *ld, u_long cmd, void *addr, int32_t flag, bool poll) +{ + int error; + + switch (cmd) { + case DIOCCACHESYNC: + error = ld_icp_flush(ld, poll); + break; + + default: + error = EPASSTHROUGH; + break; + } + + return error; +} + static void ld_icp_intr(struct icp_ccb *ic) { diff --git a/sys/dev/ic/ld_nvme.c b/sys/dev/ic/ld_nvme.c index fee77eb3af2..a0f26afc3cc 100644 --- a/sys/dev/ic/ld_nvme.c +++ b/sys/dev/ic/ld_nvme.c @@ -1,4 +1,4 @@ -/* $NetBSD: ld_nvme.c,v 1.10 2016/11/01 14:39:38 jdolecek Exp $ */ +/* $NetBSD: ld_nvme.c,v 1.11 2017/02/27 21:32:33 jdolecek Exp $ */ /*- * Copyright (C) 2016 NONAKA Kimihiro <nonaka@netbsd.org> @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ld_nvme.c,v 1.10 2016/11/01 14:39:38 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ld_nvme.c,v 1.11 2017/02/27 21:32:33 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -60,7 +60,8 @@ CFATTACH_DECL_NEW(ld_nvme, sizeof(struct ld_nvme_softc), static int ld_nvme_start(struct ld_softc *, struct buf *); static int ld_nvme_dump(struct ld_softc *, void *, int, int); -static int ld_nvme_flush(struct ld_softc *, int); +static int ld_nvme_flush(struct ld_softc *, bool); +static int ld_nvme_ioctl(struct ld_softc *, u_long, void *, int32_t, bool); static void ld_nvme_biodone(void *, struct buf *, uint16_t); static void ld_nvme_syncdone(void *, struct buf *, uint16_t); @@ -112,7 +113,7 @@ ld_nvme_attach(device_t parent, device_t self, void *aux) ld->sc_maxqueuecnt = naa->naa_qentries; ld->sc_start = ld_nvme_start; ld->sc_dump = ld_nvme_dump; - ld->sc_flush = ld_nvme_flush; + ld->sc_ioctl = ld_nvme_ioctl; ld->sc_flags = LDF_ENABLED; ldattach(ld, "fcfs"); } @@ -180,16 +181,34 @@ ld_nvme_biodone(void *xc, struct buf *bp, uint16_t cmd_status) } static int -ld_nvme_flush(struct ld_softc *ld, int flags) +ld_nvme_flush(struct ld_softc *ld, bool poll) { struct ld_nvme_softc *sc = device_private(ld->sc_dv); - /* wait for the sync to finish */ return nvme_ns_sync(sc->sc_nvme, sc->sc_nsid, sc, - (flags & LDFL_POLL) ? NVME_NS_CTX_F_POLL : 0, + poll ? NVME_NS_CTX_F_POLL : 0, ld_nvme_syncdone); } +static int +ld_nvme_ioctl(struct ld_softc *ld, u_long cmd, void *addr, int32_t flag, bool poll) +{ + int error; + struct ld_nvme_softc *sc = device_private(ld->sc_dv); + + switch (cmd) { + case DIOCCACHESYNC: + error = ld_nvme_flush(ld, poll); + break; + + default: + error = EPASSTHROUGH; + break; + } + + return error; +} + static void ld_nvme_syncdone(void *xc, struct buf *bp, uint16_t cmd_status) { diff --git a/sys/dev/ld.c b/sys/dev/ld.c index f026db387ce..d0669004d20 100644 --- a/sys/dev/ld.c +++ b/sys/dev/ld.c @@ -1,4 +1,4 @@ -/* $NetBSD: ld.c,v 1.99 2016/11/26 12:32:03 mlelstv Exp $ */ +/* $NetBSD: ld.c,v 1.100 2017/02/27 21:32:33 jdolecek Exp $ */ /*- * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ld.c,v 1.99 2016/11/26 12:32:03 mlelstv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ld.c,v 1.100 2017/02/27 21:32:33 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -70,6 +70,7 @@ static void ld_set_geometry(struct ld_softc *); static void ld_config_interrupts (device_t); static int ld_lastclose(device_t); static int ld_discard(device_t, off_t, off_t); +static int ld_flush(device_t, bool); extern struct cfdriver ld_cd; @@ -247,15 +248,12 @@ ldenddetach(struct ld_softc *sc) pmf_device_deregister(dksc->sc_dev); /* - * XXX We can't really flush the cache here, beceause the + * XXX We can't really flush the cache here, because the * XXX device may already be non-existent from the controller's * XXX perspective. */ #if 0 - /* Flush the device's cache. */ - if (sc->sc_flush != NULL) - if ((*sc->sc_flush)(sc, 0) != 0) - device_printf(dksc->sc_dev, "unable to flush cache\n"); + ld_flush(dksc->sc_dev, false); #endif cv_destroy(&sc->sc_drain); mutex_destroy(&sc->sc_mutex); @@ -272,14 +270,8 @@ ld_suspend(device_t dev, const pmf_qual_t *qual) static bool ld_shutdown(device_t dev, int flags) { - struct ld_softc *sc = device_private(dev); - struct dk_softc *dksc = &sc->sc_dksc; - - if ((flags & RB_NOSYNC) == 0 && sc->sc_flush != NULL - && (*sc->sc_flush)(sc, LDFL_POLL) != 0) { - device_printf(dksc->sc_dev, "unable to flush cache\n"); + if ((flags & RB_NOSYNC) == 0 && ld_flush(dev, true) != 0) return false; - } return true; } @@ -303,10 +295,7 @@ ldopen(dev_t dev, int flags, int fmt, struct lwp *l) static int ld_lastclose(device_t self) { - struct ld_softc *sc = device_private(self); - - if (sc->sc_flush != NULL && (*sc->sc_flush)(sc, 0) != 0) - device_printf(self, "unable to flush cache\n"); + ld_flush(self, false); return 0; } @@ -356,6 +345,10 @@ ldioctl(dev_t dev, u_long cmd, void *addr, int32_t flag, struct lwp *l) error = 0; + /* + * Some common checks so that individual attachments wouldn't need + * to duplicate them. + */ switch (cmd) { case DIOCCACHESYNC: /* @@ -364,18 +357,40 @@ ldioctl(dev_t dev, u_long cmd, void *addr, int32_t flag, struct lwp *l) */ if ((flag & FWRITE) == 0) error = EBADF; - else if (sc->sc_flush) - error = (*sc->sc_flush)(sc, 0); else - error = 0; /* XXX Error out instead? */ + error = 0; break; + } - default: - error = dk_ioctl(dksc, dev, cmd, addr, flag, l); - break; + if (error != 0) + return (error); + + if (sc->sc_ioctl) { + error = (*sc->sc_ioctl)(sc, cmd, addr, flag, 0); + if (error != EPASSTHROUGH) + return (error); } - return (error); + /* something not handled by the attachment */ + return dk_ioctl(dksc, dev, cmd, addr, flag, l); +} + +/* + * Flush the device's cache. + */ +static int +ld_flush(device_t self, bool poll) +{ + int error = 0; + struct ld_softc *sc = device_private(self); + + if (sc->sc_ioctl) { + error = (*sc->sc_ioctl)(sc, DIOCCACHESYNC, NULL, 0, poll); + if (error != 0) + device_printf(self, "unable to flush cache\n"); + } + + return error; } static void diff --git a/sys/dev/ldvar.h b/sys/dev/ldvar.h index 0bec99ecdc1..37625e88fef 100644 --- a/sys/dev/ldvar.h +++ b/sys/dev/ldvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: ldvar.h,v 1.28 2016/09/16 15:20:50 jdolecek Exp $ */ +/* $NetBSD: ldvar.h,v 1.29 2017/02/27 21:32:33 jdolecek Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -59,7 +59,7 @@ struct ld_softc { int sc_maxqueuecnt; /* maximum h/w queue depth */ int (*sc_dump)(struct ld_softc *, void *, int, int); - int (*sc_flush)(struct ld_softc *, int); + int (*sc_ioctl)(struct ld_softc *, u_long, void *, int32_t, bool); int (*sc_start)(struct ld_softc *, struct buf *); int (*sc_discard)(struct ld_softc *, off_t, off_t); }; @@ -68,9 +68,6 @@ struct ld_softc { #define LDF_ENABLED 0x001 /* device enabled */ #define LDF_DRAIN 0x020 /* maxqueuecnt has changed; drain */ -/* sc_flush() flags */ -#define LDFL_POLL 0x001 /* poll for completion */ - int ldadjqparam(struct ld_softc *, int); void ldattach(struct ld_softc *, const char *); int ldbegindetach(struct ld_softc *, int); diff --git a/sys/dev/pci/ld_twa.c b/sys/dev/pci/ld_twa.c index 4a8de777317..f3b44c4d433 100644 --- a/sys/dev/pci/ld_twa.c +++ b/sys/dev/pci/ld_twa.c @@ -1,5 +1,5 @@ /* $wasabi: ld_twa.c,v 1.9 2006/02/14 18:44:37 jordanr Exp $ */ -/* $NetBSD: ld_twa.c,v 1.19 2016/09/27 03:33:32 pgoyette Exp $ */ +/* $NetBSD: ld_twa.c,v 1.20 2017/02/27 21:32:33 jdolecek Exp $ */ /*- * Copyright (c) 2000, 2001, 2002, 2003, 2004 The NetBSD Foundation, Inc. @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ld_twa.c,v 1.19 2016/09/27 03:33:32 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ld_twa.c,v 1.20 2017/02/27 21:32:33 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -76,7 +76,8 @@ static int ld_twa_detach(device_t, int); static int ld_twa_dobio(struct ld_twa_softc *, void *, size_t, daddr_t, struct buf *); static int ld_twa_dump(struct ld_softc *, void *, int, int); -static int ld_twa_flush(struct ld_softc *, int); +static int ld_twa_flush(struct ld_softc *, bool); +static int ld_twa_ioctl(struct ld_softc *, u_long, void *, int32_t, bool); static void ld_twa_handler(struct twa_request *); static int ld_twa_match(device_t, cfdata_t, void *); static int ld_twa_start(struct ld_softc *, struct buf *); @@ -120,7 +121,7 @@ ld_twa_attach(device_t parent, device_t self, void *aux) ld->sc_maxqueuecnt = twa->sc_units[sc->sc_hwunit].td_openings; ld->sc_start = ld_twa_start; ld->sc_dump = ld_twa_dump; - ld->sc_flush = ld_twa_flush; + ld->sc_ioctl = ld_twa_ioctl; ldattach(ld, BUFQ_DISK_DEFAULT_STRAT); } @@ -235,7 +236,7 @@ ld_twa_dump(struct ld_softc *ld, void *data, int blkno, int blkcnt) static int -ld_twa_flush(struct ld_softc *ld, int flags) +ld_twa_flush(struct ld_softc *ld, bool poll) { int s, rv = 0; struct twa_request *tr; @@ -276,6 +277,24 @@ ld_twa_flush(struct ld_softc *ld, int flags) return (rv); } +static int +ld_twa_ioctl(struct ld_softc *ld, u_long cmd, void *addr, int32_t flag, bool poll) +{ + int error; + + switch (cmd) { + case DIOCCACHESYNC: + error = ld_twa_flush(ld, poll); + break; + + default: + error = EPASSTHROUGH; + break; + } + + return error; +} + static void ld_twa_adjqparam(device_t self, int openings) { diff --git a/sys/dev/pci/ld_twe.c b/sys/dev/pci/ld_twe.c index 9c13634cb82..dc4e0f3e8f1 100644 --- a/sys/dev/pci/ld_twe.c +++ b/sys/dev/pci/ld_twe.c @@ -1,4 +1,4 @@ -/* $NetBSD: ld_twe.c,v 1.39 2016/09/27 03:33:32 pgoyette Exp $ */ +/* $NetBSD: ld_twe.c,v 1.40 2017/02/27 21:32:33 jdolecek Exp $ */ /*- * Copyright (c) 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ld_twe.c,v 1.39 2016/09/27 03:33:32 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ld_twe.c,v 1.40 2017/02/27 21:32:33 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -66,7 +66,8 @@ static int ld_twe_detach(device_t, int); static int ld_twe_dobio(struct ld_twe_softc *, void *, int, int, int, struct buf *); static int ld_twe_dump(struct ld_softc *, void *, int, int); -static int ld_twe_flush(struct ld_softc *, int); +static int ld_twe_flush(struct ld_softc *, bool); +static int ld_twe_ioctl(struct ld_softc *, u_long, void *, int32_t, bool); static void ld_twe_handler(struct twe_ccb *, int); static int ld_twe_match(device_t, cfdata_t, void *); static int ld_twe_start(struct ld_softc *, struct buf *); @@ -112,7 +113,7 @@ ld_twe_attach(device_t parent, device_t self, void *aux) ld->sc_maxqueuecnt = twe->sc_openings; ld->sc_start = ld_twe_start; ld->sc_dump = ld_twe_dump; - ld->sc_flush = ld_twe_flush; + ld->sc_ioctl = ld_twe_ioctl; typestr = twe_describe_code(twe_table_unittype, td->td_type); if (typestr == NULL) { @@ -266,7 +267,7 @@ ld_twe_dump(struct ld_softc *ld, void *data, int blkno, int blkcnt) } static int -ld_twe_flush(struct ld_softc *ld, int flags) +ld_twe_flush(struct ld_softc *ld, bool poll) { struct ld_twe_softc *sc = (void *) ld; struct twe_softc *twe = device_private(device_parent(ld->sc_dv)); @@ -286,7 +287,7 @@ ld_twe_flush(struct ld_softc *ld, int flags) tc->tc_unit = sc->sc_hwunit; tc->tc_count = 0; - if (flags & LDFL_POLL) { + if (poll) { /* * Polled commands must not sit on the software queue. Wait * up to 2 seconds for the command to complete. @@ -315,6 +316,24 @@ ld_twe_flush(struct ld_softc *ld, int flags) return (rv); } +static int +ld_twe_ioctl(struct ld_softc *ld, u_long cmd, void *addr, int32_t flag, bool poll) +{ + int error; + + switch (cmd) { + case DIOCCACHESYNC: + error = ld_twe_flush(ld, poll); + break; + + default: + error = EPASSTHROUGH; + break; + } + + return error; +} + static void ld_twe_adjqparam(device_t self, int openings) { diff --git a/sys/dev/pci/ld_virtio.c b/sys/dev/pci/ld_virtio.c index 7bcfd433181..fa33cdec19f 100644 --- a/sys/dev/pci/ld_virtio.c +++ b/sys/dev/pci/ld_virtio.c @@ -1,4 +1,4 @@ -/* $NetBSD: ld_virtio.c,v 1.13 2016/11/30 01:36:38 christos Exp $ */ +/* $NetBSD: ld_virtio.c,v 1.14 2017/02/27 21:32:33 jdolecek Exp $ */ /* * Copyright (c) 2010 Minoura Makoto. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ld_virtio.c,v 1.13 2016/11/30 01:36:38 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ld_virtio.c,v 1.14 2017/02/27 21:32:33 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -350,7 +350,6 @@ ld_virtio_attach(device_t parent, device_t self, void *aux) goto err; ld->sc_dump = ld_virtio_dump; - ld->sc_flush = NULL; ld->sc_start = ld_virtio_start; ld->sc_flags = LDF_ENABLED; |
