Author: ian
Date: Mon Dec  9 19:00:39 2019
New Revision: 355565
URL: https://svnweb.freebsd.org/changeset/base/355565

Log:
  Switch gpioths(4) from using a callout to a taskqueue for periodic polling
  of the sensor hardware.  Part of the polling process involves signalling
  the chip then waiting 20 milliseconds.  This was being done with DELAY(),
  which is a pretty rude thing to do in a callout.  Now a taskqueue_thread
  task is scheduled to do the polling, and because sleeping is allowed in
  the task context, pause_sbt() replaces DELAY() for the 20ms wait.

Modified:
  head/sys/dev/gpio/gpioths.c

Modified: head/sys/dev/gpio/gpioths.c
==============================================================================
--- head/sys/dev/gpio/gpioths.c Mon Dec  9 17:58:22 2019        (r355564)
+++ head/sys/dev/gpio/gpioths.c Mon Dec  9 19:00:39 2019        (r355565)
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/errno.h>
 #include <sys/systm.h>
 #include <sys/sysctl.h>
+#include <sys/taskqueue.h>
 
 #include <dev/gpio/gpiobusvar.h>
 
@@ -90,7 +91,8 @@ struct gpioths_softc {
        int                      temp;
        int                      hum;
        int                      fails;
-       struct callout           callout;
+       struct timeout_task      task;
+       bool                     detaching;
 };
 
 static int
@@ -148,7 +150,7 @@ gpioths_dht_initread(struct gpioths_softc *sc)
         */
        gpio_pin_setflags(sc->pin, GPIO_PIN_OUTPUT);
        gpio_pin_set_active(sc->pin, false);
-       DELAY(GPIOTHS_DHT_STARTCYCLE);
+       pause_sbt("gpioths", ustosbt(GPIOTHS_DHT_STARTCYCLE), C_PREL(2), 0);
        gpio_pin_set_active(sc->pin, true);
        gpio_pin_setflags(sc->pin, GPIO_PIN_INPUT);
 }
@@ -285,14 +287,16 @@ error:
 }
 
 static void
-gpioths_poll(void *arg)
+gpioths_poll(void *arg, int pending __unused)
 {
        struct gpioths_softc    *sc;
 
        sc = (struct gpioths_softc *)arg;
 
        gpioths_dht_readbytes(sc);
-       callout_schedule(&sc->callout, GPIOTHS_POLLTIME * hz);
+       if (!sc->detaching)
+               taskqueue_enqueue_timeout_sbt(taskqueue_thread, &sc->task,
+                   GPIOTHS_POLLTIME * SBT_1S, 0, C_PREL(3));
 }
 
 static int
@@ -309,6 +313,8 @@ gpioths_attach(device_t dev)
 
        sc->dev = dev;
 
+       TIMEOUT_TASK_INIT(taskqueue_thread, &sc->task, 0, gpioths_poll, sc);
+
 #ifdef FDT
        /* Try to configure our pin from fdt data on fdt-based systems. */
        err = gpio_pin_get_by_ofw_idx(dev, ofw_bus_get_node(dev), PIN_IDX,
@@ -355,9 +361,11 @@ gpioths_attach(device_t dev)
 
        /* 
         * Do an initial read so we have correct values for reporting before
-        * registering the sysctls that can access those values.
+        * registering the sysctls that can access those values.  This also
+        * schedules the periodic polling the driver does every few seconds to
+        * update the sysctl variables.
         */
-       gpioths_dht_readbytes(sc);
+       gpioths_poll(sc, 0);
 
        sysctl_add_oid(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "temperature",     
                        \
            CTLFLAG_RD | CTLTYPE_INT | CTLFLAG_MPSAFE,
@@ -370,9 +378,6 @@ gpioths_attach(device_t dev)
            CTLFLAG_RD, &sc->fails, 0,
            "failures since last successful read");
 
-       callout_init(&sc->callout, 1);
-       callout_reset(&sc->callout, GPIOTHS_POLLTIME * hz, gpioths_poll, sc);
-
        return (0);
 }
 
@@ -383,7 +388,9 @@ gpioths_detach(device_t dev)
 
        sc = device_get_softc(dev);
        gpio_pin_release(sc->pin);
-       callout_drain(&sc->callout);
+       sc->detaching = true;
+       while (taskqueue_cancel_timeout(taskqueue_thread, &sc->task, NULL) != 0)
+               taskqueue_drain_timeout(taskqueue_thread, &sc->task);
 
        return (0);
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to