Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/i2c convert device polling from callout to kthread.



details:   https://anonhg.NetBSD.org/src/rev/a88fb8eadfa4
branches:  trunk
changeset: 346246:a88fb8eadfa4
user:      kardel <kardel%NetBSD.org@localhost>
date:      Sun Jul 03 12:26:55 2016 +0000

description:
convert device polling from callout to kthread.
Solves:
        - hung initialization on A20 (bananapi)
        - allows iic_exec() implementations to use condvars

diffstat:

 sys/dev/i2c/hytp14.c    |  96 ++++++++++++++++++++++++++++++++++++++++--------
 sys/dev/i2c/hytp14var.h |  16 ++++++--
 2 files changed, 91 insertions(+), 21 deletions(-)

diffs (208 lines):

diff -r ff4c2d1921b2 -r a88fb8eadfa4 sys/dev/i2c/hytp14.c
--- a/sys/dev/i2c/hytp14.c      Sun Jul 03 11:55:27 2016 +0000
+++ b/sys/dev/i2c/hytp14.c      Sun Jul 03 12:26:55 2016 +0000
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * Copyright (c) 2014,2016 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -37,7 +37,7 @@
  */ 
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hytp14.c,v 1.6 2015/09/18 17:21:43 phx Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hytp14.c,v 1.7 2016/07/03 12:26:55 kardel Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -45,6 +45,9 @@
 #include <sys/device.h>
 #include <sys/module.h>
 #include <sys/sysctl.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/kthread.h>
 
 #include <dev/sysmon/sysmonvar.h>
 #include <dev/i2c/i2cvar.h>
@@ -59,9 +62,11 @@
 static void hytp14_refresh(struct sysmon_envsys *, envsys_data_t *);
 static void hytp14_refresh_humidity(struct hytp14_sc *, envsys_data_t *);
 static void hytp14_refresh_temp(struct hytp14_sc *, envsys_data_t *);
+static void hytp14_thread(void *);
 static int sysctl_hytp14_interval(SYSCTLFN_ARGS);
 
-/*#define HYT_DEBUG 3*/
+/* #define HYT_DEBUG 3 */
+
 #ifdef HYT_DEBUG
 volatile int hythygtemp_debug = HYT_DEBUG;
 
@@ -115,7 +120,7 @@
        const struct sysctlnode *rnode, *node;
        struct hytp14_sc *sc;
        struct i2c_attach_args *ia;
-       int i;
+       int i, rv;
 
        ia = aux;
        sc = device_private(self);
@@ -123,6 +128,12 @@
        sc->sc_dev = self;
        sc->sc_tag = ia->ia_tag;
        sc->sc_addr = ia->ia_addr;
+
+       mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE);
+       cv_init(&sc->sc_condvar, "hytcv");
+
+       sc->sc_state = HYTP14_THR_INIT;
+       
        sc->sc_valid = ENVSYS_SINVALID;
        sc->sc_numsensors = __arraycount(hytp14_sensors);
 
@@ -180,15 +191,18 @@
                    sysctl_hytp14_interval, 0, (void *)sc, 0,
                    CTL_HW, rnode->sysctl_num, CTL_CREATE, CTL_EOL);
 
-       aprint_normal(": HYT-221/271/939 humidity and temperature sensor\n");
 
-       /* set up callout for the default measurement interval */
+       /* set up the default measurement interval for worker thread */
        sc->sc_mrinterval = HYTP14_MR_INTERVAL;
-       callout_init(&sc->sc_mrcallout, 0);
-       callout_setfunc(&sc->sc_mrcallout, hytp14_measurement_request, sc);
 
-       /* issue initial measurement request */
-       hytp14_measurement_request(sc);
+       /* create worker kthread */
+       rv = kthread_create(PRI_NONE, KTHREAD_MUSTJOIN, NULL,
+                           hytp14_thread, sc, &sc->sc_thread,
+                           "%s", device_xname(sc->sc_dev));
+       if (rv)
+         aprint_error_dev(self, "unable to create intr thread\n");
+
+       aprint_normal(": HYT-221/271/939 humidity and temperature sensor\n");
 }
 
 static int
@@ -203,11 +217,62 @@
                sc->sc_sme = NULL;
        }
 
