Separate event delivery from polling and limit evaluation in

sme_events_worker().

Provide a wrapper that can be called from sensor drivers' interrupt
routines to find and deliver a specific event.

XXX Actually updating sensor drivers (and their parent devices) to
XXX have interrupts is a future enhancement.  This is simply an
XXX enabler.
This commit is contained in:
pgoyette 2010-03-19 01:16:44 +00:00
parent e41c20ba61
commit 4e3cadf247
2 changed files with 74 additions and 38 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysmon_envsys_events.c,v 1.85 2010/02/18 12:30:53 pgoyette Exp $ */
/* $NetBSD: sysmon_envsys_events.c,v 1.86 2010/03/19 01:16:44 pgoyette Exp $ */
/*-
* Copyright (c) 2007, 2008 Juan Romero Pardines.
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys_events.c,v 1.85 2010/02/18 12:30:53 pgoyette Exp $");
__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys_events.c,v 1.86 2010/03/19 01:16:44 pgoyette Exp $");
#include <sys/param.h>
#include <sys/types.h>
@ -578,19 +578,15 @@ sme_events_check(void *arg)
void
sme_events_worker(struct work *wk, void *arg)
{
const struct sme_description_table *sdt = NULL;
const struct sme_sensor_event *sse = sme_sensor_event;
sme_event_t *see = (void *)wk;
struct sysmon_envsys *sme = see->see_sme;
envsys_data_t *edata = see->see_edata;
int i, state = 0;
KASSERT(wk == &see->see_wk);
KASSERT(sme != NULL || edata != NULL);
mutex_enter(&sme->sme_mtx);
if ((see->see_flags & SEE_EVENT_WORKING) == 0)
see->see_flags |= SEE_EVENT_WORKING;
see->see_flags |= SEE_EVENT_WORKING;
/*
* sme_events_check marks the sensors to make us refresh them here.
* Don't refresh if the driver uses its own method for refreshing.
@ -612,7 +608,6 @@ sme_events_worker(struct work *wk, void *arg)
if (edata->state == ENVSYS_SINVALID)
goto out;
switch (see->see_type) {
/*
* For range limits, if the driver claims responsibility for
* limit/range checking, just user driver-supplied status.
@ -620,30 +615,74 @@ sme_events_worker(struct work *wk, void *arg)
* relinquish responsibility for ALL limits if there is even
* one limit that it cannot handle!
*/
if ((see->see_type == PENVSYS_EVENT_LIMITS ||
see->see_type == PENVSYS_EVENT_CAPACITY) &&
(edata->upropset & PROP_DRIVER_LIMITS) == 0) {
if ((edata->upropset & (PROP_CRITMIN | PROP_BATTCAP)) &&
(edata->value_cur < edata->limits.sel_critmin))
edata->state = ENVSYS_SCRITUNDER;
else if ((edata->upropset & (PROP_WARNMIN | PROP_BATTWARN)) &&
(edata->value_cur < edata->limits.sel_warnmin))
edata->state = ENVSYS_SWARNUNDER;
else if ((edata->upropset & (PROP_CRITMAX | PROP_BATTMAX)) &&
(edata->value_cur > edata->limits.sel_critmax))
edata->state = ENVSYS_SCRITOVER;
else if ((edata->upropset & (PROP_WARNMAX | PROP_BATTHIGH)) &&
(edata->value_cur > edata->limits.sel_warnmax))
edata->state = ENVSYS_SWARNOVER;
else
edata->state = ENVSYS_SVALID;
}
sme_deliver_event(see);
out:
see->see_flags &= ~SEE_EVENT_WORKING;
cv_broadcast(&sme->sme_condvar);
mutex_exit(&sme->sme_mtx);
}
/*
* sme_deliver_typed_event
*
* + Find the monitor event of a particular type for a given sensor
* on a device and deliver the event if one is required.
*/
void
sme_deliver_typed_event(struct sysmon_envsys *sme, envsys_data_t *edata,
int ev_type)
{
sme_event_t *see;
mutex_enter(&sme->sme_mtx);
LIST_FOREACH(see, &sme->sme_events_list, see_list) {
if (edata != see->see_edata ||
see->see_type != ev_type)
continue;
sme_deliver_event(see);
break;
}
mutex_exit(&sme->sme_mtx);
}
/*
* sme_deliver_event:
*
* + If new sensor state requires it, send an event to powerd
*
* Must be called with the device's sysmon mutex held
* see->see_sme->sme_mtx
*/
void
sme_deliver_event(sme_event_t *see)
{
envsys_data_t *edata = see->see_edata;
const struct sme_description_table *sdt = NULL;
const struct sme_sensor_event *sse = sme_sensor_event;
int i, state = 0;
switch (see->see_type) {
case PENVSYS_EVENT_LIMITS:
case PENVSYS_EVENT_CAPACITY:
#define __EXCEED_LIM(valid, lim, rel) \
((edata->upropset & (valid)) && \
(edata->value_cur rel (edata->limits.lim)))
if ((edata->upropset & PROP_DRIVER_LIMITS) == 0) {
if __EXCEED_LIM(PROP_CRITMIN | PROP_BATTCAP,
sel_critmin, <)
edata->state = ENVSYS_SCRITUNDER;
else if __EXCEED_LIM(PROP_WARNMIN | PROP_BATTWARN,
sel_warnmin, <)
edata->state = ENVSYS_SWARNUNDER;
else if __EXCEED_LIM(PROP_CRITMAX | PROP_BATTMAX,
sel_critmax, >)
edata->state = ENVSYS_SCRITOVER;
else if __EXCEED_LIM(PROP_WARNMAX | PROP_BATTHIGH,
sel_warnmax, >)
edata->state = ENVSYS_SWARNOVER;
else
edata->state = ENVSYS_SVALID;
}
#undef __EXCEED_LIM
/*
* Send event if state has changed
*/
@ -763,7 +802,7 @@ sme_events_worker(struct work *wk, void *arg)
* Stop the callout and send the 'low-power' event.
*/
sysmon_low_power = true;
callout_stop(&sme->sme_callout);
callout_stop(&see->see_sme->sme_callout);
pes.pes_type = PENVSYS_TYPE_BATTERY;
sysmon_penvsys_event(&pes, PENVSYS_EVENT_LOW_POWER);
}
@ -771,11 +810,6 @@ sme_events_worker(struct work *wk, void *arg)
default:
panic("%s: invalid event type %d", __func__, see->see_type);
}
out:
see->see_flags &= ~SEE_EVENT_WORKING;
cv_broadcast(&sme->sme_condvar);
mutex_exit(&sme->sme_mtx);
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysmon_envsysvar.h,v 1.32 2010/03/14 18:03:15 pgoyette Exp $ */
/* $NetBSD: sysmon_envsysvar.h,v 1.33 2010/03/19 01:16:44 pgoyette Exp $ */
/*-
* Copyright (c) 2007, 2008 Juan Romero Pardines.
@ -129,7 +129,9 @@ void sme_event_drvadd(void *);
int sme_events_init(struct sysmon_envsys *);
void sme_events_destroy(struct sysmon_envsys *);
void sme_events_check(void *);
void sme_events_worker(struct work *, void *);
void sme_events_worker(struct work *, void *);
void sme_deliver_event(sme_event_t *);
void sme_deliver_typed_event(struct sysmon_envsys *, envsys_data_t *, int);
/*
* common functions to create/update objects in a dictionary.