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;