-       /* stop our measurement requests */
-       callout_stop(&sc->sc_mrcallout);
-       callout_destroy(&sc->sc_mrcallout);
+       /* stop measurement thread */
+       mutex_enter(&sc->sc_mutex);
+       sc->sc_state = HYTP14_THR_STOP;
+       cv_signal(&sc->sc_condvar);
+       mutex_exit(&sc->sc_mutex);
+
+       /* await thread completion */
+       kthread_join(sc->sc_thread);
+
+       /* cleanup */
+       cv_destroy(&sc->sc_condvar);
+       mutex_destroy(&sc->sc_mutex);
+       
+       return 0;
+}
+
+static void
+hytp14_thread(void *aux)
+{
+       struct hytp14_sc *sc = aux;
+       int rv;
+       
+       mutex_enter(&sc->sc_mutex);
 
-       return 0;
+       DPRINTF(2, ("%s(%s): thread start - state=%d\n",
+                   __func__, device_xname(sc->sc_dev),
+                   sc->sc_state));
+       
+       while (sc->sc_state != HYTP14_THR_STOP) {
+               sc->sc_state = HYTP14_THR_RUN;
+
+               DPRINTF(2, ("%s(%s): waiting %d seconds\n",
+                           __func__, device_xname(sc->sc_dev),
+                               sc->sc_mrinterval));
+               
+               rv = cv_timedwait(&sc->sc_condvar, &sc->sc_mutex, hz * sc->sc_mrinterval);
+
+               if (rv == EWOULDBLOCK) {
+                       /* timeout - run measurement */
+                       DPRINTF(2, ("%s(%s): timeout -> measurement\n",
+                                   __func__, device_xname(sc->sc_dev)));
+
+                       hytp14_measurement_request(sc);
+               } else {
+                       DPRINTF(2, ("%s(%s): condvar signalled - state=%d\n",
+                                   __func__, device_xname(sc->sc_dev),
+                                   sc->sc_state));
+               }
+       }
+       
+       mutex_exit(&sc->sc_mutex);
+
+       DPRINTF(2, ("%s(%s): thread exit\n",
+                   __func__, device_xname(sc->sc_dev)));
+
+       kthread_exit(0);
 }
 
 static void
@@ -267,9 +332,6 @@
                DPRINTF(2, ("%s: %s: failed acquire i2c bus - error %d\n",
                    device_xname(sc->sc_dev), __func__, error));
        }
-
-       /* schedule next measurement interval */
-       callout_schedule(&sc->sc_mrcallout, sc->sc_mrinterval * hz);
 }
 
 static int
diff -r ff4c2d1921b2 -r a88fb8eadfa4 sys/dev/i2c/hytp14var.h
--- a/sys/dev/i2c/hytp14var.h   Sun Jul 03 11:55:27 2016 +0000
+++ b/sys/dev/i2c/hytp14var.h   Sun Jul 03 12:26:55 2016 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: hytp14var.h,v 1.3 2015/09/09 17:16:20 phx Exp $ */
+/* $NetBSD: hytp14var.h,v 1.4 2016/07/03 12:26:55 kardel Exp $ */
 
 /*-
- * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * Copyright (c) 2014,2016 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -47,18 +47,26 @@
 /* the default measurement interval is 50 seconds */
 #define HYTP14_MR_INTERVAL     50
 
+#define HYTP14_THR_INIT                0
+#define HYTP14_THR_RUN         1
+#define HYTP14_THR_STOP                2
+
 struct hytp14_sc {
        device_t        sc_dev;
        i2c_tag_t       sc_tag;
        i2c_addr_t      sc_addr;
-
+       
+       kmutex_t        sc_mutex;
+       kcondvar_t      sc_condvar;
+       struct lwp     *sc_thread;  /* measurement poll thread */
+       int             sc_state;   /* thread communication */
+       
        int             sc_valid;   /* ENVSYS validity state for this sensor */
        uint8_t         sc_data[4]; /* current sensor data */
        uint8_t         sc_last[4]; /* last sensor data, before MR */
 
        int             sc_numsensors;
 
-       callout_t       sc_mrcallout;
        int32_t         sc_mrinterval;
 
        struct sysmon_envsys *sc_sme;



Home | Main Index | Thread Index | Old Index