The branch main has been updated by manu:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=25d21a845223ffad189fd2a7831ebf5e298b628a

commit 25d21a845223ffad189fd2a7831ebf5e298b628a
Author:     Emmanuel Vadot <m...@freebsd.org>
AuthorDate: 2022-05-13 11:56:36 +0000
Commit:     Emmanuel Vadot <m...@freebsd.org>
CommitDate: 2022-05-25 07:57:10 +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
---
 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 2b19aec8ad16..c2c4977eb9ba 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
 };
@@ -177,12 +208,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);
        }
 
@@ -190,9 +225,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);
 }
 
@@ -200,18 +237,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 47756a25db3f..c4bfdf32e562 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;
+};

Reply via email to