svn commit: r355565 - head/sys/dev/gpio
Ian Lepore
ian at FreeBSD.org
Mon Dec 9 19:00:39 UTC 2019
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);
}
More information about the svn-src-all
mailing list