From b832a7e5053cd29ec8d5421482ffd3b311e27092 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 13 Dec 2019 19:39:33 +0000 Subject: [PATCH] Create new wrapper function: bus_delayed_attach_children() Delay the attachment of children, when requested, until after interrutps are running. This is often needed to allow children to run transactions on i2c or spi busses. It's a common enough idiom that it will be useful to have its own wrapper. Reviewed by: ian Differential Revision: https://reviews.freebsd.org/D21465 --- share/man/man9/Makefile | 1 + share/man/man9/bus_delayed_attach_children.9 | 55 ++++++++++++++++++++ sys/arm/broadcom/bcm2835/bcm2835_bsc.c | 2 +- sys/arm/freescale/imx/imx_i2c.c | 3 +- sys/arm/freescale/imx/imx_spi.c | 4 +- sys/arm/mv/a37x0_spi.c | 2 +- sys/arm/mv/mv_spi.c | 4 +- sys/arm/ti/ti_i2c.c | 2 +- sys/dev/glxiic/glxiic.c | 3 +- sys/dev/ichsmb/ichsmb.c | 7 +-- sys/dev/ow/owc_gpiobus.c | 2 +- sys/kern/subr_bus.c | 16 ++++++ sys/sys/bus.h | 1 + 13 files changed, 83 insertions(+), 19 deletions(-) create mode 100644 share/man/man9/bus_delayed_attach_children.9 diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index 9a79aff4cc25..2981771836f8 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -34,6 +34,7 @@ MAN= accept_filter.9 \ BUS_CHILD_DELETED.9 \ BUS_CHILD_DETACHED.9 \ BUS_CONFIG_INTR.9 \ + bus_delayed_attach_children.9 \ BUS_DESCRIBE_INTR.9 \ bus_dma.9 \ bus_generic_attach.9 \ diff --git a/share/man/man9/bus_delayed_attach_children.9 b/share/man/man9/bus_delayed_attach_children.9 new file mode 100644 index 000000000000..724d90096537 --- /dev/null +++ b/share/man/man9/bus_delayed_attach_children.9 @@ -0,0 +1,55 @@ +.\" -*- nroff -*- +.\" +.\" Copyright (c) 2019 M. Warner Losh +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd August 29, 2019 +.Dt BUS_DELAYED_ATTACH_CHILDREN 9 +.Os +.Sh NAME +.Nm bus_delayed_attach_children +.Nd "request that the children be attached when interrupts are enabled" +.Sh SYNOPSIS +.In sys/param.h +.In sys/bus.h +.Pp +.Ft int +.Fn bus_delayed_attach_children "device_t dev" +.Sh DESCRIPTION +The +.Fn bus_delayed_attach_children +function requests that the children of this device +be attached when interrupts are running. +If interrupts are currently running, this happens immediately. +If interrupts aren't yet running, this happens after interrupts are enabled, but +before the system mounts root. +.Sh RETURN VALUES +A zero return value indicates success. +.Sh SEE ALSO +.Xr bus 9 , +.Xr device 9 , +.Xr driver 9 +.Sh AUTHORS +This manual page was written by +.An Warner Losh Aq Mt imp@FreeBSD.org . diff --git a/sys/arm/broadcom/bcm2835/bcm2835_bsc.c b/sys/arm/broadcom/bcm2835/bcm2835_bsc.c index 0c68a12a1f43..d4d246db03e8 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_bsc.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_bsc.c @@ -347,7 +347,7 @@ bcm_bsc_attach(device_t dev) } /* Probe and attach the iicbus when interrupts are available. */ - config_intrhook_oneshot((ich_func_t)bus_generic_attach, dev); + bus_delayed_attach_children(dev); return (0); } diff --git a/sys/arm/freescale/imx/imx_i2c.c b/sys/arm/freescale/imx/imx_i2c.c index 1d21f7964acb..1811d7a084ad 100644 --- a/sys/arm/freescale/imx/imx_i2c.c +++ b/sys/arm/freescale/imx/imx_i2c.c @@ -449,8 +449,7 @@ no_recovery: /* We don't do a hardware reset here because iicbus_attach() does it. */ /* Probe and attach the iicbus when interrupts are available. */ - config_intrhook_oneshot((ich_func_t)bus_generic_attach, dev); - return (0); + return (bus_delayed_attach_children(dev)); } static int diff --git a/sys/arm/freescale/imx/imx_spi.c b/sys/arm/freescale/imx/imx_spi.c index 21add56cef7f..6624955ff124 100644 --- a/sys/arm/freescale/imx/imx_spi.c +++ b/sys/arm/freescale/imx/imx_spi.c @@ -566,9 +566,7 @@ spi_attach(device_t dev) * their attach. We can't do IO until timers and interrupts are working. */ sc->spibus = device_add_child(dev, "spibus", -1); - config_intrhook_oneshot((ich_func_t)bus_generic_attach, dev); - - return (0); + return (bus_delayed_attach_children(dev)); } static int diff --git a/sys/arm/mv/a37x0_spi.c b/sys/arm/mv/a37x0_spi.c index 69a4ceeac080..6194232464ce 100644 --- a/sys/arm/mv/a37x0_spi.c +++ b/sys/arm/mv/a37x0_spi.c @@ -220,7 +220,7 @@ a37x0_spi_attach(device_t dev) device_add_child(dev, "spibus", -1); /* Probe and attach the spibus when interrupts are available. */ - config_intrhook_oneshot((ich_func_t)bus_generic_attach, dev); + bus_delayed_attach_children(dev); return (0); } diff --git a/sys/arm/mv/mv_spi.c b/sys/arm/mv/mv_spi.c index 1ad3b5749da5..95d7d21e85c3 100644 --- a/sys/arm/mv/mv_spi.c +++ b/sys/arm/mv/mv_spi.c @@ -174,9 +174,7 @@ mv_spi_attach(device_t dev) device_add_child(dev, "spibus", -1); /* Probe and attach the spibus when interrupts are available. */ - config_intrhook_oneshot((ich_func_t)bus_generic_attach, dev); - - return (0); + return (bus_delayed_attach_children(dev)); } static int diff --git a/sys/arm/ti/ti_i2c.c b/sys/arm/ti/ti_i2c.c index 8f1804493192..4a9313d6f501 100644 --- a/sys/arm/ti/ti_i2c.c +++ b/sys/arm/ti/ti_i2c.c @@ -905,7 +905,7 @@ ti_i2c_attach(device_t dev) } /* Probe and attach the iicbus when interrupts are available. */ - config_intrhook_oneshot((ich_func_t)bus_generic_attach, dev); + err = bus_delayed_attach_children(dev); out: if (err) { diff --git a/sys/dev/glxiic/glxiic.c b/sys/dev/glxiic/glxiic.c index d5f5f248f4af..e742812824df 100644 --- a/sys/dev/glxiic/glxiic.c +++ b/sys/dev/glxiic/glxiic.c @@ -411,8 +411,7 @@ glxiic_attach(device_t dev) glxiic_smb_enable(sc, IIC_FASTEST, 0); /* Probe and attach the iicbus when interrupts are available. */ - config_intrhook_oneshot((ich_func_t)bus_generic_attach, dev); - error = 0; + error = bus_delayed_attach_children(dev); out: if (error != 0) { diff --git a/sys/dev/ichsmb/ichsmb.c b/sys/dev/ichsmb/ichsmb.c index b69c40089024..5354d5ca94c6 100644 --- a/sys/dev/ichsmb/ichsmb.c +++ b/sys/dev/ichsmb/ichsmb.c @@ -131,11 +131,8 @@ ichsmb_attach(device_t dev) goto fail; } - /* Probe and attach the smbus when interrupts are available */ - config_intrhook_oneshot((ich_func_t)bus_generic_attach, dev); - - return (0); - + /* Attach children when interrupts are available */ + return (bus_delayed_attach_children(dev)); fail: mtx_destroy(&sc->mutex); return (error); diff --git a/sys/dev/ow/owc_gpiobus.c b/sys/dev/ow/owc_gpiobus.c index 621f7b1c6f09..d01d5e6968b8 100644 --- a/sys/dev/ow/owc_gpiobus.c +++ b/sys/dev/ow/owc_gpiobus.c @@ -131,7 +131,7 @@ owc_gpiobus_attach(device_t dev) free(kids, M_TEMP); if (nkid == 0) device_add_child(dev, "ow", -1); - config_intrhook_oneshot((ich_func_t)bus_generic_attach, dev); + bus_delayed_attach_children(dev); return (0); } diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c index f40a0194ee22..f36cc881f182 100644 --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -3752,6 +3752,22 @@ bus_generic_attach(device_t dev) return (0); } +/** + * @brief Helper function for delaying attaching children + * + * Many buses can't run transactions on the bus which children need to probe and + * attach until after interrupts and/or timers are running. This function + * delays their attach until interrupts and timers are enabled. + */ +int +bus_delayed_attach_children(device_t dev) +{ + /* Probe and attach the bus children when interrupts are available */ + config_intrhook_oneshot((ich_func_t)bus_generic_attach, dev); + + return (0); +} + /** * @brief Helper function for implementing DEVICE_DETACH() * diff --git a/sys/sys/bus.h b/sys/sys/bus.h index 508267754e41..a2d22af77277 100644 --- a/sys/sys/bus.h +++ b/sys/sys/bus.h @@ -567,6 +567,7 @@ int bus_child_present(device_t child); int bus_child_pnpinfo_str(device_t child, char *buf, size_t buflen); int bus_child_location_str(device_t child, char *buf, size_t buflen); void bus_enumerate_hinted_children(device_t bus); +int bus_delayed_attach_children(device_t bus); static __inline struct resource * bus_alloc_resource_any(device_t dev, int type, int *rid, u_int flags)