summaryrefslogtreecommitdiff
path: root/sys/dev/usb
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2015-04-30 10:00:51 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2015-04-30 10:00:51 +0000
commitc6f4813deb2dc0e2342d8ff9d25174e2451e42b8 (patch)
tree2e36bf059e3bf4ab3baea6d17f0df3905c661c68 /sys/dev/usb
parentf0a73669441175de197b2cc9b92c56cf847868d4 (diff)
Instead of using a single flat array for all sensors, put all the
children of a sensor in a separate structure. Children sensors should only be probbed if their parent is active. This make the dependency tree explicit and will reduce the number of I/O. From David Higgs.
Diffstat (limited to 'sys/dev/usb')
-rw-r--r--sys/dev/usb/upd.c96
1 files changed, 62 insertions, 34 deletions
diff --git a/sys/dev/usb/upd.c b/sys/dev/usb/upd.c
index 428b2c28cc9..93b06e9e8d1 100644
--- a/sys/dev/usb/upd.c
+++ b/sys/dev/usb/upd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: upd.c,v 1.17 2015/04/27 09:14:45 mpi Exp $ */
+/* $OpenBSD: upd.c,v 1.18 2015/04/30 10:00:50 mpi Exp $ */
/*
* Copyright (c) 2014 Andre de Oliveira <andre@openbsd.org>
@@ -23,6 +23,7 @@
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/device.h>
+#include <sys/queue.h>
#include <sys/sensors.h>
#include <dev/usb/hid.h>
@@ -46,9 +47,11 @@ struct upd_usage_entry {
uint8_t usage_id;
enum sensor_type senstype;
char *usage_name; /* sensor string */
+ int nchildren;
+ struct upd_usage_entry *children;
};
-static struct upd_usage_entry upd_usage_table[] = {
+static struct upd_usage_entry upd_usage_batdep[] = {
{ HUP_BATTERY, HUB_REL_STATEOF_CHARGE,
SENSOR_PERCENT, "RelativeStateOfCharge" },
{ HUP_BATTERY, HUB_ABS_STATEOF_CHARGE,
@@ -61,25 +64,32 @@ static struct upd_usage_entry upd_usage_table[] = {
SENSOR_INDICATOR, "Charging" },
{ HUP_BATTERY, HUB_DISCHARGING,
SENSOR_INDICATOR, "Discharging" },
+ { HUP_BATTERY, HUB_ATRATE_TIMETOFULL,
+ SENSOR_TIMEDELTA, "AtRateTimeToFull" }
+};
+static struct upd_usage_entry upd_usage_roots[] = {
{ HUP_BATTERY, HUB_BATTERY_PRESENT,
- SENSOR_INDICATOR, "BatteryPresent" },
+ SENSOR_INDICATOR, "BatteryPresent",
+ nitems(upd_usage_batdep), upd_usage_batdep },
{ HUP_POWER, HUP_SHUTDOWN_IMMINENT,
SENSOR_INDICATOR, "ShutdownImminent" },
{ HUP_BATTERY, HUB_AC_PRESENT,
- SENSOR_INDICATOR, "ACPresent" },
- { HUP_BATTERY, HUB_ATRATE_TIMETOFULL,
- SENSOR_TIMEDELTA, "AtRateTimeToFull" }
+ SENSOR_INDICATOR, "ACPresent" }
};
+#define UPD_MAX_SENSORS (nitems(upd_usage_batdep) + nitems(upd_usage_roots))
struct upd_report {
size_t size;
int enabled;
};
+SLIST_HEAD(upd_sensor_head, upd_sensor);
struct upd_sensor {
- struct ksensor ksensor;
- struct hid_item hitem;
- int attached;
+ struct ksensor ksensor;
+ struct hid_item hitem;
+ int attached;
+ struct upd_sensor_head children;
+ SLIST_ENTRY(upd_sensor) dep_next;
};
struct upd_softc {
@@ -92,10 +102,13 @@ struct upd_softc {
struct sensor_task *sc_sensortask;
struct upd_report *sc_reports;
struct upd_sensor *sc_sensors;
+ struct upd_sensor_head sc_root_sensors;
};
int upd_match(struct device *, void *, void *);
void upd_attach(struct device *, struct device *, void *);
+void upd_attach_sensor_tree(struct upd_softc *, void *, int, int,
+ struct upd_usage_entry *, struct upd_sensor_head *);
int upd_detach(struct device *, int);
void upd_refresh(void *);
@@ -134,13 +147,11 @@ upd_match(struct device *parent, void *match, void *aux)
DPRINTF(("upd: vendor=0x%04x, product=0x%04x\n", uha->uaa->vendor,
uha->uaa->product));
- /*
- * look for at least one sensor of our table
- */
+ /* need at least one sensor from root of tree */
uhidev_get_report_desc(uha->parent, &desc, &size);
- for (i = 0; i < nitems(upd_usage_table); i++)
+ for (i = 0; i < nitems(upd_usage_roots); i++)
if (upd_lookup_usage_entry(desc, size,
- upd_usage_table + i, &item)) {
+ upd_usage_roots + i, &item)) {
ret = UMATCH_VENDOR_PRODUCT;
break;
}
@@ -153,9 +164,6 @@ upd_attach(struct device *parent, struct device *self, void *aux)
{
struct upd_softc *sc = (struct upd_softc *)self;
struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
- struct hid_item item;
- struct upd_usage_entry *entry;
- struct upd_sensor *sensor;
int size;
int i;
void *desc;
@@ -164,6 +172,7 @@ upd_attach(struct device *parent, struct device *self, void *aux)
sc->sc_hdev.sc_parent = uha->parent;
sc->sc_reports = NULL;
sc->sc_sensors = NULL;
+ SLIST_INIT(&sc->sc_root_sensors);
strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
sizeof(sc->sc_sensordev.xname));
@@ -174,13 +183,41 @@ upd_attach(struct device *parent, struct device *self, void *aux)
sc->sc_reports = mallocarray(sc->sc_max_repid,
sizeof(struct upd_report), M_USBDEV, M_WAITOK | M_ZERO);
- sc->sc_sensors = mallocarray(nitems(upd_usage_table),
+ sc->sc_sensors = mallocarray(UPD_MAX_SENSORS,
sizeof(struct upd_sensor), M_USBDEV, M_WAITOK | M_ZERO);
- sc->sc_num_sensors = 0;
+ for (i = 0; i < UPD_MAX_SENSORS; i++)
+ SLIST_INIT(&sc->sc_sensors[i].children);
+ sc->sc_num_sensors = 0;
uhidev_get_report_desc(uha->parent, &desc, &size);
- for (i = 0; i < nitems(upd_usage_table); i++) {
- entry = &upd_usage_table[i];
+ upd_attach_sensor_tree(sc, desc, size, nitems(upd_usage_roots),
+ upd_usage_roots, &sc->sc_root_sensors);
+ DPRINTF(("upd: sc_num_sensors=%d\n", sc->sc_num_sensors));
+
+ sc->sc_sensortask = sensor_task_register(sc, upd_refresh, 6);
+ if (sc->sc_sensortask == NULL) {
+ printf(", unable to register update task\n");
+ return;
+ }
+ sensordev_install(&sc->sc_sensordev);
+
+ printf("\n");
+
+ DPRINTF(("upd_attach: complete\n"));
+}
+
+void
+upd_attach_sensor_tree(struct upd_softc *sc, void *desc, int size,
+ int nentries, struct upd_usage_entry *entries,
+ struct upd_sensor_head *queue)
+{
+ struct hid_item item;
+ struct upd_usage_entry *entry;
+ struct upd_sensor *sensor;
+ int i;
+
+ for (i = 0; i < nentries; i++) {
+ entry = entries + i;
if (!upd_lookup_usage_entry(desc, size, entry, &item))
continue;
@@ -200,27 +237,18 @@ upd_attach(struct device *parent, struct device *self, void *aux)
sensor->ksensor.value = 0;
sensor_attach(&sc->sc_sensordev, &sensor->ksensor);
sensor->attached = 1;
+ SLIST_INSERT_HEAD(queue, sensor, dep_next);
sc->sc_num_sensors++;
+ upd_attach_sensor_tree(sc, desc, size, entry->nchildren,
+ entry->children, &sensor->children);
+
if (sc->sc_reports[item.report_ID].enabled)
continue;
-
sc->sc_reports[item.report_ID].size = hid_report_size(desc,
size, item.kind, item.report_ID);
sc->sc_reports[item.report_ID].enabled = 1;
}
- DPRINTF(("upd: sc_num_sensors=%d\n", sc->sc_num_sensors));
-
- sc->sc_sensortask = sensor_task_register(sc, upd_refresh, 6);
- if (sc->sc_sensortask == NULL) {
- printf(", unable to register update task\n");
- return;
- }
- sensordev_install(&sc->sc_sensordev);
-
- printf("\n");
-
- DPRINTF(("upd_attach: complete\n"));
}
int