Add capability to send sensor limit values to the driver so they can

be programmed into device registers.  This way we can let the hardware
help us out instead of having to always compare the value against each
limit.  (Driver updates for some sensors to take advantage of this
capability will be forthcoming.)
This commit is contained in:
pgoyette 2009-06-13 16:08:25 +00:00
parent fdcbe744db
commit c235777756
7 changed files with 305 additions and 143 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: envsys.4,v 1.42 2009/03/15 12:33:53 joerg Exp $
.\" $NetBSD: envsys.4,v 1.43 2009/06/13 16:08:25 pgoyette Exp $
.\"
.\" Copyright (c) 2007 The NetBSD Foundation, Inc.
.\" All rights reserved.
@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd November 13, 2007
.Dd June 12, 2009
.Dt ENVSYS 4
.Os
.Sh NAME
@ -135,6 +135,12 @@ dictionary (which contains specific properties for a device):
\&\*[Lt]string\&\*[Gt]Ampere hour\&\*[Lt]\&/string\&\*[Gt]
\&\*[Lt]key\&\*[Gt]want-percentage\&\*[Lt]\&/key\&\*[Gt]
\&\*[Lt]true\&/\&\*[Gt]
\&\*[Lt]key\&\*[Gt]warning-capacity\&\*[Lt]\&/key\&\*[Gt]
\&\*[Lt]integer\&\*[Gt]19234\&\*[Lt]\&/integer\&\*[Gt]
\&\*[Lt]key\&\*[Gt]warning-max\&\*[Lt]\&/key\&\*[Gt]
\&\*[Lt]integer\&\*[Gt]323150000\&\*[Lt]\&/integer\&\*[Gt]
\&\*[Lt]key\&\*[Gt]warning-min\&\*[Lt]\&/key\&\*[Gt]
\&\*[Lt]integer\&\*[Gt]298150000\&\*[Lt]\&/integer\&\*[Gt]
\&\*[Lt]\&/dict\&\*[Gt]
\&\*[Lt]dict\&\*[Gt]
\&\*[Lt]key\&\*[Gt]device-properties\&\*[Lt]\&/key\&\*[Gt]
@ -184,19 +190,14 @@ Current max value in the sensor.
Current min value in the sensor.
.It Fa monitoring-state-critical
If true, the driver has enabled the flag to monitor a critical state.
.It Fa monitoring-state-critical-over
If true, the driver has enabled the flag to monitor a critical over state.
.It Fa monitoring-state-critical-under
If true, the driver has enabled the flag to monitor a critical under state.
.It Fa monitoring-state-hw-range-limits
If true, the driver has enabled the flag to monitor warning or critical
limits.
.It Fa monitoring-state-state-changed
If true, the driver has enabled the flag to monitor for state changes in
a drive or Battery state sensor.
.It Fa monitoring-state-warning-over
If true, the driver has enabled the flag to monitor a warning over state.
.It Fa monitoring-state-warning-under
If true, the driver has enabled the flag to monitor a warning under state.
.It Fa monitoring-supported
If true, critical capacity/max/min limits may be set by the
If true, critical/warning capacity/max/min limits may be set by the
.Dv ENVSYS_SETDICTIONARY
.Xr ioctl 2 .
.It Fa state
@ -209,6 +210,21 @@ If true,
and
.Em cur-value
are valid and a percentage may be computed from them.
.It Fa warning-capacity
Warning capacity set previously by the
.Dv ENVSYS_SETDICTIONARY
.Xr ioctl 2 .
Only available on sensors with the
.Em want-percentage
object enabled.
.It Fa warning-max
Warning max limit set previously by the
.Dv ENVSYS_SETDICTIONARY
.Xr ioctl 2 .
.It Fa warning-min
Warning min limit set previously by the
.Dv ENVSYS_SETDICTIONARY
.Xr ioctl 2 .
.El
.It Dv ENVSYS_REMOVEPROPS Pq prop_dictionary_t
.Pp
@ -251,6 +267,12 @@ a sensor understands:
\&\*[Lt]integer\&\*[Gt]3400\&\*[Lt]\&/integer\&\*[Gt]
\&\*[Lt]key\&\*[Gt]critical-min\&\*[Lt]\&/key\&\*[Gt]
\&\*[Lt]integer\&\*[Gt]2800\&\*[Lt]\&/integer\&\*[Gt]
\&\*[Lt]key\&\*[Gt]warning-capacity\&\*[Lt]\&/key\&\*[Gt]
\&\*[Lt]integer\&\*[Gt]15\&\*[Lt]\&/integer\&\*[Gt]
\&\*[Lt]key\&\*[Gt]warning-max\&\*[Lt]\&/key\&\*[Gt]
\&\*[Lt]integer\&\*[Gt]3200\&\*[Lt]\&/integer\&\*[Gt]
\&\*[Lt]key\&\*[Gt]warning-min\&\*[Lt]\&/key\&\*[Gt]
\&\*[Lt]integer\&\*[Gt]2900\&\*[Lt]\&/integer\&\*[Gt]
\&\*[Lt]\&/dict\&\*[Gt]
.Ed
.Pp
@ -305,12 +327,12 @@ object specifying the sensor that is required for the new properties.
If an unknown object was sent with the dictionary,
.Er EINVAL
will be returned, or if the sensor does not support changing
rfact (voltage sensors) or critical/capacity limits,
rfact (voltage sensors) or critical/warning/capacity limits,
.Er ENOTSUP
will be returned.
.El
.Sh NOTES
When setting a critical max or min limit with the
When setting a critical/warning max or min limit with the
.Dv ENVSYS_SETDICTIONARY
.Xr ioctl 2 ,
the user must be aware that
@ -320,7 +342,7 @@ Please see
.Xr sysmon_envsys 9
for more information.
.Pp
Also when setting a critical capacity limit, the formula to send a
Also when setting a critical or warning capacity limit, the formula to send a
proper value to
.Xr sysmon_envsys 9
is the following:

View File

@ -1,4 +1,4 @@
.\" $NetBSD: sysmon_envsys.9,v 1.24 2009/06/01 20:08:44 pgoyette Exp $
.\" $NetBSD: sysmon_envsys.9,v 1.25 2009/06/13 16:08:25 pgoyette Exp $
.\"
.\" Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
.\" All rights reserved.
@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd June 1, 2009
.Dd June 13, 2009
.Dt SYSMON_ENVSYS 9
.Os
.Sh NAME
@ -104,6 +104,8 @@ struct sysmon_envsys {
uint64_t sme_events_timeout;
void *sme_cookie;
void (*sme_refresh)(struct sysmon_envsys *, envsys_data_t *);
void (*sme_set_limits)(struct sysmon_envsys *, sysmon_envsys_lim_t *);
void (*sme_get_limits)(struct sysmon_envsys *, sysmon_envsys_lim_t *);
};
.Ed
.Pp
@ -126,14 +128,10 @@ Currently supporting
If enabled, the
.Ar sme_refresh
function callback won't be used
to refresh sensors data and the driver will use its own method.
Hence
.Ar sme_cookie
won't be necessary either (OPTIONAL).
to refresh sensors data and the driver will use its own method (OPTIONAL).
.It Fa sme_events_timeout
This is used to specify the default timeout value that will be used to
check for critical events if any monitoring flag was set.
The value is used as seconds (OPTIONAL).
This is used to specify the default timeout value (in seconds) that will be
used to check for critical events if any monitoring flag was set (OPTIONAL).
.El
.Pp
If the driver wants to refresh sensors data via the
@ -145,8 +143,11 @@ framework, the following members must be specified:
Pointer to the device struct (also called
.Dq softc ) .
This may be used in the
.Sy sme_refresh
function callback.
.Sy sme_refresh ,
.Sy sme_get_limits ,
or
.Sy sme_set_limits
function callbacks.
.It Fa sme_refresh
Pointer to a function that will be used to refresh sensor data in
the device.
@ -156,6 +157,19 @@ sensor depending of the returned data by the driver.
.Em You don't have to refresh all sensors, only the sensor specified by the
.Sy edata-\*[Gt]sensor
.Em index .
.It Fa sme_get_limits
Pointer to a function that will be used to obtain from the driver the
initial limits (or thresholds) used when monitoring a sensor's value.
(See the
.Sx SENSOR DETAILS
section for more information.)
.It Fa sme_set_limits
Pointer to a function that alerts the device driver whenever monitoring
limits (or thresholds) are updated by the user.
Setting this function allows the device driver to reprogram hardware
limits (if provided by the device), and gives the driver direct control
over setting the sensor's state based on hardware status.
XXXX
.El
.Pp
Note that it's not necessary to refresh the sensors data before the
@ -203,7 +217,7 @@ of
This will be used to report its current state (on/off).
.It SME_CLASS_BATTERY
.Pp
This class is for devices that want to act as an
This class is for devices that want to act as a
.Em Battery .
The device writer must ensure that at least there are two sensors with
units of
@ -211,14 +225,14 @@ units of
and
.Sy ENVSYS_BATTERY_CHARGE .
.Pp
These two sensors are used to ensure that the battery device won't
never send a
These two sensors are used to ensure that the battery device can
send a
.Em low-power
event to the
.Xr powerd 8
daemon (if running) when all battery devices are in a critical state.
The critical state means that a battery is not currently charging
and its charge state is low or critical.
(The critical state occurs when a battery is not currently charging
and its charge state is low or critical).
When the
.Em low-power
condition is met, an event is sent to the
@ -241,7 +255,7 @@ If a
.Dv SME_CLASS_ACADAPTER
or
.Dv SME_CLASS_BATTERY
class don't have the sensors required, the
class device doesn't have the sensors required, the
.Em low-power
event will never be sent, and the graceful shutdown won't be possible.
.Ss SENSOR DETAILS
@ -301,10 +315,13 @@ daemon (if running).
The monitoring event will be registered when this flag is
.Dv true
and one or more of the
.Dv ENVSYS_FMONFOO
.Dv ENVSYS_FMONxxx
flags were set in the
.Ar flags
member.
.Em NOTE
.Em that limits (or thresholds) can be set at any time to enable
.Em monitoring that the sensor's value remains within those limits.
.It Fa desc
Used to set the description string.
.Em NOTE
@ -445,11 +462,11 @@ member is not set to
or
.Ar ENVSYS_BATTERY_CAPACITY .
.It ENVSYS_FMONNOTSUPP
Disallows to set a critical limit via the
Disallows setting of limits (or thresholds) via the
.Dv ENVSYS_SETDICTIONARY
.Xr ioctl 2 .
This flag has not any effect for monitoring flags set in the driver and it's
only meant to disable setting critical limits from userland.
This flag has no effect on monitoring flags set in the driver and is
only disables setting the limits from userland.
.El
.Pp
.Em If the driver has to use any of the
@ -464,10 +481,9 @@ If
.Ar units
is set to
.Ar ENVSYS_DRIVE ,
there are some predefined states that must be set (only one)
to the
the
.Ar value_cur
member:
member must be set to one of the following predefined states:
.Pp
.Bl -tag -width "ENVSYS_DRIVE_POWERDOWNXX" -compact
.It ENVSYS_DRIVE_EMPTY
@ -505,10 +521,9 @@ If
.Ar units
is set to
.Ar ENVSYS_BATTERY_CAPACITY ,
there are some predefined capacity states that must be set (only one)
to the
the
.Ar value_cur
member:
member must be set to one of the following predefined capacity states:
.Pp
.Bl -tag -width "ENVSYS_BATTERY_CAPACITY_CRITICAL" -compact
.It ENVSYS_BATTERY_CAPACITY_NORMAL

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysmon_envsys.c,v 1.87 2009/06/08 00:55:35 pgoyette Exp $ */
/* $NetBSD: sysmon_envsys.c,v 1.88 2009/06/13 16:08:25 pgoyette Exp $ */
/*-
* Copyright (c) 2007, 2008 Juan Romero Pardines.
@ -64,7 +64,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.87 2009/06/08 00:55:35 pgoyette Exp $");
__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.88 2009/06/13 16:08:25 pgoyette Exp $");
#include <sys/param.h>
#include <sys/types.h>
@ -1633,6 +1633,76 @@ sme_update_dictionary(struct sysmon_envsys *sme)
if (error)
break;
}
#ifdef NOTYET
/*
* Update limits from driver if they've been changed
*/
if ((edata->flags & ENVSYS_FLIMITS_CHANGED) == 0)
continue;
if (edata->upropset & PROP_DRVR_CRITMAX) {
error = sme_sensor_upint32(dict, "critical-max",
edata->lim_critmax);
if (error)
break;
edata->upropset &= ~PROP_USER_CRITMAX;
} else if ((edata->upropset & PROP_USER_CRITMAX) == 0)
prop_dictionary_remove(dict, "critical-max");
if (edata->upropset & PROP_DRVR_WARNMAX) {
error = sme_sensor_upint32(dict, "warning-max",
edata->lim_warnmax);
if (error)
break;
edata->upropset &= ~PROP_USER_WARNMAX;
} else if ((edata->upropset & PROP_USER_WARNMAX) == 0)
prop_dictionary_remove(dict, "warning-max");
if (edata->flags & ENVSYS_FPERCENT) {
if (edata->upropset & PROP_DRVR_BATTWARN) {
error = sme_sensor_upint32(dict,
"warning-capacity",
edata->lim_warnmin);
if (error)
break;
edata->upropset &= ~PROP_USER_BATTWARN;
} else if ((edata->upropset & PROP_USER_BATTWARN) == 0)
prop_dictionary_remove(dict,
"warning-capacity");
if (edata->upropset & PROP_DRVR_BATTCAP) {
error = sme_sensor_upint32(dict,
"critical-capacity",
edata->lim_critmin);
if (error)
break;
edata->upropset &= ~PROP_USER_BATTCAP;
} else if ((edata->upropset & PROP_USER_BATTCAP) == 0)
prop_dictionary_remove(dict,
"critical-capacity");
} else {
if (edata->upropset & PROP_DRVR_WARNMIN) {
error = sme_sensor_upint32(dict,
"warning-min",
edata->lim_warnmin);
if (error)
break;
edata->upropset &= ~PROP_USER_WARNMIN;
} else if ((edata->upropset & PROP_USER_WARNMIN) == 0)
prop_dictionary_remove(dict, "warning-min");
if (edata->upropset & PROP_DRVR_CRITMIN) {
error = sme_sensor_upint32(dict,
"critical-min",
edata->lim_critmin);
if (error)
break;
edata->upropset &= ~PROP_USER_CRITMIN;
} else if ((edata->upropset & PROP_USER_CRITMIN) == 0)
prop_dictionary_remove(dict, "critical-min");
}
#endif
}
return error;
@ -1653,8 +1723,7 @@ sme_userset_dictionary(struct sysmon_envsys *sme, prop_dictionary_t udict,
prop_dictionary_t dict, tdict = NULL;
prop_object_t obj, obj1, obj2, tobj = NULL;
uint64_t refresh_timo = 0;
int32_t critmax = 0, warnmax = 0, warnmin = 0, critmin = 0;
int props = 0;
sysmon_envsys_lim_t lims;
int i, error = 0;
const char *blah;
bool targetfound = false;
@ -1718,6 +1787,8 @@ sme_userset_dictionary(struct sysmon_envsys *sme, prop_dictionary_t udict,
if (!prop_string_equals(obj1, obj))
continue;
lims.sel_flags = 0;
/*
* Check if a new description operation was
* requested by the user and set new description.
@ -1796,8 +1867,8 @@ sme_userset_dictionary(struct sysmon_envsys *sme, prop_dictionary_t udict,
goto out;
}
critmin = prop_number_integer_value(obj2);
props |= PROP_BATTCAP;
lims.sel_critmin = prop_number_integer_value(obj2);
lims.sel_flags |= PROP_BATTCAP;
}
/*
@ -1812,8 +1883,8 @@ sme_userset_dictionary(struct sysmon_envsys *sme, prop_dictionary_t udict,
goto out;
}
warnmin = prop_number_integer_value(obj2);
props |= PROP_BATTWARN;
lims.sel_warnmin = prop_number_integer_value(obj2);
lims.sel_flags |= PROP_BATTWARN;
}
/*
@ -1829,8 +1900,8 @@ sme_userset_dictionary(struct sysmon_envsys *sme, prop_dictionary_t udict,
goto out;
}
critmax = prop_number_integer_value(obj2);
props |= PROP_CRITMAX;
lims.sel_critmax = prop_number_integer_value(obj2);
lims.sel_flags |= PROP_CRITMAX;
}
/*
@ -1846,8 +1917,8 @@ sme_userset_dictionary(struct sysmon_envsys *sme, prop_dictionary_t udict,
goto out;
}
warnmax = prop_number_integer_value(obj2);
props |= PROP_WARNMAX;
lims.sel_warnmax = prop_number_integer_value(obj2);
lims.sel_flags |= PROP_WARNMAX;
}
/*
@ -1863,8 +1934,8 @@ sme_userset_dictionary(struct sysmon_envsys *sme, prop_dictionary_t udict,
goto out;
}
critmin = prop_number_integer_value(obj2);
props |= PROP_CRITMIN;
lims.sel_critmin = prop_number_integer_value(obj2);
lims.sel_flags |= PROP_CRITMIN;
}
/*
@ -1880,16 +1951,12 @@ sme_userset_dictionary(struct sysmon_envsys *sme, prop_dictionary_t udict,
goto out;
}
warnmin = prop_number_integer_value(obj2);
props |= PROP_WARNMIN;
lims.sel_warnmin = prop_number_integer_value(obj2);
lims.sel_flags |= PROP_WARNMIN;
}
if (props) {
error = sme_event_register(dict,
edata,
sme,
critmax, warnmax, warnmin,
critmin, props,
if (lims.sel_flags) {
error = sme_event_register(dict, edata, sme, &lims,
(edata->flags & ENVSYS_FPERCENT)?
PENVSYS_EVENT_CAPACITY:
PENVSYS_EVENT_LIMITS,
@ -1900,7 +1967,7 @@ sme_userset_dictionary(struct sysmon_envsys *sme, prop_dictionary_t udict,
goto out;
mutex_enter(&sme->sme_mtx);
edata->upropset |= props;
edata->upropset |= lims.sel_flags;
mutex_exit(&sme->sme_mtx);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysmon_envsys_events.c,v 1.66 2009/06/08 13:06:33 pgoyette Exp $ */
/* $NetBSD: sysmon_envsys_events.c,v 1.67 2009/06/13 16:08:25 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.66 2009/06/08 13:06:33 pgoyette Exp $");
__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys_events.c,v 1.67 2009/06/13 16:08:25 pgoyette Exp $");
#include <sys/param.h>
#include <sys/types.h>
@ -82,9 +82,8 @@ static bool sme_acadapter_check(void);
*/
int
sme_event_register(prop_dictionary_t sdict, envsys_data_t *edata,
struct sysmon_envsys *sme, int32_t critmax,
int32_t warnmax, int32_t warnmin, int32_t critmin,
int lim_flags, int crittype, int powertype)
struct sysmon_envsys *sme, sysmon_envsys_lim_t *lims,
int crittype, int powertype)
{
sme_event_t *see = NULL, *osee = NULL;
prop_object_t obj;
@ -108,36 +107,36 @@ sme_event_register(prop_dictionary_t sdict, envsys_data_t *edata,
__func__, sme->sme_name, edata->desc, lim_flags));
see = osee;
if (lim_flags & PROP_CRITMAX) {
if (critmax == see->see_critmax) {
if (lims->sel_flags & PROP_CRITMAX) {
if (lims->sel_critmax == see->see_lims.sel_critmax) {
DPRINTF(("%s: type=%d (critmax exists)\n",
__func__, crittype));
error = EEXIST;
lim_flags &= ~PROP_CRITMAX;
lims->sel_flags &= ~PROP_CRITMAX;
}
}
if (lim_flags & PROP_WARNMAX) {
if (warnmax == see->see_warnmax) {
if (lims->sel_flags & PROP_WARNMAX) {
if (lims->sel_warnmax == see->see_lims.sel_warnmax) {
DPRINTF(("%s: type=%d (warnmax exists)\n",
__func__, crittype));
error = EEXIST;
lim_flags &= ~PROP_WARNMAX;
lims->sel_flags &= ~PROP_WARNMAX;
}
}
if (lim_flags & (PROP_WARNMIN | PROP_BATTWARN)) {
if (warnmin == see->see_warnmin) {
if (lims->sel_flags & (PROP_WARNMIN | PROP_BATTWARN)) {
if (lims->sel_warnmin == see->see_lims.sel_warnmin) {
DPRINTF(("%s: type=%d (warnmin exists)\n",
__func__, crittype));
error = EEXIST;
lim_flags &= ~(PROP_WARNMIN | PROP_BATTWARN);
lims->sel_flags &= ~(PROP_WARNMIN | PROP_BATTWARN);
}
}
if (lim_flags & (PROP_CRITMIN | PROP_BATTCAP)) {
if (critmin == see->see_critmin) {
if (lims->sel_flags & (PROP_CRITMIN | PROP_BATTCAP)) {
if (lims->sel_critmin == see->see_lims.sel_critmin) {
DPRINTF(("%s: type=%d (critmin exists)\n",
__func__, crittype));
error = EEXIST;
lim_flags &= ~(PROP_CRITMIN | PROP_BATTCAP);
lims->sel_flags &= ~(PROP_CRITMIN | PROP_BATTCAP);
}
}
break;
@ -192,7 +191,7 @@ sme_event_register(prop_dictionary_t sdict, envsys_data_t *edata,
/*
* Limit operation requested.
*/
if (lim_flags & PROP_CRITMAX) {
if (lims->sel_flags & PROP_CRITMAX) {
objkey = "critical-max";
obj = prop_dictionary_get(sdict, objkey);
if (obj && prop_object_type(obj) != PROP_TYPE_NUMBER) {
@ -200,17 +199,19 @@ sme_event_register(prop_dictionary_t sdict, envsys_data_t *edata,
__func__, sme->sme_name, objkey));
error = ENOTSUP;
} else {
see->see_critmax = critmax;
error = sme_sensor_upint32(sdict, objkey, critmax);
see->see_lims.sel_critmax = lims->sel_critmax;
error = sme_sensor_upint32(sdict, objkey,
lims->sel_critmax);
DPRINTF(("%s: (%s) event [sensor=%s type=%d] "
"(%s updated)\n", __func__, sme->sme_name,
edata->desc, crittype, objkey));
}
if (error && error != EEXIST)
goto out;
see->see_edata->upropset |= PROP_CRITMAX;
}
if (error && error != EEXIST)
goto out;
if (lim_flags & PROP_WARNMAX) {
if (lims->sel_flags & PROP_WARNMAX) {
objkey = "warning-max";
obj = prop_dictionary_get(sdict, objkey);
if (obj && prop_object_type(obj) != PROP_TYPE_NUMBER) {
@ -218,17 +219,19 @@ sme_event_register(prop_dictionary_t sdict, envsys_data_t *edata,
__func__, sme->sme_name, objkey));
error = ENOTSUP;
} else {
see->see_warnmax = warnmax;
error = sme_sensor_upint32(sdict, objkey, warnmax);
see->see_lims.sel_warnmax = lims->sel_warnmax;
error = sme_sensor_upint32(sdict, objkey,
lims->sel_warnmax);
DPRINTF(("%s: (%s) event [sensor=%s type=%d] "
"(%s updated)\n", __func__, sme->sme_name,
edata->desc, crittype, objkey));
}
if (error && error != EEXIST)
goto out;
see->see_edata->upropset |= PROP_WARNMAX;
}
if (error && error != EEXIST)
goto out;
if (lim_flags & PROP_WARNMIN) {
if (lims->sel_flags & PROP_WARNMIN) {
objkey = "warning-min";
obj = prop_dictionary_get(sdict, objkey);
if (obj && prop_object_type(obj) != PROP_TYPE_NUMBER) {
@ -236,17 +239,19 @@ sme_event_register(prop_dictionary_t sdict, envsys_data_t *edata,
__func__, sme->sme_name, objkey));
error = ENOTSUP;
} else {
see->see_warnmin = warnmin;
error = sme_sensor_upint32(sdict, objkey, warnmin);
see->see_lims.sel_warnmin = lims->sel_warnmin;
error = sme_sensor_upint32(sdict, objkey,
lims->sel_warnmin);
DPRINTF(("%s: (%s) event [sensor=%s type=%d] "
"(%s updated)\n", __func__, sme->sme_name,
edata->desc, crittype, objkey));
}
if (error && error != EEXIST)
goto out;
see->see_edata->upropset |= PROP_WARNMIN;
}
if (error && error != EEXIST)
goto out;
if (lim_flags & PROP_CRITMIN) {
if (lims->sel_flags & PROP_CRITMIN) {
objkey = "critical-min";
obj = prop_dictionary_get(sdict, objkey);
if (obj && prop_object_type(obj) != PROP_TYPE_NUMBER) {
@ -254,17 +259,19 @@ sme_event_register(prop_dictionary_t sdict, envsys_data_t *edata,
__func__, sme->sme_name, objkey));
error = ENOTSUP;
} else {
see->see_critmin = critmin;
error = sme_sensor_upint32(sdict, objkey, critmin);
see->see_lims.sel_critmin = lims->sel_critmin;
error = sme_sensor_upint32(sdict, objkey,
lims->sel_critmin);
DPRINTF(("%s: (%s) event [sensor=%s type=%d] "
"(%s updated)\n", __func__, sme->sme_name,
edata->desc, crittype, objkey));
}
if (error && error != EEXIST)
goto out;
see->see_edata->upropset |= PROP_CRITMIN;
}
if (error && error != EEXIST)
goto out;
if (lim_flags & PROP_BATTWARN) {
if (lims->sel_flags & PROP_BATTWARN) {
objkey = "warning-capacity";
obj = prop_dictionary_get(sdict, objkey);
if (obj && prop_object_type(obj) != PROP_TYPE_NUMBER) {
@ -272,17 +279,19 @@ sme_event_register(prop_dictionary_t sdict, envsys_data_t *edata,
__func__, sme->sme_name, objkey));
error = ENOTSUP;
} else {
see->see_warnmin = warnmin;
error = sme_sensor_upint32(sdict, objkey, warnmin);
see->see_lims.sel_warnmin = lims->sel_warnmin;
error = sme_sensor_upint32(sdict, objkey,
lims->sel_warnmin);
DPRINTF(("%s: (%s) event [sensor=%s type=%d] "
"(%s updated)\n", __func__, sme->sme_name,
edata->desc, crittype, objkey));
}
if (error && error != EEXIST)
goto out;
see->see_edata->upropset |= PROP_BATTWARN;
}
if (error && error != EEXIST)
goto out;
if (lim_flags & PROP_BATTCAP) {
if (lims->sel_flags & PROP_BATTCAP) {
objkey = "critical-capacity";
obj = prop_dictionary_get(sdict, objkey);
if (obj && prop_object_type(obj) != PROP_TYPE_NUMBER) {
@ -290,28 +299,41 @@ sme_event_register(prop_dictionary_t sdict, envsys_data_t *edata,
__func__, sme->sme_name, objkey));
error = ENOTSUP;
} else {
see->see_critmin = critmin;
error = sme_sensor_upint32(sdict, objkey, critmin);
see->see_lims.sel_critmin = lims->sel_critmin;
error = sme_sensor_upint32(sdict, objkey,
lims->sel_critmin);
DPRINTF(("%s: (%s) event [sensor=%s type=%d] "
"(%s updated)\n", __func__, sme->sme_name,
edata->desc, crittype, objkey));
}
if (error && error != EEXIST)
goto out;
see->see_edata->upropset |= PROP_BATTCAP;
}
if (error && error != EEXIST)
goto out;
DPRINTF(("%s: (%s) event registered (sensor=%s snum=%d type=%d "
"critmin=%" PRIu32 " warnmin=%" PRIu32 " warnmax=%" PRIu32
" critmax=%" PRIu32 " props 0x%04x)\n", __func__,
see->see_sme->sme_name, see->see_pes.pes_sensname,
see->see_edata->sensor, see->see_type, see->see_critmin,
see->see_warnmin, see->see_warnmax, see->see_critmax,
see->see_edata->upropset));
see->see_edata->sensor, see->see_type, see->see_lims.sel_critmin,
see->see_lims.sel_warnmin, see->see_lims.sel_warnmax,
see->see_lims.sel_critmax, see->see_edata->upropset));
/*
* Initialize the events framework if it wasn't initialized before.
*/
if ((sme->sme_flags & SME_CALLOUT_INITIALIZED) == 0)
error = sme_events_init(sme);
/*
* If driver requested notification, advise it of new
* limit values
*/
if (sme->sme_set_limits) {
see->see_lims.sel_flags = see->see_edata->upropset &
PROP_LIMITS;
(*sme->sme_set_limits)(sme, &(see->see_lims));
}
out:
if ((error == 0 || error == EEXIST) && osee == NULL)
LIST_INSERT_HEAD(&sme->sme_events_list, see, see_list);
@ -428,6 +450,7 @@ void
sme_event_drvadd(void *arg)
{
sme_event_drv_t *sed_t = arg;
sysmon_envsys_lim_t lims;
int error = 0;
KASSERT(sed_t != NULL);
@ -440,7 +463,7 @@ do { \
error = sme_event_register(sed_t->sed_sdict, \
sed_t->sed_edata, \
sed_t->sed_sme, \
0, 0, 0, 0, 0, \
&lims, \
(b), \
sed_t->sed_powertype); \
if (error && error != EEXIST) \
@ -457,18 +480,26 @@ do { \
} \
} while (/* CONSTCOND */ 0)
if (sed_t->sed_edata->flags & ENVSYS_FMONLIMITS) {
if (sed_t->sed_sme->sme_get_limits)
(*sed_t->sed_sme->sme_get_limits)(sed_t->sed_sme,
&lims);
else
sed_t->sed_edata->flags &= ~ENVSYS_FMONLIMITS;
}
SEE_REGEVENT(ENVSYS_FMONCRITICAL,
PENVSYS_EVENT_CRITICAL,
"critical");
SEE_REGEVENT(ENVSYS_FMONLIMITS,
PENVSYS_EVENT_LIMITS,
"hw-range-limits");
SEE_REGEVENT(ENVSYS_FMONSTCHANGED,
PENVSYS_EVENT_STATE_CHANGED,
"state-changed");
SEE_REGEVENT(ENVSYS_FMONLIMITS,
PENVSYS_EVENT_LIMITS,
"hw-range-limits");
/*
* we are done, free memory now.
*/
@ -604,24 +635,31 @@ sme_events_worker(struct work *wk, void *arg)
switch (see->see_type) {
/*
* For user range limits, calculate a new state first
* State based on user limits will override any hardware
* detected state.
* For range limits, if the driver claims responsibility for
* limit/range checking, just user driver-supplied status.
* Else calculate our own status. Note that driver must
* relinquish responsibility for ALL limits if there is even
* one limit that it cannot handle!
*/
case PENVSYS_EVENT_LIMITS:
case PENVSYS_EVENT_CAPACITY:
#define __EXCEEDED_LIMIT(lim, rel) ((lim) && edata->value_cur rel (lim))
if __EXCEEDED_LIMIT(see->see_critmin, <)
edata->state = ENVSYS_SCRITUNDER;
else if __EXCEEDED_LIMIT(see->see_warnmin, <)
edata->state = ENVSYS_SWARNUNDER;
else if __EXCEEDED_LIMIT(see->see_warnmax, >)
edata->state = ENVSYS_SWARNOVER;
else if __EXCEEDED_LIMIT(see->see_critmax, >)
edata->state = ENVSYS_SCRITOVER;
#define __EXCEED_LIM(lim, rel) ((lim) && edata->value_cur rel (lim))
if ((see->see_lims.sel_flags & PROP_DRIVER_LIMITS) == 0) {
if __EXCEED_LIM(see->see_lims.sel_critmin, <)
edata->state = ENVSYS_SCRITUNDER;
else if __EXCEED_LIM(see->see_lims.sel_warnmin, <)
edata->state = ENVSYS_SWARNUNDER;
else if __EXCEED_LIM(see->see_lims.sel_warnmax, >)
edata->state = ENVSYS_SWARNOVER;
else if __EXCEED_LIM(see->see_lims.sel_critmax, >)
edata->state = ENVSYS_SCRITOVER;
}
/* FALLTHROUGH */
#undef __EXCEEDED_LIMIT
#undef __EXCEED_LIM
/*
* Send event if state has changed
*/
if (edata->state == see->see_evsent)
break;

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysmon_envsysvar.h,v 1.29 2009/06/08 00:55:35 pgoyette Exp $ */
/* $NetBSD: sysmon_envsysvar.h,v 1.30 2009/06/13 16:08:25 pgoyette Exp $ */
/*-
* Copyright (c) 2007, 2008 Juan Romero Pardines.
@ -73,10 +73,7 @@ typedef struct sme_event {
struct sysmon_envsys *see_sme; /* device associated */
struct penvsys_state see_pes; /* our power envsys */
envsys_data_t *see_edata; /* our sensor data */
int32_t see_critmin; /* critical-min value set */
int32_t see_warnmin; /* warning-min value set */
int32_t see_warnmax; /* warning-max value set */
int32_t see_critmax; /* critical-max value set */
sysmon_envsys_lim_t see_lims; /* limit values */
int see_type; /* type of the event */
int see_evsent; /* event already sent */
int see_flags; /* see above */
@ -128,8 +125,8 @@ void sysmon_envsys_release(struct sysmon_envsys *, bool);
* functions to handle sysmon envsys events.
*/
int sme_event_register(prop_dictionary_t, envsys_data_t *,
struct sysmon_envsys *, int32_t, int32_t,
int32_t, int32_t, int, int, int);
struct sysmon_envsys *, sysmon_envsys_lim_t *,
int, int);
int sme_event_unregister(struct sysmon_envsys *, const char *, int);
void sme_event_unregister_all(struct sysmon_envsys *);
void sme_event_drvadd(void *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysmonvar.h,v 1.27 2008/06/03 15:00:57 jmcneill Exp $ */
/* $NetBSD: sysmonvar.h,v 1.28 2009/06/13 16:08:25 pgoyette Exp $ */
/*-
* Copyright (c) 2000 Zembu Labs, Inc.
@ -60,7 +60,6 @@ struct workqueue;
*****************************************************************************/
struct sme_event;
struct sme_sensor_names;
struct sysmon_envsys {
const char *sme_name; /* envsys device name */
@ -86,6 +85,13 @@ struct sysmon_envsys {
*/
void (*sme_refresh)(struct sysmon_envsys *, envsys_data_t *);
/*
* Function callbacks to exchange limit/threshold values
* with device
*/
void (*sme_set_limits)(struct sysmon_envsys *, sysmon_envsys_lim_t *);
void (*sme_get_limits)(struct sysmon_envsys *, sysmon_envsys_lim_t *);
struct workqueue *sme_wq; /* the workqueue for the events */
struct callout sme_callout; /* for the events */
uint64_t sme_events_timeout; /* the timeout used in the callout */

View File

@ -1,4 +1,4 @@
/* $NetBSD: envsys.h,v 1.25 2009/06/08 00:55:35 pgoyette Exp $ */
/* $NetBSD: envsys.h,v 1.26 2009/06/13 16:08:25 pgoyette Exp $ */
/*-
* Copyright (c) 1999, 2007 The NetBSD Foundation, Inc.
@ -145,7 +145,8 @@ enum envsys_battery_capacity_states {
#define ENVSYS_REMOVEPROPS _IOWR('E', 2, struct plistref)
/*
* Properties that can be set in upropset
* Properties that can be set in upropset (and in the event_limit's
* flags field)
*/
#define PROP_CRITMAX 0x0001
#define PROP_CRITMIN 0x0002
@ -156,6 +157,22 @@ enum envsys_battery_capacity_states {
#define PROP_DESC 0x0040
#define PROP_RFACT 0x0080
#define PROP_DRIVER_LIMITS 0x8000
#define PROP_LIMITS 0x003f
/*
* Thresholds/limits that are being monitored
*/
struct sysmon_envsys_lim {
uint32_t sel_flags; /* Flag which limits are present */
int32_t sel_critmax;
int32_t sel_warnmax;
int32_t sel_warnmin;
int32_t sel_critmin;
};
typedef struct sysmon_envsys_lim sysmon_envsys_lim_t;
/*
* Compatibility with old interface. Only ENVSYS_GTREDATA
* and ENVSYS_GTREINFO ioctls are supported.