Skip to content

Commit

Permalink
Implement configurable generic thermal backend
Browse files Browse the repository at this point in the history
Previously thermal policy was driven by choosing which plugins dsme should
use. As the plugins are platform dependant this makes it impossible to use
the same dsme build in multiple platforms. In practice this has meant
that lately the thermal policy has been working only in Jolla phone.

Implement generic thermal sensor plugin that is fully configuration data
driven and can be used to monitor any number of thermal sensors that show
up as text files on for example /sys or /proc filesystems.

The configuration file format is documented at:
  doc/thermal_sensor_config_files.txt

Move legacy dbus queries from platform specific plugins to thermal manager.
If suitable thermal objects have been registered, the temperatures can be
queried just like before. Also use dbus constants defined in libdsme
instead of hardcoding method and state names.

Thermal manager now uses polling periods defined in configuration file for
the generic thermal object, but also implements thermal status specific
fallback strategy.

A graphviz diagram is provided to clarify control flow between the thermal
manager and sensor plugins.

Thermal objects can now be safely unregistered when/if needed. This has
not been a big issue while unregistering has happened only during dsme
exit, but fixing it allows development of features like configuration
reload without restarting dsme.

Drop Jolla phone hw temperature plugins. The functionality can be
implemented via platform specific configuration files.

Drop N9 surface temperature object and battery temperature plugins.
The battery temperature is used only for estimating the device surface
temperature and compiling it requires build-dependency to libbmeipc.
If/when this is needed battery temperature plugin should be build
separately from N9 specific adaptation repository after which the
surface temperature object can be implemeted as configuration entry.

Drop N9 memory temperature object and omap temperature plugins. Since
memory temperature can be read from sysfs file, it can be implemented
as configuration entry if/when needed.

While the thermalobject.c is a new source file, it contains code/logic
copied from the old implementation. For this reason also the relevant
author and copyright information has been copied over from older sources.

[dsme] Implement configurable generic thermal backend. Fixes JB#25904
  • Loading branch information
spiiroin committed May 6, 2015
1 parent 0999bf5 commit 8536793
Show file tree
Hide file tree
Showing 19 changed files with 3,712 additions and 1,658 deletions.
44 changes: 8 additions & 36 deletions configure.ac
Expand Up @@ -11,21 +11,6 @@ AC_CONFIG_SRCDIR([dsme/dsme-wdd-wd.c])
# CONFIG OPTIONS
#

# bmeipc
AC_ARG_WITH([bmeipc],
[AS_HELP_STRING([--without-bmeipc],
[disable BME ipc communication])])

AS_IF([test "x$with_bmeipc" != xno],
[AC_CHECK_LIB([bmeipc], [bmeipc_open],
[AC_SUBST([LIBBMEIPC], ["-lbmeipc"])
AC_DEFINE([DSME_BMEIPC], [1])
],
[AC_MSG_FAILURE([libbmeipc not found (--without-bmeipc to disable)])])
])

AM_CONDITIONAL([WANT_BMEIPC], [test x$with_bmeipc != xno])

#
# powerontimer
#
Expand Down Expand Up @@ -92,30 +77,17 @@ AS_IF([test "x$enable_validatorlistener" != xno],
AM_CONDITIONAL([WANT_VALIDATOR_LISTENER], [test x$enable_validatorlistener != xno])

#
# memory thermal mgmt
#
AC_ARG_ENABLE([memory-thermal-mgmt],
[AS_HELP_STRING([--enable-memory-thermal-mgmt],
[enable memory thermal management (libthermalobject_memory)])],
[],
[enable_memory_thermal_mgmt=no])

AS_IF([test "x$enable_memory_thermal_mgmt" != xno],
[AC_DEFINE([DSME_MEMORY_THERMAL_MGMT], [1])])
AM_CONDITIONAL([WANT_MEMORY_THERMAL_MGMT], [test x$enable_memory_thermal_mgmt != xno])

#
# HW thermal mgmt
# Generic thermal mgmt
#
AC_ARG_ENABLE([hw-thermal-mgmt],
[AS_HELP_STRING([--disable-hw-thermal-mgmt],
[disable hw thermal management (libthermalobject_hw)])],
AC_ARG_ENABLE([generic-thermal-mgmt],
[AS_HELP_STRING([--disable-generic-thermal-mgmt],
[disable generic thermal management (libthermalobject_generic)])],
[],
[enable_hw_thermal_mgmt=yes])
[enable_generic_thermal_mgmt=yes])

AS_IF([test "x$enable_hw_thermal_mgmt" != xno],
[AC_DEFINE([DSME_HW_THERMAL_MGMT], [1])])
AM_CONDITIONAL([WANT_HW_THERMAL_MGMT], [test x$enable_hw_thermal_mgmt != xno])
AS_IF([test "x$enable_generic_thermal_mgmt" != xno],
[AC_DEFINE([DSME_GENERIC_THERMAL_MGMT], [1])])
AM_CONDITIONAL([WANT_GENERIC_THERMAL_MGMT], [test x$enable_generic_thermal_mgmt != xno])

#
# pwrkeymonitor
Expand Down
228 changes: 228 additions & 0 deletions doc/thermal_sensor_config_files.txt
@@ -0,0 +1,228 @@
General
=======

Temperature sensors provide input for dsme thermal policy. When
one or more sensors indicate that the device is running too hot
or cold, the dsme thernal manager will broadcast D-Bus signals.
Other components on the system can subscribe to these signals
and for example notify the user about the situation. If at
least one sensor gets to fatal thermal status, the device will
shutdown.

This document describes the configuration file format used for
describing location and thermal limits for temperature sensors
accessible via file io.

Encoding
========

The general format for the configuration file is:
<keyword>':'[whitespace]<argument>[<whitespace><argument>]...

Any line starting with '#' is assumed to be a comment.

Apart from comment lines the file should be ascii text.

The "Name" keyword selects sensor configuration to modify. All
the other keywords modify the latest sensor to be named.

It is assumed that there is no need for white space characters
when specifying sensor names, file paths and enable/disable
strings.

Location
========

The sensor plugin looks for files matching glob pattern:
/etc/dsme/thermal_sensor_*.conf

The configuration files should be installed from hw adaptation
specific packages to /etc/dsme directory and the name should
include a hw identifier part, something like:
/etc/dsme/thermal_sensor_sbj.conf
/etc/dsme/thermal_sensor_rm696.conf

Parsing
=======

First all installed configuration files are read and a set
of thermal objects is constructed.

Then each thermal object is
a) validated for internal consistency
b) registered to thermal manager

