diff options
Diffstat (limited to 'drivers/thermal/thermal_core.h')
| -rw-r--r-- | drivers/thermal/thermal_core.h | 202 |
1 files changed, 178 insertions, 24 deletions
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index 17c1bbed734d..bdadd141aa24 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -9,10 +9,164 @@ #ifndef __THERMAL_CORE_H__ #define __THERMAL_CORE_H__ +#include <linux/cleanup.h> #include <linux/device.h> #include <linux/thermal.h> #include "thermal_netlink.h" +#include "thermal_thresholds.h" +#include "thermal_debugfs.h" + +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; +}; + +struct thermal_trip_desc { + struct thermal_trip trip; + struct thermal_trip_attrs trip_attrs; + struct list_head list_node; + struct list_head thermal_instances; + int threshold; +}; + +/** + * 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. + * @trip_crossed: called for trip points that have just been crossed + * @manage: called on thermal zone temperature updates + * @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); + void (*trip_crossed)(struct thermal_zone_device *tz, + const struct thermal_trip *trip, + bool upward); + void (*manage)(struct thermal_zone_device *tz); + void (*update_tz)(struct thermal_zone_device *tz, + enum thermal_notify_event reason); + struct list_head governor_list; +}; + +#define TZ_STATE_FLAG_SUSPENDED BIT(0) +#define TZ_STATE_FLAG_RESUMING BIT(1) +#define TZ_STATE_FLAG_INIT BIT(2) +#define TZ_STATE_FLAG_EXIT BIT(3) + +#define TZ_STATE_READY 0 + +/** + * 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 + * @resume: resume completion + * @trips_high: trips above the current zone temperature + * @trips_reached: trips below or at the current zone temperature + * @trips_invalid: trips with invalid temperature + * @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) + * @recheck_delay_jiffies: delay after a failed attempt to determine the zone + * temperature before trying again + * @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. + * @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 + * @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 + * @state: current state of the thermal zone + * @trips: array of struct thermal_trip objects + */ +struct thermal_zone_device { + int id; + char type[THERMAL_NAME_LENGTH]; + struct device device; + struct completion removal; + struct completion resume; + struct attribute_group trips_attribute_group; + struct list_head trips_high; + struct list_head trips_reached; + struct list_head trips_invalid; + enum thermal_device_mode mode; + void *devdata; + int num_trips; + unsigned long passive_delay_jiffies; + unsigned long polling_delay_jiffies; + unsigned long recheck_delay_jiffies; + int temperature; + int last_temperature; + int emul_temperature; + int passive; + int prev_low_trip; + int prev_high_trip; + struct thermal_zone_device_ops ops; + struct thermal_zone_params *tzp; + struct thermal_governor *governor; + void *governor_data; + struct ida ida; + struct mutex lock; + struct list_head node; + struct delayed_work poll_queue; + enum thermal_notify_event notify_event; + u8 state; +#ifdef CONFIG_THERMAL_DEBUGFS + struct thermal_debugfs *debugfs; +#endif + struct list_head user_thresholds; + struct thermal_trip_desc trips[] __counted_by(num_trips); +}; + +DEFINE_GUARD(thermal_zone, struct thermal_zone_device *, mutex_lock(&_T->lock), + mutex_unlock(&_T->lock)) + +DEFINE_GUARD(thermal_zone_reverse, struct thermal_zone_device *, + mutex_unlock(&_T->lock), mutex_lock(&_T->lock)) + +/* Initial thermal zone temperature. */ +#define THERMAL_TEMP_INIT INT_MIN + +/* + * Default and maximum delay after a failed thermal zone temperature check + * before attempting to check it again (in jiffies). + */ +#define THERMAL_RECHECK_DELAY msecs_to_jiffies(250) +#define THERMAL_MAX_RECHECK_DELAY (120 * HZ) /* Default Thermal Governor */ #if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE) @@ -54,16 +208,10 @@ int for_each_thermal_cooling_device(int (*cb)(struct thermal_cooling_device *, int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *), void *thermal_governor); -int __for_each_thermal_trip(struct thermal_zone_device *, - int (*cb)(struct thermal_trip *, void *), - void *); - struct thermal_zone_device *thermal_zone_get_by_id(int id); -struct thermal_attr { - struct device_attribute attr; - char name[THERMAL_NAME_LENGTH]; -}; +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) static inline bool cdev_is_power_actor(struct thermal_cooling_device *cdev) { @@ -72,14 +220,10 @@ static inline bool cdev_is_power_actor(struct thermal_cooling_device *cdev) } void thermal_cdev_update(struct thermal_cooling_device *); +void thermal_cdev_update_nocheck(struct thermal_cooling_device *cdev); void __thermal_cdev_update(struct thermal_cooling_device *cdev); -int get_tz_trend(struct thermal_zone_device *tz, int trip); - -struct thermal_instance * -get_thermal_instance(struct thermal_zone_device *tz, - struct thermal_cooling_device *cdev, - int trip); +int get_tz_trend(struct thermal_zone_device *tz, const struct thermal_trip *trip); /* * This structure is used to describe the behavior of @@ -89,9 +233,8 @@ get_thermal_instance(struct thermal_zone_device *tz, struct thermal_instance { int id; char name[THERMAL_NAME_LENGTH]; - struct thermal_zone_device *tz; struct thermal_cooling_device *cdev; - int trip; + const struct thermal_trip *trip; bool initialized; unsigned long upper; /* Highest cooling state for this trip point */ unsigned long lower; /* Lowest cooling state for this trip point */ @@ -100,7 +243,7 @@ struct thermal_instance { struct device_attribute attr; char weight_attr_name[THERMAL_NAME_LENGTH]; struct device_attribute weight_attr; - struct list_head tz_node; /* node in tz->thermal_instances */ + struct list_head trip_node; /* node in trip->thermal_instances */ struct list_head cdev_node; /* node in cdev->thermal_instances */ unsigned int weight; /* The weight of the cooling device */ bool upper_no_limit; @@ -118,15 +261,29 @@ int thermal_zone_device_set_policy(struct thermal_zone_device *, char *); int thermal_build_list_of_policies(char *buf); void __thermal_zone_device_update(struct thermal_zone_device *tz, enum thermal_notify_event event); +void thermal_zone_device_critical_reboot(struct thermal_zone_device *tz); +void thermal_zone_device_critical_shutdown(struct thermal_zone_device *tz); +void thermal_governor_update_tz(struct thermal_zone_device *tz, + enum thermal_notify_event reason); /* Helpers */ -void __thermal_zone_set_trips(struct thermal_zone_device *tz); -int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id, - struct thermal_trip *trip); +#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) + +const char *thermal_trip_type_name(enum thermal_trip_type trip_type); + +void thermal_zone_set_trips(struct thermal_zone_device *tz, int low, int high); +int thermal_zone_trip_id(const struct thermal_zone_device *tz, + const struct thermal_trip *trip); int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp); +void thermal_zone_set_trip_hyst(struct thermal_zone_device *tz, + struct thermal_trip *trip, int hyst); /* sysfs I/F */ -int thermal_zone_create_device_groups(struct thermal_zone_device *, int); +int thermal_zone_create_device_groups(struct thermal_zone_device *tz); void thermal_zone_destroy_device_groups(struct thermal_zone_device *); void thermal_cooling_device_setup_sysfs(struct thermal_cooling_device *); void thermal_cooling_device_destroy_sysfs(struct thermal_cooling_device *cdev); @@ -146,7 +303,4 @@ thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev, unsigned long new_state) {} #endif /* CONFIG_THERMAL_STATISTICS */ -/* device tree support */ -int thermal_zone_device_is_enabled(struct thermal_zone_device *tz); - #endif /* __THERMAL_CORE_H__ */ |
