Source-Changes-HG archive

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

[src/thorpej-i2c-spi-conf]: src/sys/dev/i2c - Set D_MCLOSE in the iic_cdevsw ...



details:   https://anonhg.NetBSD.org/src/rev/d73e3ff9833d
branches:  thorpej-i2c-spi-conf
changeset: 378786:d73e3ff9833d
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Sun May 16 21:03:38 2021 +0000

description:
- Set D_MCLOSE in the iic_cdevsw so that we get a d_close call for
  each close so that the module ref counting works properly.
- Rearrange things a little to avoid holding the iic_mtx a long as
  previously done.

diffstat:

 sys/dev/i2c/i2c.c |  56 ++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 41 insertions(+), 15 deletions(-)

diffs (134 lines):

diff -r 142620132525 -r d73e3ff9833d sys/dev/i2c/i2c.c
--- a/sys/dev/i2c/i2c.c Sun May 16 15:40:20 2021 +0000
+++ b/sys/dev/i2c/i2c.c Sun May 16 21:03:38 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: i2c.c,v 1.78.2.3 2021/05/16 04:40:08 thorpej Exp $     */
+/*     $NetBSD: i2c.c,v 1.78.2.4 2021/05/16 21:03:38 thorpej Exp $     */
 
 /*-
  * Copyright (c) 2021 The NetBSD Foundation, Inc.
@@ -69,7 +69,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: i2c.c,v 1.78.2.3 2021/05/16 04:40:08 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: i2c.c,v 1.78.2.4 2021/05/16 21:03:38 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -115,13 +115,6 @@ 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,
@@ -134,11 +127,16 @@ const struct cdevsw iic_cdevsw = {
        .d_mmap = nommap,
        .d_kqfilter = nokqfilter,
        .d_discard = nodiscard,
-       .d_flag = D_OTHER
+       .d_flag = D_OTHER | D_MCLOSE,
 };
 
 static void    iic_smbus_intr_thread(void *);
 
+static kmutex_t iic_mtx;
+static int iic_refcnt;
+static bool iic_unloading;
+static ONCE_DECL(iic_once);
+
 static struct i2c_device_link *
 iic_devslot_lookup(struct iic_softc *sc, i2c_addr_t addr)
 {
@@ -928,22 +926,43 @@ iic_use_direct_match(const struct i2c_at
 static int
 iic_open(dev_t dev, int flag, int fmt, lwp_t *l)
 {
-       struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev));
+       struct iic_softc *sc;
 
        mutex_enter(&iic_mtx);
-       if (sc == NULL) {
+
+       if (iic_unloading) {
                mutex_exit(&iic_mtx);
                return ENXIO;
        }
+
+       /* Hold a refrence while we look up the softc. */
+       if (iic_refcnt == INT_MAX) {
+               mutex_exit(&iic_mtx);
+               return EBUSY;
+       }
        iic_refcnt++;
+
        mutex_exit(&iic_mtx);
 
+       sc = device_lookup_private(&iic_cd, minor(dev));
+
+       if (sc == NULL) {
+               mutex_enter(&iic_mtx);
+               iic_refcnt--;
+               mutex_exit(&iic_mtx);
+               return ENXIO;
+       }
+
        return 0;
 }
 
 static int
 iic_close(dev_t dev, int flag, int fmt, lwp_t *l)
 {
+       struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev));;
+
+       KASSERT(iic_refcnt != 0);
+       KASSERT(sc != NULL);
 
        mutex_enter(&iic_mtx);
        iic_refcnt--;
@@ -1037,7 +1056,7 @@ MODULE(MODULE_CLASS_DRIVER, iic, "i2cexe
 #include "ioconf.c"
 #endif
 
-int
+static int
 iic_init(void)
 {
 
@@ -1084,19 +1103,26 @@ iic_modcmd(modcmd_t cmd, void *opaque)
                        mutex_exit(&iic_mtx);
                        return EBUSY;
                }
+               iic_unloading = true;
+               mutex_exit(&iic_mtx);
 #ifdef _MODULE
                error = config_fini_component(cfdriver_ioconf_iic,
                    cfattach_ioconf_iic, cfdata_ioconf_iic);
                if (error != 0) {
+                       mutex_enter(&iic_mtx);
+                       iic_unloading = false;
                        mutex_exit(&iic_mtx);
                        break;
                }
                error = devsw_detach(NULL, &iic_cdevsw);
-               if (error != 0)
+               if (error != 0) {
                        config_init_component(cfdriver_ioconf_iic,
                            cfattach_ioconf_iic, cfdata_ioconf_iic);
+                       mutex_enter(&iic_mtx);
+                       iic_unloading = false;
+                       mutex_exit(&iic_mtx);
+               }
 #endif
-               mutex_exit(&iic_mtx);
                break;
        default:
                error = ENOTTY;



Home | Main Index | Thread Index | Old Index