The validation includes checking that the sensor value can be
read. This implicitly means that meta-sensors must be defined
later than the sensors they depend on or the validation step
will fail. Which in turn means that all meta sensors that are
part of circular dependency chain get rejected.

The parser is implemented in modules/thermalsensor_generic.c
starting from function tsg_objects_read_config().

Keywords
========

Name: <sensor_name>

Required

If the configuration for given sensor_name does not
exist yet, it is created and selected. Otherwise
already existing configuration item is selected.

There are no hard requirements for sensor naming, but
thermal manager D-Bus service assigns special meaning
to sensor names "core", "battery" and"surface", so
those should be used when applicable.

To allow flexibility in dealing with single/multicore
devices etc, the sensor_name can be constructed from
two parts: <group_prefix><unique_part>

So on a single core device there should be
Name: core

But multicore device could do also
Name: core:cpu1
Name: core:cpu2

Or alternatively:
Name: core0
Name: core1

After which D-Bus query for "core" sensor will return
the status of the sensor in the "core" group that has
the biggest deviation from normal status.

Temp: <path_to_temperature_file> <temperature_unit>

Required unless "Meta" keyword is used.

The path_to_temperature_file defines a file path from
which integer temperature value can be read.

Configuration validation will fail unless the file
exists and is readable by dsme.

The temperature_unit defines how the integer value
should be interpreted. Supported units are:

- "C" degrees Centigrade, used as is
- "dC" 10ths of degrees, rounded up to full degrees
- "mc" 1000ths of degrees, rounded up to full degrees

Meta: <sensor_name> [offset]

Required unless "Temp" keyword is used.

The dependency sensor_name must already be defined or
the meta sensor validation will fail.

The offset is degrees to added to the temperature
of the named sensor, e.g.

meta_sensor_temp = dependency_sensor_temp + offset

Can be used for example in cases where there is no
separate surface temperature sensor, but the
temperature on the surface can be estimated based on
some other sensor like battery / cpu core.

Using meta sensor allows warning user about possible
surface temperature issues while the "real" battery or
core temperature config deals with hardware operational
limits only.

Mode: <path_to_control_file> <enable_string> [disable_string]

Optional, makes sense only if "Temp" keyword is used.

Should be used if sensor needs to be explicitly
enabled. If disable_string is not defined, the sensor
is left enabled on dsme exit.

Configuration validation will fail if:
- path_to_control_file is not writable by dsme
- enable_string is not set
- writing enable_string to path_to_control_file fails

Low: <mintemp> <minwait> <maxwait>
Normal: <mintemp> <minwait> <maxwait>
Warning: <mintemp> <minwait> <maxwait>
Alert: <mintemp> <minwait> <maxwait>
Fatal: <mintemp> <minwait> <maxwait>
Invalid: <mintemp> <minwait> <maxwait>

Required, all thermal status levels must be defined.

The mintemp specifies the low temperature bound
for the thermal status.

The minwait/maxwait defines the polling delay while
the sensor is in this thermal status.

Also temperatures that are below Low.mintemp are
considered Invalid. The expected range provided
by the sensor should be [Low.mintemp ... Invalid.mintemp)

Configuration validation will fail if:
- one or more levels are not defined
- temperatures are not in ascending order
- polling delays do not make sense

