git: d0d0d14abcab - stable/13 - linuxkpi: Rework detach function
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 21 Jun 2022 15:23:13 UTC
The branch stable/13 has been updated by manu: URL: https://cgit.FreeBSD.org/src/commit/?id=d0d0d14abcab6427ca747f198d2bcfecc0d142c2 commit d0d0d14abcab6427ca747f198d2bcfecc0d142c2 Author: Emmanuel Vadot <manu@FreeBSD.org> AuthorDate: 2022-05-13 11:56:36 +0000 Commit: Emmanuel Vadot <manu@FreeBSD.org> CommitDate: 2022-06-21 15:13:57 +0000 linuxkpi: Rework detach function We need to detach the matching i2c adapter so look for the right one. While here add some locks to protect multiple add/del at the same time. Fixes: 1961a14a47 ("linuxkpi: Add i2c support") Sponsored by: Beckhoff Automation GmbH & Co. KG (cherry picked from commit 25d21a845223ffad189fd2a7831ebf5e298b628a) --- sys/compat/linuxkpi/common/src/linux_i2c.c | 70 ++++++++++++++++++++++++---- sys/compat/linuxkpi/common/src/linux_i2cbb.c | 10 ++++ sys/compat/linuxkpi/common/src/lkpi_iic_if.m | 4 ++ 3 files changed, 76 insertions(+), 8 deletions(-) diff --git a/sys/compat/linuxkpi/common/src/linux_i2c.c b/sys/compat/linuxkpi/common/src/linux_i2c.c index ef264abd3fd4..eedd877f0e0f 100644 --- a/sys/compat/linuxkpi/common/src/linux_i2c.c +++ b/sys/compat/linuxkpi/common/src/linux_i2c.c @@ -53,6 +53,27 @@ struct lkpi_iic_softc { struct i2c_adapter *adapter; }; +static struct sx lkpi_sx_i2c; + +static void +lkpi_sysinit_i2c(void *arg __unused) +{ + + sx_init(&lkpi_sx_i2c, "lkpi-i2c"); +} + +static void +lkpi_sysuninit_i2c(void *arg __unused) +{ + + sx_destroy(&lkpi_sx_i2c); +} + +SYSINIT(lkpi_i2c, SI_SUB_DRIVERS, SI_ORDER_ANY, + lkpi_sysinit_i2c, NULL); +SYSUNINIT(lkpi_i2c, SI_SUB_DRIVERS, SI_ORDER_ANY, + lkpi_sysuninit_i2c, NULL); + static int lkpi_iic_probe(device_t dev) { @@ -98,6 +119,15 @@ lkpi_iic_add_adapter(device_t dev, struct i2c_adapter *adapter) return (0); } +static struct i2c_adapter * +lkpi_iic_get_adapter(device_t dev) +{ + struct lkpi_iic_softc *sc; + + sc = device_get_softc(dev); + return (sc->adapter); +} + static device_method_t lkpi_iic_methods[] = { /* device interface */ DEVMETHOD(device_probe, lkpi_iic_probe), @@ -113,6 +143,7 @@ static device_method_t lkpi_iic_methods[] = { /* lkpi_iic interface */ DEVMETHOD(lkpi_iic_add_adapter, lkpi_iic_add_adapter), + DEVMETHOD(lkpi_iic_get_adapter, lkpi_iic_get_adapter), DEVMETHOD_END }; @@ -179,12 +210,16 @@ lkpi_i2c_add_adapter(struct i2c_adapter *adapter) device_t lkpi_iic; int error; + if (adapter->name[0] == '\0') + return (-EINVAL); if (bootverbose) device_printf(adapter->dev.parent->bsddev, "Adding i2c adapter %s\n", adapter->name); + sx_xlock(&lkpi_sx_i2c); lkpi_iic = device_add_child(adapter->dev.parent->bsddev, "lkpi_iic", -1); if (lkpi_iic == NULL) { device_printf(adapter->dev.parent->bsddev, "Couldn't add lkpi_iic\n"); + sx_xunlock(&lkpi_sx_i2c); return (ENXIO); } @@ -192,9 +227,11 @@ lkpi_i2c_add_adapter(struct i2c_adapter *adapter) if (error) { device_printf(adapter->dev.parent->bsddev, "failed to attach child: error %d\n", error); + sx_xunlock(&lkpi_sx_i2c); return (ENXIO); } LKPI_IIC_ADD_ADAPTER(lkpi_iic, adapter); + sx_xunlock(&lkpi_sx_i2c); return (0); } @@ -202,18 +239,35 @@ int lkpi_i2c_del_adapter(struct i2c_adapter *adapter) { device_t child; + int unit, rv; + if (adapter == NULL) + return (-EINVAL); if (bootverbose) device_printf(adapter->dev.parent->bsddev, "Removing i2c adapter %s\n", adapter->name); + sx_xlock(&lkpi_sx_i2c); + unit = 0; + while ((child = device_find_child(adapter->dev.parent->bsddev, "lkpi_iic", unit++)) != NULL) { + + if (adapter == LKPI_IIC_GET_ADAPTER(child)) { + device_delete_child(adapter->dev.parent->bsddev, child); + rv = 0; + goto out; + } + } - child = device_find_child(adapter->dev.parent->bsddev, "lkpi_iic", -1); - if (child != NULL) - device_delete_child(adapter->dev.parent->bsddev, child); - - child = device_find_child(adapter->dev.parent->bsddev, "lkpi_iicbb", -1); - if (child != NULL) - device_delete_child(adapter->dev.parent->bsddev, child); + unit = 0; + while ((child = device_find_child(adapter->dev.parent->bsddev, "lkpi_iicbb", unit++)) != NULL) { - return (0); + if (adapter == LKPI_IIC_GET_ADAPTER(child)) { + device_delete_child(adapter->dev.parent->bsddev, child); + rv = 0; + goto out; + } + } + rv = -EINVAL; +out: + sx_xunlock(&lkpi_sx_i2c); + return (rv); } diff --git a/sys/compat/linuxkpi/common/src/linux_i2cbb.c b/sys/compat/linuxkpi/common/src/linux_i2cbb.c index e6f851bee103..f7321f060fa0 100644 --- a/sys/compat/linuxkpi/common/src/linux_i2cbb.c +++ b/sys/compat/linuxkpi/common/src/linux_i2cbb.c @@ -100,6 +100,15 @@ lkpi_iicbb_add_adapter(device_t dev, struct i2c_adapter *adapter) return (0); } +static struct i2c_adapter * +lkpi_iicbb_get_adapter(device_t dev) +{ + struct lkpi_iicbb_softc *sc; + + sc = device_get_softc(dev); + return (sc->adapter); +} + static device_method_t lkpi_iicbb_methods[] = { /* device interface */ DEVMETHOD(device_probe, lkpi_iicbb_probe), @@ -117,6 +126,7 @@ static device_method_t lkpi_iicbb_methods[] = { /* lkpi_iicbb interface */ DEVMETHOD(lkpi_iic_add_adapter, lkpi_iicbb_add_adapter), + DEVMETHOD(lkpi_iic_get_adapter, lkpi_iicbb_get_adapter), DEVMETHOD_END }; diff --git a/sys/compat/linuxkpi/common/src/lkpi_iic_if.m b/sys/compat/linuxkpi/common/src/lkpi_iic_if.m index 2379182c409b..c1b4abd79084 100644 --- a/sys/compat/linuxkpi/common/src/lkpi_iic_if.m +++ b/sys/compat/linuxkpi/common/src/lkpi_iic_if.m @@ -35,3 +35,7 @@ METHOD int add_adapter { device_t dev; struct i2c_adapter *adapter; }; + +METHOD struct i2c_adapter * get_adapter { + device_t dev; +};