2018-05-07 17:52:29 +00:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
2012-09-18 05:34:53 +00:00
|
|
|
/*
|
|
|
|
* thermal_core.h
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012 Intel Corp
|
|
|
|
* Author: Durgadoss R <durgadoss.r@intel.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __THERMAL_CORE_H__
|
|
|
|
#define __THERMAL_CORE_H__
|
|
|
|
|
|
|
|
#include <linux/device.h>
|
|
|
|
#include <linux/thermal.h>
|
|
|
|
|
2020-07-07 09:01:57 +00:00
|
|
|
#include "thermal_netlink.h"
|
thermal: core: Add user thresholds support
The user thresholds mechanism is a way to have the userspace to tell
the thermal framework to send a notification when a temperature limit
is crossed. There is no id, no hysteresis, just the temperature and
the direction of the limit crossing. That means we can be notified
when a threshold is crossed the way up only, or the way down only or
both ways. That allows to create hysteresis values if it is needed.
A threshold can be added, deleted or flushed. The latter means all
thresholds belonging to a thermal zone will be deleted.
When a threshold is added:
- if the same threshold (temperature and direction) exists, an error
is returned
- if a threshold is specified with the same temperature but a
different direction, the specified direction is added
- if there is no threshold with the same temperature then it is
created
When a threshold is deleted:
- if the same threshold (temperature and direction) exists, it is
deleted
- if a threshold is specified with the same temperature but a
different direction, the specified direction is removed
- if there is no threshold with the same temperature, then an error
is returned
When the threshold are flushed:
- All thresholds related to a thermal zone are deleted
When a threshold is crossed:
- the userspace does not need to know which threshold(s) have been
crossed, it will be notified with the current temperature and the
previous temperature
- if multiple thresholds have been crossed between two updates only
one notification will be send to the userspace, it is pointless to
send a notification per thresholds crossed as the userspace can
handle that easily when it has the temperature delta information
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Link: https://patch.msgid.link/20240923100005.2532430-2-daniel.lezcano@linaro.org
[ rjw: Subject edit, use BIT(0) and BIT(1) in symbol definitions ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2024-09-23 09:59:57 +00:00
|
|
|
#include "thermal_thresholds.h"
|
2024-01-09 09:41:11 +00:00
|
|
|
#include "thermal_debugfs.h"
|
2020-07-07 09:01:57 +00:00
|
|
|
|
2024-07-29 16:25:03 +00:00
|
|
|
struct thermal_attr {
|
|
|
|
struct device_attribute attr;
|
|
|
|
char name[THERMAL_NAME_LENGTH];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct thermal_trip_attrs {
|
|
|
|
struct thermal_attr type;
|
|
|
|
struct thermal_attr temp;
|
|
|
|
struct thermal_attr hyst;
|
|
|
|
};
|
|
|
|
|
2024-04-02 18:57:57 +00:00
|
|
|
struct thermal_trip_desc {
|
|
|
|
struct thermal_trip trip;
|
2024-07-29 16:25:03 +00:00
|
|
|
struct thermal_trip_attrs trip_attrs;
|
2024-04-02 19:03:36 +00:00
|
|
|
struct list_head notify_list_node;
|
|
|
|
int notify_temp;
|
2024-04-02 18:57:57 +00:00
|
|
|
int threshold;
|
|
|
|
};
|
|
|
|
|
2024-04-04 19:27:07 +00:00
|
|
|
/**
|
|
|
|
* struct thermal_governor - structure that holds thermal governor information
|
|
|
|
* @name: name of the governor
|
|
|
|
* @bind_to_tz: callback called when binding to a thermal zone. If it
|
|
|
|
* returns 0, the governor is bound to the thermal zone,
|
|
|
|
* otherwise it fails.
|
|
|
|
* @unbind_from_tz: callback called when a governor is unbound from a
|
|
|
|
* thermal zone.
|
2024-04-10 16:10:53 +00:00
|
|
|
* @trip_crossed: called for trip points that have just been crossed
|
2024-04-10 16:08:12 +00:00
|
|
|
* @manage: called on thermal zone temperature updates
|
2024-04-04 19:27:07 +00:00
|
|
|
* @update_tz: callback called when thermal zone internals have changed, e.g.
|
|
|
|
* thermal cooling instance was added/removed
|
|
|
|
* @governor_list: node in thermal_governor_list (in thermal_core.c)
|
|
|
|
*/
|
|
|
|
struct thermal_governor {
|
|
|
|
const char *name;
|
|
|
|
int (*bind_to_tz)(struct thermal_zone_device *tz);
|
|
|
|
void (*unbind_from_tz)(struct thermal_zone_device *tz);
|
2024-04-10 16:10:53 +00:00
|
|
|
void (*trip_crossed)(struct thermal_zone_device *tz,
|
|
|
|
const struct thermal_trip *trip,
|
|
|
|
bool crossed_up);
|
2024-04-10 16:08:12 +00:00
|
|
|
void (*manage)(struct thermal_zone_device *tz);
|
2024-04-04 19:27:07 +00:00
|
|
|
void (*update_tz)(struct thermal_zone_device *tz,
|
|
|
|
enum thermal_notify_event reason);
|
|
|
|
struct list_head governor_list;
|
|
|
|
};
|
|
|
|
|
2024-10-04 19:11:53 +00:00
|
|
|
#define TZ_STATE_FLAG_SUSPENDED BIT(0)
|
|
|
|
#define TZ_STATE_FLAG_RESUMING BIT(1)
|
thermal: core: Mark thermal zones as initializing to start with
After thermal_zone_device_register_with_trips() has called
device_register() and it has registered the new thermal zone device
with the driver core, user space may access its sysfs attributes and,
among other things, it may enable the thermal zone before it is ready.
To address this, introduce a new thermal zone state flag for
initialization and set it before calling device_register() in
thermal_zone_device_register_with_trips(). This causes
__thermal_zone_device_update() to return early until the new flag
is cleared.
To clear it when the thermal zone is ready, introduce a new
function called thermal_zone_init_complete() that will also invoke
__thermal_zone_device_update() after clearing that flag (both under the
thernal zone lock) and make thermal_zone_device_register_with_trips()
call the new function instead of checking need_update and calling
thermal_zone_device_update() when it is set.
After this change, if user space enables the thermal zone prematurely,
__thermal_zone_device_update() will return early for it until
thermal_zone_init_complete() is called. In turn, if the thermal zone
is not enabled by user space before thermal_zone_init_complete() is
called, the __thermal_zone_device_update() call in it will return early
because the thermal zone has not been enabled yet, but that function
will be invoked again by thermal_zone_device_set_mode() when the thermal
zone is enabled and it will not return early this time.
The checking of need_update is not necessary any more because the
__thermal_zone_device_update() calls potentially triggered by cooling
device binding take place before calling thermal_zone_init_complete(),
so they all will return early, which means that
thermal_zone_init_complete() must call __thermal_zone_device_update()
in case the thermal zone is enabled prematurely by user space.
Fixes: 203d3d4aa482 ("the generic thermal sysfs driver")
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://patch.msgid.link/9360231.CDJkKcVGEf@rjwysocki.net
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
2024-10-04 19:15:04 +00:00
|
|
|
#define TZ_STATE_FLAG_INIT BIT(2)
|
2024-10-04 19:11:53 +00:00
|
|
|
|
|
|
|
#define TZ_STATE_READY 0
|
|
|
|
|
2024-04-02 18:57:57 +00:00
|
|
|
/**
|
|
|
|
* struct thermal_zone_device - structure for a thermal zone
|
|
|
|
* @id: unique id number for each thermal zone
|
|
|
|
* @type: the thermal zone device type
|
|
|
|
* @device: &struct device for this thermal zone
|
|
|
|
* @removal: removal completion
|
2024-06-14 15:22:25 +00:00
|
|
|
* @resume: resume completion
|
2024-04-02 18:57:57 +00:00
|
|
|
* @mode: current mode of this thermal zone
|
|
|
|
* @devdata: private pointer for device private data
|
|
|
|
* @num_trips: number of trip points the thermal zone supports
|
|
|
|
* @passive_delay_jiffies: number of jiffies to wait between polls when
|
|
|
|
* performing passive cooling.
|
|
|
|
* @polling_delay_jiffies: number of jiffies to wait between polls when
|
|
|
|
* checking whether trip points have been crossed (0 for
|
|
|
|
* interrupt driven systems)
|
2024-07-18 19:01:14 +00:00
|
|
|
* @recheck_delay_jiffies: delay after a failed attempt to determine the zone
|
|
|
|
* temperature before trying again
|
2024-04-02 18:57:57 +00:00
|
|
|
* @temperature: current temperature. This is only for core code,
|
|
|
|
* drivers should use thermal_zone_get_temp() to get the
|
|
|
|
* current temperature
|
|
|
|
* @last_temperature: previous temperature read
|
|
|
|
* @emul_temperature: emulated temperature when using CONFIG_THERMAL_EMULATION
|
|
|
|
* @passive: 1 if you've crossed a passive trip point, 0 otherwise.
|
|
|
|
* @prev_low_trip: the low current temperature if you've crossed a passive
|
|
|
|
trip point.
|
|
|
|
* @prev_high_trip: the above current temperature if you've crossed a
|
|
|
|
passive trip point.
|
|
|
|
* @need_update: if equals 1, thermal_zone_device_update needs to be invoked.
|
|
|
|
* @ops: operations this &thermal_zone_device supports
|
|
|
|
* @tzp: thermal zone parameters
|
|
|
|
* @governor: pointer to the governor for this thermal zone
|
|
|
|
* @governor_data: private pointer for governor data
|
|
|
|
* @thermal_instances: list of &struct thermal_instance of this thermal zone
|
|
|
|
* @ida: &struct ida to generate unique id for this zone's cooling
|
|
|
|
* devices
|
|
|
|
* @lock: lock to protect thermal_instances list
|
|
|
|
* @node: node in thermal_tz_list (in thermal_core.c)
|
|
|
|
* @poll_queue: delayed work for polling
|
|
|
|
* @notify_event: Last notification event
|
2024-10-04 19:11:53 +00:00
|
|
|
* @state: current state of the thermal zone
|
2024-04-02 18:57:57 +00:00
|
|
|
* @trips: array of struct thermal_trip objects
|
|
|
|
*/
|
|
|
|
struct thermal_zone_device {
|
|
|
|
int id;
|
|
|
|
char type[THERMAL_NAME_LENGTH];
|
|
|
|
struct device device;
|
|
|
|
struct completion removal;
|
2024-06-14 15:22:25 +00:00
|
|
|
struct completion resume;
|
2024-04-02 18:57:57 +00:00
|
|
|
struct attribute_group trips_attribute_group;
|
|
|
|
enum thermal_device_mode mode;
|
|
|
|
void *devdata;
|
|
|
|
int num_trips;
|
|
|
|
unsigned long passive_delay_jiffies;
|
|
|
|
unsigned long polling_delay_jiffies;
|
2024-07-18 19:01:14 +00:00
|
|
|
unsigned long recheck_delay_jiffies;
|
2024-04-02 18:57:57 +00:00
|
|
|
int temperature;
|
|
|
|
int last_temperature;
|
|
|
|
int emul_temperature;
|
|
|
|
int passive;
|
|
|
|
int prev_low_trip;
|
|
|
|
int prev_high_trip;
|
|
|
|
atomic_t need_update;
|
|
|
|
struct thermal_zone_device_ops ops;
|
|
|
|
struct thermal_zone_params *tzp;
|
|
|
|
struct thermal_governor *governor;
|
|
|
|
void *governor_data;
|
|
|
|
struct list_head thermal_instances;
|
|
|
|
struct ida ida;
|
|
|
|
struct mutex lock;
|
|
|
|
struct list_head node;
|
|
|
|
struct delayed_work poll_queue;
|
|
|
|
enum thermal_notify_event notify_event;
|
2024-10-04 19:11:53 +00:00
|
|
|
u8 state;
|
2024-04-02 18:57:57 +00:00
|
|
|
#ifdef CONFIG_THERMAL_DEBUGFS
|
|
|
|
struct thermal_debugfs *debugfs;
|
|
|
|
#endif
|
thermal: core: Add user thresholds support
The user thresholds mechanism is a way to have the userspace to tell
the thermal framework to send a notification when a temperature limit
is crossed. There is no id, no hysteresis, just the temperature and
the direction of the limit crossing. That means we can be notified
when a threshold is crossed the way up only, or the way down only or
both ways. That allows to create hysteresis values if it is needed.
A threshold can be added, deleted or flushed. The latter means all
thresholds belonging to a thermal zone will be deleted.
When a threshold is added:
- if the same threshold (temperature and direction) exists, an error
is returned
- if a threshold is specified with the same temperature but a
different direction, the specified direction is added
- if there is no threshold with the same temperature then it is
created
When a threshold is deleted:
- if the same threshold (temperature and direction) exists, it is
deleted
- if a threshold is specified with the same temperature but a
different direction, the specified direction is removed
- if there is no threshold with the same temperature, then an error
is returned
When the threshold are flushed:
- All thresholds related to a thermal zone are deleted
When a threshold is crossed:
- the userspace does not need to know which threshold(s) have been
crossed, it will be notified with the current temperature and the
previous temperature
- if multiple thresholds have been crossed between two updates only
one notification will be send to the userspace, it is pointless to
send a notification per thresholds crossed as the userspace can
handle that easily when it has the temperature delta information
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Link: https://patch.msgid.link/20240923100005.2532430-2-daniel.lezcano@linaro.org
[ rjw: Subject edit, use BIT(0) and BIT(1) in symbol definitions ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2024-09-23 09:59:57 +00:00
|
|
|
struct list_head user_thresholds;
|
2024-04-02 18:57:57 +00:00
|
|
|
struct thermal_trip_desc trips[] __counted_by(num_trips);
|
|
|
|
};
|
|
|
|
|
thermal: core: Allow thermal zones to tell the core to ignore them
The iwlwifi wireless driver registers a thermal zone that is only needed
when the network interface handled by it is up and it wants that thermal
zone to be effectively ignored by the core otherwise.
Before commit a8a261774466 ("thermal: core: Call monitor_thermal_zone()
if zone temperature is invalid") that could be achieved by returning
an error code from the thermal zone's .get_temp() callback because the
core did not really handle errors returned by it almost at all.
However, commit a8a261774466 made the core attempt to recover from the
situation in which the temperature of a thermal zone cannot be
determined due to errors returned by its .get_temp() and is always
invalid from the core's perspective.
That was done because there are thermal zones in which .get_temp()
returns errors to start with due to some difficulties related to the
initialization ordering, but then it will start to produce valid
temperature values at one point.
Unfortunately, the simple approach taken by commit a8a261774466,
which is to poll the thermal zone periodically until its .get_temp()
callback starts to return valid temperature values, is at odds with
the special thermal zone in iwlwifi in which .get_temp() may always
return an error because its network interface may always be down. If
that happens, every attempt to invoke the thermal zone's .get_temp()
callback resulting in an error causes the thermal core to print a
dev_warn() message to the kernel log which is super-noisy.
To address this problem, make the core handle the case in which
.get_temp() returns 0, but the temperature value returned by it
is not actually valid, in a special way. Namely, make the core
completely ignore the invalid temperature value coming from
.get_temp() in that case, which requires folding in
update_temperature() into its caller and a few related changes.
On the iwlwifi side, modify iwl_mvm_tzone_get_temp() to return 0
and put THERMAL_TEMP_INVALID into the temperature return memory
location instead of returning an error when the firmware is not
running or it is not of the right type.
Also, to clearly separate the handling of invalid temperature
values from the thermal zone initialization, introduce a special
THERMAL_TEMP_INIT value specifically for the latter purpose.
Fixes: a8a261774466 ("thermal: core: Call monitor_thermal_zone() if zone temperature is invalid")
Closes: https://lore.kernel.org/linux-pm/20240715044527.GA1544@sol.localdomain/
Reported-by: Eric Biggers <ebiggers@kernel.org>
Reported-by: Stefan Lippers-Hollmann <s.l-h@gmx.de>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=201761
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Tested-by: Stefan Lippers-Hollmann <s.l-h@gmx.de>
Cc: 6.10+ <stable@vger.kernel.org> # 6.10+
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://patch.msgid.link/4950004.31r3eYUQgx@rjwysocki.net
[ rjw: Rebased on top of the current mainline ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2024-07-17 19:45:02 +00:00
|
|
|
/* Initial thermal zone temperature. */
|
|
|
|
#define THERMAL_TEMP_INIT INT_MIN
|
|
|
|
|
2024-06-28 12:10:03 +00:00
|
|
|
/*
|
2024-07-18 19:01:14 +00:00
|
|
|
* Default and maximum delay after a failed thermal zone temperature check
|
|
|
|
* before attempting to check it again (in jiffies).
|
2024-06-28 12:10:03 +00:00
|
|
|
*/
|
2024-07-18 19:01:14 +00:00
|
|
|
#define THERMAL_RECHECK_DELAY msecs_to_jiffies(250)
|
|
|
|
#define THERMAL_MAX_RECHECK_DELAY (120 * HZ)
|
2024-06-28 12:10:03 +00:00
|
|
|
|
2020-04-02 14:27:39 +00:00
|
|
|
/* Default Thermal Governor */
|
|
|
|
#if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE)
|
|
|
|
#define DEFAULT_THERMAL_GOVERNOR "step_wise"
|
|
|
|
#elif defined(CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE)
|
|
|
|
#define DEFAULT_THERMAL_GOVERNOR "fair_share"
|
|
|
|
#elif defined(CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE)
|
|
|
|
#define DEFAULT_THERMAL_GOVERNOR "user_space"
|
|
|
|
#elif defined(CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR)
|
|
|
|
#define DEFAULT_THERMAL_GOVERNOR "power_allocator"
|
2023-06-09 12:44:08 +00:00
|
|
|
#elif defined(CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG)
|
|
|
|
#define DEFAULT_THERMAL_GOVERNOR "bang_bang"
|
2020-04-02 14:27:39 +00:00
|
|
|
#endif
|
|
|
|
|
2012-09-18 05:34:53 +00:00
|
|
|
/* Initial state of a cooling device during binding */
|
|
|
|
#define THERMAL_NO_TARGET -1UL
|
|
|
|
|
2019-06-12 20:13:24 +00:00
|
|
|
/* Init section thermal table */
|
|
|
|
extern struct thermal_governor *__governor_thermal_table[];
|
|
|
|
extern struct thermal_governor *__governor_thermal_table_end[];
|
|
|
|
|
|
|
|
#define THERMAL_TABLE_ENTRY(table, name) \
|
|
|
|
static typeof(name) *__thermal_table_entry_##name \
|
2020-10-22 02:36:07 +00:00
|
|
|
__used __section("__" #table "_thermal_table") = &name
|
2019-06-12 20:13:24 +00:00
|
|
|
|
|
|
|
#define THERMAL_GOVERNOR_DECLARE(name) THERMAL_TABLE_ENTRY(governor, name)
|
|
|
|
|
|
|
|
#define for_each_governor_table(__governor) \
|
|
|
|
for (__governor = __governor_thermal_table; \
|
|
|
|
__governor < __governor_thermal_table_end; \
|
|
|
|
__governor++)
|
|
|
|
|
2020-07-06 10:55:35 +00:00
|
|
|
int for_each_thermal_zone(int (*cb)(struct thermal_zone_device *, void *),
|
|
|
|
void *);
|
|
|
|
|
|
|
|
int for_each_thermal_cooling_device(int (*cb)(struct thermal_cooling_device *,
|
|
|
|
void *), void *);
|
|
|
|
|
|
|
|
int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *),
|
|
|
|
void *thermal_governor);
|
|
|
|
|
2020-07-06 10:55:36 +00:00
|
|
|
struct thermal_zone_device *thermal_zone_get_by_id(int id);
|
|
|
|
|
2024-10-03 12:25:58 +00:00
|
|
|
DEFINE_CLASS(thermal_zone_get_by_id, struct thermal_zone_device *,
|
|
|
|
if (_T) put_device(&_T->device), thermal_zone_get_by_id(id), int id)
|
|
|
|
|
2020-04-02 14:27:41 +00:00
|
|
|
static inline bool cdev_is_power_actor(struct thermal_cooling_device *cdev)
|
|
|
|
{
|
|
|
|
return cdev->ops->get_requested_power && cdev->ops->state2power &&
|
|
|
|
cdev->ops->power2state;
|
|
|
|
}
|
|
|
|
|
2021-01-18 17:38:24 +00:00
|
|
|
void thermal_cdev_update(struct thermal_cooling_device *);
|
2021-04-22 11:43:06 +00:00
|
|
|
void __thermal_cdev_update(struct thermal_cooling_device *cdev);
|
2021-01-18 17:38:24 +00:00
|
|
|
|
2023-10-12 18:34:50 +00:00
|
|
|
int get_tz_trend(struct thermal_zone_device *tz, const struct thermal_trip *trip);
|
2020-04-02 14:27:43 +00:00
|
|
|
|
2012-09-18 05:34:53 +00:00
|
|
|
/*
|
|
|
|
* This structure is used to describe the behavior of
|
|
|
|
* a certain cooling device on a certain trip point
|
|
|
|
* in a certain thermal zone
|
|
|
|
*/
|
|
|
|
struct thermal_instance {
|
|
|
|
int id;
|
|
|
|
char name[THERMAL_NAME_LENGTH];
|
|
|
|
struct thermal_cooling_device *cdev;
|
2023-09-21 17:52:44 +00:00
|
|
|
const struct thermal_trip *trip;
|
2015-10-30 08:31:47 +00:00
|
|
|
bool initialized;
|
2012-09-18 05:34:53 +00:00
|
|
|
unsigned long upper; /* Highest cooling state for this trip point */
|
|
|
|
unsigned long lower; /* Lowest cooling state for this trip point */
|
|
|
|
unsigned long target; /* expected cooling state */
|
|
|
|
char attr_name[THERMAL_NAME_LENGTH];
|
|
|
|
struct device_attribute attr;
|
2015-02-18 16:04:24 +00:00
|
|
|
char weight_attr_name[THERMAL_NAME_LENGTH];
|
|
|
|
struct device_attribute weight_attr;
|
2012-09-18 05:34:53 +00:00
|
|
|
struct list_head tz_node; /* node in tz->thermal_instances */
|
|
|
|
struct list_head cdev_node; /* node in cdev->thermal_instances */
|
2015-02-18 16:04:21 +00:00
|
|
|
unsigned int weight; /* The weight of the cooling device */
|
2023-03-17 17:01:26 +00:00
|
|
|
bool upper_no_limit;
|
2012-09-18 05:34:53 +00:00
|
|
|
};
|
|
|
|
|
2016-11-08 05:08:57 +00:00
|
|
|
#define to_thermal_zone(_dev) \
|
|
|
|
container_of(_dev, struct thermal_zone_device, device)
|
|
|
|
|
2016-11-08 05:09:01 +00:00
|
|
|
#define to_cooling_device(_dev) \
|
|
|
|
container_of(_dev, struct thermal_cooling_device, device)
|
|
|
|
|
2013-03-26 08:38:29 +00:00
|
|
|
int thermal_register_governor(struct thermal_governor *);
|
|
|
|
void thermal_unregister_governor(struct thermal_governor *);
|
2016-11-08 05:08:55 +00:00
|
|
|
int thermal_zone_device_set_policy(struct thermal_zone_device *, char *);
|
2016-11-08 05:08:56 +00:00
|
|
|
int thermal_build_list_of_policies(char *buf);
|
2022-11-10 15:24:58 +00:00
|
|
|
void __thermal_zone_device_update(struct thermal_zone_device *tz,
|
|
|
|
enum thermal_notify_event event);
|
2023-11-29 12:43:29 +00:00
|
|
|
void thermal_zone_device_critical_reboot(struct thermal_zone_device *tz);
|
2023-12-20 23:17:45 +00:00
|
|
|
void thermal_governor_update_tz(struct thermal_zone_device *tz,
|
|
|
|
enum thermal_notify_event reason);
|
2013-03-26 08:38:29 +00:00
|
|
|
|
2020-03-31 16:54:48 +00:00
|
|
|
/* Helpers */
|
2024-04-02 18:56:43 +00:00
|
|
|
#define for_each_trip_desc(__tz, __td) \
|
|
|
|
for (__td = __tz->trips; __td - __tz->trips < __tz->num_trips; __td++)
|
|
|
|
|
|
|
|
#define trip_to_trip_desc(__trip) \
|
|
|
|
container_of(__trip, struct thermal_trip_desc, trip)
|
2023-10-12 18:26:46 +00:00
|
|
|
|
2024-05-28 15:00:51 +00:00
|
|
|
const char *thermal_trip_type_name(enum thermal_trip_type trip_type);
|
|
|
|
|
2024-08-16 08:12:32 +00:00
|
|
|
void thermal_zone_set_trips(struct thermal_zone_device *tz, int low, int high);
|
2023-12-15 19:53:52 +00:00
|
|
|
int thermal_zone_trip_id(const struct thermal_zone_device *tz,
|
2023-09-21 17:52:44 +00:00
|
|
|
const struct thermal_trip *trip);
|
2022-08-05 15:38:34 +00:00
|
|
|
int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp);
|
2024-05-23 16:05:03 +00:00
|
|
|
void thermal_zone_trip_down(struct thermal_zone_device *tz,
|
|
|
|
const struct thermal_trip *trip);
|
2024-07-29 16:27:25 +00:00
|
|
|
void thermal_zone_set_trip_hyst(struct thermal_zone_device *tz,
|
|
|
|
struct thermal_trip *trip, int hyst);
|
2020-03-31 16:54:48 +00:00
|
|
|
|
2016-11-08 05:09:00 +00:00
|
|
|
/* sysfs I/F */
|
2024-02-22 17:30:49 +00:00
|
|
|
int thermal_zone_create_device_groups(struct thermal_zone_device *tz);
|
2017-08-08 14:39:52 +00:00
|
|
|
void thermal_zone_destroy_device_groups(struct thermal_zone_device *);
|
2016-11-08 05:09:02 +00:00
|
|
|
void thermal_cooling_device_setup_sysfs(struct thermal_cooling_device *);
|
2018-04-02 10:56:25 +00:00
|
|
|
void thermal_cooling_device_destroy_sysfs(struct thermal_cooling_device *cdev);
|
2023-03-17 17:01:26 +00:00
|
|
|
void thermal_cooling_device_stats_reinit(struct thermal_cooling_device *cdev);
|
2016-11-08 05:09:02 +00:00
|
|
|
/* used only at binding time */
|
2018-04-03 09:49:03 +00:00
|
|
|
ssize_t trip_point_show(struct device *, struct device_attribute *, char *);
|
|
|
|
ssize_t weight_show(struct device *, struct device_attribute *, char *);
|
|
|
|
ssize_t weight_store(struct device *, struct device_attribute *, const char *,
|
|
|
|
size_t);
|
2016-11-08 05:09:00 +00:00
|
|
|
|
2018-04-02 10:56:25 +00:00
|
|
|
#ifdef CONFIG_THERMAL_STATISTICS
|
|
|
|
void thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev,
|
|
|
|
unsigned long new_state);
|
|
|
|
#else
|
|
|
|
static inline void
|
|
|
|
thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev,
|
|
|
|
unsigned long new_state) {}
|
|
|
|
#endif /* CONFIG_THERMAL_STATISTICS */
|
|
|
|
|
2012-09-18 05:34:53 +00:00
|
|
|
#endif /* __THERMAL_CORE_H__ */
|