If needed for some reason, it is possible to leave
out some levels by defining the following levels
to start from the same mintemp, for example:

Low: -50 30 30
Normal: -50 30 30
Warning: 100 30 30
Alert: 100 30 30
Fatal: 100 30 30
Invalid: 100 30 30

Would make temperatures from -50 to +99 register as
"normal" and everything else as "invalid".

Example
=======

# CPU temperature that can be read from sysfs file, is reported
# as degrees Centigrade and must be explicitly enabled

Name: core
Temp: /sys/devices/virtual/thermal/thermal_zone9/temp C
Mode: /sys/devices/virtual/thermal/thermal_zone9/mode enabled disabled
Low: -99 60 120
Normal: -15 60 120
Warning: 99 30 60
Alert: 109 5 10
Fatal: 119 5 10
Invalid: 200 60 120

# Battery temperature that can be read from sysfs file, is
# reported as tenths of degrees Centigrade and does not need to
# be explicitly enabled

Name: battery
Temp: /sys/class/power_supply/battery/temp dC
Low: -99 60 120
Normal: -4 60 120
Warning: 59 30 60
Alert: 64 5 10
Fatal: 68 5 10
Invalid: 200 60 120

# Surface temperature that is assumed to be roughly equal
# to battery temperature minus one degree

Name: surface
Meta: battery -1
Low: -99 60 120
Normal: -1 55 60
Warning: 56 55 60
Alert: 59 20 30
Fatal: 63 20 30
Invalid: 200 60 120
41 changes: 8 additions & 33 deletions modules/Makefile.am
Expand Up @@ -34,17 +34,8 @@ noinst_HEADERS = dsme_dbus.h \
#
pkgsysconfdir = @sysconfdir@


if WANT_BMEIPC
pkglib_LTLIBRARIES += thermalobject_surface.la
endif

if WANT_MEMORY_THERMAL_MGMT
pkglib_LTLIBRARIES += thermalobject_memory.la
endif

if WANT_HW_THERMAL_MGMT
pkglib_LTLIBRARIES += thermalobject_hw.la
if WANT_GENERIC_THERMAL_MGMT
pkglib_LTLIBRARIES += thermalsensor_generic.la
endif

if WANT_POWERON_TIMER
Expand Down Expand Up @@ -130,8 +121,8 @@ alarmtracker_la_SOURCES = alarmtracker.c
alarmtracker_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
alarmtracker_la_CPPFLAGS = $(AM_CPPFLAGS) -D_GNU_SOURCE

thermalmanager_la_SOURCES = thermalmanager.c
thermalmanager_la_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS) $(DBUS_CFLAGS) -DDSME_THERMAL_TUNING
thermalmanager_la_SOURCES = thermalmanager.c thermalobject.c
thermalmanager_la_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS) $(DBUS_CFLAGS)
thermalmanager_la_LIBADD = -lthermalmanager_dbus_if

emergencycalltracker_la_SOURCES = emergencycalltracker.c
Expand All @@ -150,26 +141,10 @@ thermalflagger_la_SOURCES = thermalflagger.c

malf_la_SOURCES = malf.c

if WANT_BMEIPC
thermalobject_surface_la_SOURCES = thermalobject_surface.c \
thermalsensor_battery.c \
thermalsensor_battery.h
thermalobject_surface_la_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS)
thermalobject_surface_la_LIBADD = $(GLIB_LIBS)
endif

if WANT_MEMORY_THERMAL_MGMT
thermalobject_memory_la_SOURCES = thermalobject_memory.c \
thermalsensor_omap.c \
thermalsensor_omap.h
endif

if WANT_HW_THERMAL_MGMT
thermalobject_hw_la_SOURCES = thermalobject_hw.c \
thermalsensor_hw.c \
thermalsensor_hw.h
thermalobject_hw_la_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS) $(DBUS_CFLAGS)
thermalobject_hw_la_LIBADD = $(GLIB_LIBS)
if WANT_GENERIC_THERMAL_MGMT
thermalsensor_generic_la_SOURCES = thermalsensor_generic.c
thermalsensor_generic_la_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS) $(DBUS_CFLAGS)
thermalsensor_generic_la_LIBADD = -lthermalmanager_dbus_if
endif


Expand Down
10 changes: 2 additions & 8 deletions modules/startup.c
Expand Up @@ -90,14 +90,8 @@ const char *modules[] = {
#endif
"thermalflagger.so",
"thermalmanager.so",
#ifdef DSME_HW_THERMAL_MGMT
"thermalobject_hw.so",
#endif
#ifdef DSME_MEMORY_THERMAL_MGMT
"thermalobject_memory.so",
#endif
#ifdef DSME_BMEIPC
"thermalobject_surface.so",
#ifdef DSME_GENERIC_THERMAL_MGMT
"thermalsensor_generic.so",
#endif
"emergencycalltracker.so",
"usbtracker.so",
Expand Down

0 comments on commit 8536793

Please sign in to comment.