diff options
Diffstat (limited to 'drivers/thermal/thermal_core.h')
-rw-r--r-- | drivers/thermal/thermal_core.h | 188 |
1 files changed, 168 insertions, 20 deletions
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index e9c099ecdd0f..09866f0ce765 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -9,12 +9,165 @@ #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) #define DEFAULT_THERMAL_GOVERNOR "step_wise" @@ -57,10 +210,8 @@ int for_each_thermal_governor(int (*cb)(struct thermal_governor *, 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) { @@ -69,15 +220,11 @@ 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, const struct thermal_trip *trip); -struct thermal_instance * -get_thermal_instance(struct thermal_zone_device *tz, - struct thermal_cooling_device *cdev, - int trip); - /* * This structure is used to describe the behavior of * a certain cooling device on a certain trip point @@ -86,7 +233,6 @@ 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; const struct thermal_trip *trip; bool initialized; @@ -97,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; @@ -120,18 +266,23 @@ void thermal_governor_update_tz(struct thermal_zone_device *tz, enum thermal_notify_event reason); /* Helpers */ -#define for_each_trip(__tz, __trip) \ - for (__trip = __tz->trips; __trip - __tz->trips < __tz->num_trips; __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) -void __thermal_zone_set_trips(struct thermal_zone_device *tz); +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); -void thermal_zone_trip_updated(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); @@ -151,7 +302,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__ */ |