From 1e4042d44e3f334027a5223ef0c445673254c879 Mon Sep 17 00:00:00 2001 From: Ian Lepore Date: Wed, 13 Sep 2017 16:54:27 +0000 Subject: [PATCH] Defer attaching and probing iicbus and its children until interrupts are available, in i2c controller drivers that require interrupts for transfers. This is the result of auditing all 22 existing drivers that attach iicbus. These drivers were the only ones remaining that require interrupts and were not using config_intrhook to defer attachment. That has led, over the years, to various i2c slave device drivers needing to use config_intrhook themselves rather than performing bus transactions in their probe() and attach() methods, just in case they were attached too early. --- sys/arm/at91/at91_twi.c | 4 ++-- sys/arm/broadcom/bcm2835/bcm2835_bsc.c | 5 ++++- sys/arm/freescale/imx/imx_i2c.c | 3 ++- sys/arm/ti/ti_i2c.c | 9 ++------- sys/dev/glxiic/glxiic.c | 9 ++++----- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/sys/arm/at91/at91_twi.c b/sys/arm/at91/at91_twi.c index 8549406c57c5..a0926800356c 100644 --- a/sys/arm/at91/at91_twi.c +++ b/sys/arm/at91/at91_twi.c @@ -160,8 +160,8 @@ at91_twi_attach(device_t dev) if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL) device_printf(dev, "could not allocate iicbus instance\n"); - /* probe and attach the iicbus */ - bus_generic_attach(dev); + /* Probe and attach the iicbus when interrupts are available. */ + config_intrhook_oneshot((ich_func_t)bus_generic_attach, dev); out: if (err) at91_twi_deactivate(dev); diff --git a/sys/arm/broadcom/bcm2835/bcm2835_bsc.c b/sys/arm/broadcom/bcm2835/bcm2835_bsc.c index e149d5d0b2db..8c21aad0ec04 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_bsc.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_bsc.c @@ -309,7 +309,10 @@ bcm_bsc_attach(device_t dev) return (ENXIO); } - return (bus_generic_attach(dev)); + /* Probe and attach the iicbus when interrupts are available. */ + config_intrhook_oneshot((ich_func_t)bus_generic_attach, dev); + + return (0); } static int diff --git a/sys/arm/freescale/imx/imx_i2c.c b/sys/arm/freescale/imx/imx_i2c.c index b58684f165e6..3b6d4aadb227 100644 --- a/sys/arm/freescale/imx/imx_i2c.c +++ b/sys/arm/freescale/imx/imx_i2c.c @@ -443,7 +443,8 @@ i2c_attach(device_t dev) /* We don't do a hardware reset here because iicbus_attach() does it. */ - bus_generic_attach(dev); + /* Probe and attach the iicbus when interrupts are available. */ + config_intrhook_oneshot((ich_func_t)bus_generic_attach, dev); return (0); } diff --git a/sys/arm/ti/ti_i2c.c b/sys/arm/ti/ti_i2c.c index 55336ffcb650..a8ccadba0dbd 100644 --- a/sys/arm/ti/ti_i2c.c +++ b/sys/arm/ti/ti_i2c.c @@ -37,11 +37,6 @@ * incorporate that sometime in the future. The idea being that for transaction * larger than a certain size the DMA engine is used, for anything less the * normal interrupt/fifo driven option is used. - * - * - * WARNING: This driver uses mtx_sleep and interrupts to perform transactions, - * which means you can't do a transaction during startup before the interrupts - * have been enabled. Hint - the freebsd function config_intrhook_establish(). */ #include @@ -909,8 +904,8 @@ ti_i2c_attach(device_t dev) goto out; } - /* Probe and attach the iicbus */ - bus_generic_attach(dev); + /* Probe and attach the iicbus when interrupts are available. */ + config_intrhook_oneshot((ich_func_t)bus_generic_attach, dev); out: if (err) { diff --git a/sys/dev/glxiic/glxiic.c b/sys/dev/glxiic/glxiic.c index f119bea6071b..101f27b760e2 100644 --- a/sys/dev/glxiic/glxiic.c +++ b/sys/dev/glxiic/glxiic.c @@ -408,11 +408,10 @@ glxiic_attach(device_t dev) glxiic_gpio_enable(sc); glxiic_smb_enable(sc, IIC_FASTEST, 0); - error = bus_generic_attach(dev); - if (error != 0) { - device_printf(dev, "Could not probe and attach children\n"); - error = ENXIO; - } + /* Probe and attach the iicbus when interrupts are available. */ + config_intrhook_oneshot((ich_func_t)bus_generic_attach, dev); + error = 0; + out: if (error != 0) { callout_drain(&sc->callout);