Module Name:    src
Committed By:   kardel
Date:           Sun Jul  3 12:26:55 UTC 2016

Modified Files:
        src/sys/dev/i2c: hytp14.c hytp14var.h

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


To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/sys/dev/i2c/hytp14.c
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/i2c/hytp14var.h

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/hytp14.c
diff -u src/sys/dev/i2c/hytp14.c:1.6 src/sys/dev/i2c/hytp14.c:1.7
--- src/sys/dev/i2c/hytp14.c:1.6	Fri Sep 18 17:21:43 2015
+++ src/sys/dev/i2c/hytp14.c	Sun Jul  3 12:26:55 2016
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: hytp14.c,v 1
 #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 int hytp14_refresh_sensor(struct 
 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 @@ hytp14_attach(device_t parent, device_t 
 	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 @@ hytp14_attach(device_t parent, device_t 
 	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 @@ hytp14_attach(device_t parent, device_t 
 		    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,14 +217,65 @@ hytp14_detach(device_t self, int flags)
 		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);
+
+	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
 hytp14_measurement_request(void *aux)
 {
 	uint8_t buf[I2C_EXEC_MAX_BUFLEN];
@@ -267,9 +332,6 @@ hytp14_measurement_request(void *aux)
 		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

Index: src/sys/dev/i2c/hytp14var.h
diff -u src/sys/dev/i2c/hytp14var.h:1.3 src/sys/dev/i2c/hytp14var.h:1.4
--- src/sys/dev/i2c/hytp14var.h:1.3	Wed Sep  9 17:16:20 2015
+++ src/sys/dev/i2c/hytp14var.h	Sun Jul  3 12:26:55 2016
@@ -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;

Reply via email to