Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/i2c When loaded as a non-built-in module, make sure ...



details:   https://anonhg.NetBSD.org/src/rev/6f2ab5cb03dc
branches:  trunk
changeset: 812299:6f2ab5cb03dc
user:      pgoyette <pgoyette%NetBSD.org@localhost>
date:      Thu Dec 10 05:33:28 2015 +0000

description:
When loaded as a non-built-in module, make sure we attach the cdevsw.
Without this, the i2c bus works but userland programs (such as
i2cscan(8)) cannot open /dev/iic*.

While we're here, add a ref-count to make sure that the device doesn't
get detached while it is open.

diffstat:

 sys/dev/i2c/i2c.c |  68 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 63 insertions(+), 5 deletions(-)

diffs (137 lines):

diff -r 15ef510a0233 -r 6f2ab5cb03dc sys/dev/i2c/i2c.c
--- a/sys/dev/i2c/i2c.c Thu Dec 10 05:29:41 2015 +0000
+++ b/sys/dev/i2c/i2c.c Thu Dec 10 05:33:28 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: i2c.c,v 1.49 2015/04/13 22:26:20 pgoyette Exp $        */
+/*     $NetBSD: i2c.c,v 1.50 2015/12/10 05:33:28 pgoyette Exp $        */
 
 /*
  * Copyright (c) 2003 Wasabi Systems, Inc.
@@ -40,7 +40,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: i2c.c,v 1.49 2015/04/13 22:26:20 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: i2c.c,v 1.50 2015/12/10 05:33:28 pgoyette Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -54,6 +54,8 @@
 #include <sys/kernel.h>
 #include <sys/fcntl.h>
 #include <sys/module.h>
+#include <sys/once.h>
+#include <sys/mutex.h>
 
 #include <dev/i2c/i2cvar.h>
 
@@ -73,6 +75,13 @@
 static dev_type_close(iic_close);
 static dev_type_ioctl(iic_ioctl);
 
+int iic_init(void);
+
+kmutex_t iic_mtx;
+int iic_refcnt;
+
+ONCE_DECL(iic_once);
+
 const struct cdevsw iic_cdevsw = {
        .d_open = iic_open,
        .d_close = iic_close,
@@ -475,8 +484,13 @@
 {
        struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev));
 
-       if (sc == NULL)
+       mutex_enter(&iic_mtx);
+       if (sc == NULL) {
+               mutex_exit(&iic_mtx);
                return ENXIO;
+       }
+       iic_refcnt++;
+       mutex_exit(&iic_mtx);
 
        return 0;
 }
@@ -484,6 +498,11 @@
 static int
 iic_close(dev_t dev, int flag, int fmt, lwp_t *l)
 {
+
+       mutex_enter(&iic_mtx);
+       iic_refcnt--;
+       mutex_exit(&iic_mtx);
+
        return 0;
 }
 
@@ -579,27 +598,66 @@
 #include "ioconf.c"
 #endif
 
+int
+iic_init(void)
+{
+
+       mutex_init(&iic_mtx, MUTEX_DEFAULT, IPL_NONE);
+       iic_refcnt = 0;
+       return 0;
+}
+
 static int
 iic_modcmd(modcmd_t cmd, void *opaque)
 {
+#ifdef _MODULE
+       int bmajor, cmajor;
+#endif
        int error;
 
        error = 0;
        switch (cmd) {
        case MODULE_CMD_INIT:
+               RUN_ONCE(&iic_once, iic_init);
+
 #ifdef _MODULE
+               mutex_enter(&iic_mtx);
+               bmajor = cmajor = -1;
+               error = devsw_attach("iic", NULL, &bmajor,
+                   &iic_cdevsw, &cmajor);
+               if (error != 0) {
+                       mutex_exit(&iic_mtx);
+                       break;
+               }
                error = config_init_component(cfdriver_ioconf_iic,
                    cfattach_ioconf_iic, cfdata_ioconf_iic);
-               if (error)
+               if (error) {
                        aprint_error("%s: unable to init component\n",
                            iic_cd.cd_name);
+                       (void)devsw_detach(NULL, &iic_cdevsw);
+               }
+               mutex_exit(&iic_mtx);
 #endif
                break;
        case MODULE_CMD_FINI:
+               mutex_enter(&iic_mtx);
+               if (iic_refcnt != 0) {
+                       mutex_exit(&iic_mtx);
+                       return EBUSY;
+               }
 #ifdef _MODULE
-               config_fini_component(cfdriver_ioconf_iic,
+               error = config_fini_component(cfdriver_ioconf_iic,
                    cfattach_ioconf_iic, cfdata_ioconf_iic);
+               if (error != 0) {
+                       mutex_exit(&iic_mtx);
+                       break;
+               }
+               error = devsw_detach(NULL, &iic_cdevsw);
+               if (error != 0)
+                       config_init_component(cfdriver_ioconf_iic,
+                           cfattach_ioconf_iic, cfdata_ioconf_iic);
 #endif
+               mutex_exit(&iic_mtx);
                break;
        default:
                error = ENOTTY;



Home | Main Index | Thread Index | Old Index