Module Name:    src
Committed By:   pgoyette
Date:           Thu Dec 10 05:33:28 UTC 2015

Modified Files:
        src/sys/dev/i2c: i2c.c

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.49 -r1.50 src/sys/dev/i2c/i2c.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/i2c/i2c.c
diff -u src/sys/dev/i2c/i2c.c:1.49 src/sys/dev/i2c/i2c.c:1.50
--- src/sys/dev/i2c/i2c.c:1.49	Mon Apr 13 22:26:20 2015
+++ src/sys/dev/i2c/i2c.c	Thu Dec 10 05:33:28 2015
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: i2c.c,v 1.49
 #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_open(iic_open);
 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 @@ iic_open(dev_t dev, int flag, int fmt, l
 {
 	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 @@ iic_open(dev_t dev, int flag, int fmt, l
 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 @@ MODULE(MODULE_CLASS_DRIVER, iic, "i2cexe
 #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;

Reply via email to