Merge back thermal core material for 6.12.

This commit is contained in:
Rafael J. Wysocki 2024-08-19 14:42:19 +02:00
commit 5ae98b5a9f
12 changed files with 151 additions and 265 deletions

View File

@ -459,14 +459,7 @@ are supposed to implement the callback. If they don't, the thermal
framework calculated the trend by comparing the previous and the current framework calculated the trend by comparing the previous and the current
temperature values. temperature values.
4.2. get_thermal_instance 4.2. thermal_cdev_update
-------------------------
This function returns the thermal_instance corresponding to a given
{thermal_zone, cooling_device, trip_point} combination. Returns NULL
if such an instance does not exist.
4.3. thermal_cdev_update
------------------------ ------------------------
This function serves as an arbitrator to set the state of a cooling This function serves as an arbitrator to set the state of a cooling

View File

@ -208,8 +208,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
*/ */
val = readl(data->regs + BCM2835_TS_TSENSCTL); val = readl(data->regs + BCM2835_TS_TSENSCTL);
if (!(val & BCM2835_TS_TSENSCTL_RSTB)) { if (!(val & BCM2835_TS_TSENSCTL_RSTB)) {
struct thermal_trip trip; int offset, slope, crit_temp;
int offset, slope;
slope = thermal_zone_get_slope(tz); slope = thermal_zone_get_slope(tz);
offset = thermal_zone_get_offset(tz); offset = thermal_zone_get_offset(tz);
@ -217,7 +216,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
* For now we deal only with critical, otherwise * For now we deal only with critical, otherwise
* would need to iterate * would need to iterate
*/ */
err = thermal_zone_get_trip(tz, 0, &trip); err = thermal_zone_get_crit_temp(tz, &crit_temp);
if (err < 0) { if (err < 0) {
dev_err(dev, "Not able to read trip_temp: %d\n", err); dev_err(dev, "Not able to read trip_temp: %d\n", err);
return err; return err;
@ -232,7 +231,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
val |= (0xFE << BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT); val |= (0xFE << BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT);
/* trip_adc value from info */ /* trip_adc value from info */
val |= bcm2835_thermal_temp2adc(trip.temperature, val |= bcm2835_thermal_temp2adc(crit_temp,
offset, offset,
slope) slope)
<< BCM2835_TS_TSENSCTL_THOLD_SHIFT; << BCM2835_TS_TSENSCTL_THOLD_SHIFT;

View File

@ -465,11 +465,22 @@ static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int hisi_trip_walk_cb(struct thermal_trip *trip, void *arg)
{
struct hisi_thermal_sensor *sensor = arg;
if (trip->type != THERMAL_TRIP_PASSIVE)
return 0;
sensor->thres_temp = trip->temperature;
/* Return nonzero to terminate the search. */
return 1;
}
static int hisi_thermal_register_sensor(struct platform_device *pdev, static int hisi_thermal_register_sensor(struct platform_device *pdev,
struct hisi_thermal_sensor *sensor) struct hisi_thermal_sensor *sensor)
{ {
int ret, i; int ret;
struct thermal_trip trip;
sensor->tzd = devm_thermal_of_zone_register(&pdev->dev, sensor->tzd = devm_thermal_of_zone_register(&pdev->dev,
sensor->id, sensor, sensor->id, sensor,
@ -482,15 +493,7 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev,
return ret; return ret;
} }
for (i = 0; i < thermal_zone_get_num_trips(sensor->tzd); i++) { thermal_zone_for_each_trip(sensor->tzd, hisi_trip_walk_cb, sensor);
thermal_zone_get_trip(sensor->tzd, i, &trip);
if (trip.type == THERMAL_TRIP_PASSIVE) {
sensor->thres_temp = trip.temperature;
break;
}
}
return 0; return 0;
} }

View File

@ -291,24 +291,6 @@ static irqreturn_t qpnp_tm_isr(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int qpnp_tm_get_critical_trip_temp(struct qpnp_tm_chip *chip)
{
struct thermal_trip trip;
int i, ret;
for (i = 0; i < thermal_zone_get_num_trips(chip->tz_dev); i++) {
ret = thermal_zone_get_trip(chip->tz_dev, i, &trip);
if (ret)
continue;
if (trip.type == THERMAL_TRIP_CRITICAL)
return trip.temperature;
}
return THERMAL_TEMP_INVALID;
}
/* /*
* This function initializes the internal temp value based on only the * This function initializes the internal temp value based on only the
* current thermal stage and threshold. Setup threshold control and * current thermal stage and threshold. Setup threshold control and
@ -343,7 +325,9 @@ static int qpnp_tm_init(struct qpnp_tm_chip *chip)
mutex_unlock(&chip->lock); mutex_unlock(&chip->lock);
crit_temp = qpnp_tm_get_critical_trip_temp(chip); ret = thermal_zone_get_crit_temp(chip->tz_dev, &crit_temp);
if (ret)
crit_temp = THERMAL_TEMP_INVALID;
mutex_lock(&chip->lock); mutex_lock(&chip->lock);

View File

@ -563,11 +563,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
if (ret) if (ret)
goto error_unregister; goto error_unregister;
ret = thermal_zone_get_num_trips(tsc->zone); dev_info(dev, "Sensor %u: Loaded\n", i);
if (ret < 0)
goto error_unregister;
dev_info(dev, "Sensor %u: Loaded %d trip points\n", i, ret);
} }
if (!priv->num_tscs) { if (!priv->num_tscs) {

View File

@ -682,24 +682,25 @@ static const struct thermal_zone_device_ops tegra_of_thermal_ops = {
.set_trips = tegra_thermctl_set_trips, .set_trips = tegra_thermctl_set_trips,
}; };
static int get_hot_temp(struct thermal_zone_device *tz, int *trip_id, int *temp) static int get_hot_trip_cb(struct thermal_trip *trip, void *arg)
{ {
int i, ret; const struct thermal_trip **trip_ret = arg;
struct thermal_trip trip;
for (i = 0; i < thermal_zone_get_num_trips(tz); i++) { if (trip->type != THERMAL_TRIP_HOT)
return 0;
ret = thermal_zone_get_trip(tz, i, &trip); *trip_ret = trip;
if (ret) /* Return nonzero to terminate the search. */
return -EINVAL; return 1;
}
if (trip.type == THERMAL_TRIP_HOT) { static const struct thermal_trip *get_hot_trip(struct thermal_zone_device *tz)
*trip_id = i; {
return 0; const struct thermal_trip *trip = NULL;
}
}
return -EINVAL; thermal_zone_for_each_trip(tz, get_hot_trip_cb, &trip);
return trip;
} }
/** /**
@ -731,8 +732,9 @@ static int tegra_soctherm_set_hwtrips(struct device *dev,
struct thermal_zone_device *tz) struct thermal_zone_device *tz)
{ {
struct tegra_soctherm *ts = dev_get_drvdata(dev); struct tegra_soctherm *ts = dev_get_drvdata(dev);
const struct thermal_trip *hot_trip;
struct soctherm_throt_cfg *stc; struct soctherm_throt_cfg *stc;
int i, trip, temperature, ret; int i, temperature, ret;
/* Get thermtrips. If missing, try to get critical trips. */ /* Get thermtrips. If missing, try to get critical trips. */
temperature = tsensor_group_thermtrip_get(ts, sg->id); temperature = tsensor_group_thermtrip_get(ts, sg->id);
@ -749,8 +751,8 @@ static int tegra_soctherm_set_hwtrips(struct device *dev,
dev_info(dev, "thermtrip: will shut down when %s reaches %d mC\n", dev_info(dev, "thermtrip: will shut down when %s reaches %d mC\n",
sg->name, temperature); sg->name, temperature);
ret = get_hot_temp(tz, &trip, &temperature); hot_trip = get_hot_trip(tz);
if (ret) { if (!hot_trip) {
dev_info(dev, "throttrip: %s: missing hot temperature\n", dev_info(dev, "throttrip: %s: missing hot temperature\n",
sg->name); sg->name);
return 0; return 0;
@ -763,7 +765,7 @@ static int tegra_soctherm_set_hwtrips(struct device *dev,
continue; continue;
cdev = ts->throt_cfgs[i].cdev; cdev = ts->throt_cfgs[i].cdev;
if (get_thermal_instance(tz, cdev, trip)) if (thermal_trip_is_bound_to_cdev(tz, hot_trip, cdev))
stc = find_throttle_cfg_by_name(ts, cdev->type); stc = find_throttle_cfg_by_name(ts, cdev->type);
else else
continue; continue;

View File

@ -303,33 +303,37 @@ stop_channel:
return 0; return 0;
} }
static void tegra_tsensor_get_hw_channel_trips(struct thermal_zone_device *tzd, struct trip_temps {
int *hot_trip, int *crit_trip) int hot_trip;
{ int crit_trip;
unsigned int i; };
static int tegra_tsensor_get_trips_cb(struct thermal_trip *trip, void *arg)
{
struct trip_temps *temps = arg;
if (trip->type == THERMAL_TRIP_HOT)
temps->hot_trip = trip->temperature;
else if (trip->type == THERMAL_TRIP_CRITICAL)
temps->crit_trip = trip->temperature;
return 0;
}
static void tegra_tsensor_get_hw_channel_trips(struct thermal_zone_device *tzd,
struct trip_temps *temps)
{
/* /*
* 90C is the maximal critical temperature of all Tegra30 SoC variants, * 90C is the maximal critical temperature of all Tegra30 SoC variants,
* use it for the default trip if unspecified in a device-tree. * use it for the default trip if unspecified in a device-tree.
*/ */
*hot_trip = 85000; temps->hot_trip = 85000;
*crit_trip = 90000; temps->crit_trip = 90000;
for (i = 0; i < thermal_zone_get_num_trips(tzd); i++) { thermal_zone_for_each_trip(tzd, tegra_tsensor_get_trips_cb, temps);
struct thermal_trip trip;
thermal_zone_get_trip(tzd, i, &trip);
if (trip.type == THERMAL_TRIP_HOT)
*hot_trip = trip.temperature;
if (trip.type == THERMAL_TRIP_CRITICAL)
*crit_trip = trip.temperature;
}
/* clamp hardware trips to the calibration limits */ /* clamp hardware trips to the calibration limits */
*hot_trip = clamp(*hot_trip, 25000, 90000); temps->hot_trip = clamp(temps->hot_trip, 25000, 90000);
/* /*
* Kernel will perform a normal system shut down if it will * Kernel will perform a normal system shut down if it will
@ -338,7 +342,7 @@ static void tegra_tsensor_get_hw_channel_trips(struct thermal_zone_device *tzd,
* shut down gracefully before sending signal to the Power * shut down gracefully before sending signal to the Power
* Management controller. * Management controller.
*/ */
*crit_trip = clamp(*crit_trip + 5000, 25000, 90000); temps->crit_trip = clamp(temps->crit_trip + 5000, 25000, 90000);
} }
static int tegra_tsensor_enable_hw_channel(const struct tegra_tsensor *ts, static int tegra_tsensor_enable_hw_channel(const struct tegra_tsensor *ts,
@ -346,7 +350,8 @@ static int tegra_tsensor_enable_hw_channel(const struct tegra_tsensor *ts,
{ {
const struct tegra_tsensor_channel *tsc = &ts->ch[id]; const struct tegra_tsensor_channel *tsc = &ts->ch[id];
struct thermal_zone_device *tzd = tsc->tzd; struct thermal_zone_device *tzd = tsc->tzd;
int err, hot_trip = 0, crit_trip = 0; struct trip_temps temps = { 0 };
int err;
u32 val; u32 val;
if (!tzd) { if (!tzd) {
@ -357,24 +362,24 @@ static int tegra_tsensor_enable_hw_channel(const struct tegra_tsensor *ts,
return 0; return 0;
} }
tegra_tsensor_get_hw_channel_trips(tzd, &hot_trip, &crit_trip); tegra_tsensor_get_hw_channel_trips(tzd, &temps);
dev_info_once(ts->dev, "ch%u: PMC emergency shutdown trip set to %dC\n", dev_info_once(ts->dev, "ch%u: PMC emergency shutdown trip set to %dC\n",
id, DIV_ROUND_CLOSEST(crit_trip, 1000)); id, DIV_ROUND_CLOSEST(temps.crit_trip, 1000));
hot_trip = tegra_tsensor_temp_to_counter(ts, hot_trip); temps.hot_trip = tegra_tsensor_temp_to_counter(ts, temps.hot_trip);
crit_trip = tegra_tsensor_temp_to_counter(ts, crit_trip); temps.crit_trip = tegra_tsensor_temp_to_counter(ts, temps.crit_trip);
/* program LEVEL2 counter threshold */ /* program LEVEL2 counter threshold */
val = readl_relaxed(tsc->regs + TSENSOR_SENSOR0_CONFIG1); val = readl_relaxed(tsc->regs + TSENSOR_SENSOR0_CONFIG1);
val &= ~TSENSOR_SENSOR0_CONFIG1_TH2; val &= ~TSENSOR_SENSOR0_CONFIG1_TH2;
val |= FIELD_PREP(TSENSOR_SENSOR0_CONFIG1_TH2, hot_trip); val |= FIELD_PREP(TSENSOR_SENSOR0_CONFIG1_TH2, temps.hot_trip);
writel_relaxed(val, tsc->regs + TSENSOR_SENSOR0_CONFIG1); writel_relaxed(val, tsc->regs + TSENSOR_SENSOR0_CONFIG1);
/* program LEVEL3 counter threshold */ /* program LEVEL3 counter threshold */
val = readl_relaxed(tsc->regs + TSENSOR_SENSOR0_CONFIG2); val = readl_relaxed(tsc->regs + TSENSOR_SENSOR0_CONFIG2);
val &= ~TSENSOR_SENSOR0_CONFIG2_TH3; val &= ~TSENSOR_SENSOR0_CONFIG2_TH3;
val |= FIELD_PREP(TSENSOR_SENSOR0_CONFIG2_TH3, crit_trip); val |= FIELD_PREP(TSENSOR_SENSOR0_CONFIG2_TH3, temps.crit_trip);
writel_relaxed(val, tsc->regs + TSENSOR_SENSOR0_CONFIG2); writel_relaxed(val, tsc->regs + TSENSOR_SENSOR0_CONFIG2);
/* /*

View File

@ -15,8 +15,20 @@
#include "thermal_netlink.h" #include "thermal_netlink.h"
#include "thermal_debugfs.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_desc {
struct thermal_trip trip; struct thermal_trip trip;
struct thermal_trip_attrs trip_attrs;
struct list_head notify_list_node; struct list_head notify_list_node;
int notify_temp; int notify_temp;
int threshold; int threshold;
@ -56,9 +68,6 @@ struct thermal_governor {
* @device: &struct device for this thermal zone * @device: &struct device for this thermal zone
* @removal: removal completion * @removal: removal completion
* @resume: resume completion * @resume: resume completion
* @trip_temp_attrs: attributes for trip points for sysfs: trip temperature
* @trip_type_attrs: attributes for trip points for sysfs: trip type
* @trip_hyst_attrs: attributes for trip points for sysfs: trip hysteresis
* @mode: current mode of this thermal zone * @mode: current mode of this thermal zone
* @devdata: private pointer for device private data * @devdata: private pointer for device private data
* @num_trips: number of trip points the thermal zone supports * @num_trips: number of trip points the thermal zone supports
@ -102,9 +111,6 @@ struct thermal_zone_device {
struct completion removal; struct completion removal;
struct completion resume; struct completion resume;
struct attribute_group trips_attribute_group; struct attribute_group trips_attribute_group;
struct thermal_attr *trip_temp_attrs;
struct thermal_attr *trip_type_attrs;
struct thermal_attr *trip_hyst_attrs;
enum thermal_device_mode mode; enum thermal_device_mode mode;
void *devdata; void *devdata;
int num_trips; int num_trips;
@ -188,11 +194,6 @@ int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *),
struct thermal_zone_device *thermal_zone_get_by_id(int id); struct thermal_zone_device *thermal_zone_get_by_id(int id);
struct thermal_attr {
struct device_attribute attr;
char name[THERMAL_NAME_LENGTH];
};
static inline bool cdev_is_power_actor(struct thermal_cooling_device *cdev) static inline bool cdev_is_power_actor(struct thermal_cooling_device *cdev)
{ {
return cdev->ops->get_requested_power && cdev->ops->state2power && return cdev->ops->get_requested_power && cdev->ops->state2power &&
@ -204,11 +205,6 @@ void __thermal_cdev_update(struct thermal_cooling_device *cdev);
int get_tz_trend(struct thermal_zone_device *tz, const struct thermal_trip *trip); 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 * This structure is used to describe the behavior of
* a certain cooling device on a certain trip point * a certain cooling device on a certain trip point
@ -262,11 +258,11 @@ const char *thermal_trip_type_name(enum thermal_trip_type trip_type);
void thermal_zone_set_trips(struct thermal_zone_device *tz); void thermal_zone_set_trips(struct thermal_zone_device *tz);
int thermal_zone_trip_id(const struct thermal_zone_device *tz, int thermal_zone_trip_id(const struct thermal_zone_device *tz,
const struct thermal_trip *trip); 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); int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp);
void thermal_zone_trip_down(struct thermal_zone_device *tz, void thermal_zone_trip_down(struct thermal_zone_device *tz,
const struct thermal_trip *trip); const struct thermal_trip *trip);
void thermal_zone_set_trip_hyst(struct thermal_zone_device *tz,
struct thermal_trip *trip, int hyst);
/* sysfs I/F */ /* sysfs I/F */
int thermal_zone_create_device_groups(struct thermal_zone_device *tz); int thermal_zone_create_device_groups(struct thermal_zone_device *tz);

View File

@ -39,18 +39,18 @@ int get_tz_trend(struct thermal_zone_device *tz, const struct thermal_trip *trip
return trend; return trend;
} }
static struct thermal_instance *get_instance(struct thermal_zone_device *tz, static bool thermal_instance_present(struct thermal_zone_device *tz,
struct thermal_cooling_device *cdev, struct thermal_cooling_device *cdev,
const struct thermal_trip *trip) const struct thermal_trip *trip)
{ {
struct thermal_instance *ti; struct thermal_instance *ti;
list_for_each_entry(ti, &tz->thermal_instances, tz_node) { list_for_each_entry(ti, &tz->thermal_instances, tz_node) {
if (ti->trip == trip && ti->cdev == cdev) if (ti->trip == trip && ti->cdev == cdev)
return ti; return true;
} }
return NULL; return false;
} }
bool thermal_trip_is_bound_to_cdev(struct thermal_zone_device *tz, bool thermal_trip_is_bound_to_cdev(struct thermal_zone_device *tz,
@ -62,7 +62,7 @@ bool thermal_trip_is_bound_to_cdev(struct thermal_zone_device *tz,
mutex_lock(&tz->lock); mutex_lock(&tz->lock);
mutex_lock(&cdev->lock); mutex_lock(&cdev->lock);
ret = !!get_instance(tz, cdev, trip); ret = thermal_instance_present(tz, cdev, trip);
mutex_unlock(&cdev->lock); mutex_unlock(&cdev->lock);
mutex_unlock(&tz->lock); mutex_unlock(&tz->lock);
@ -71,24 +71,6 @@ bool thermal_trip_is_bound_to_cdev(struct thermal_zone_device *tz,
} }
EXPORT_SYMBOL_GPL(thermal_trip_is_bound_to_cdev); EXPORT_SYMBOL_GPL(thermal_trip_is_bound_to_cdev);
struct thermal_instance *
get_thermal_instance(struct thermal_zone_device *tz,
struct thermal_cooling_device *cdev, int trip_index)
{
struct thermal_instance *ti;
mutex_lock(&tz->lock);
mutex_lock(&cdev->lock);
ti = get_instance(tz, cdev, &tz->trips[trip_index].trip);
mutex_unlock(&cdev->lock);
mutex_unlock(&tz->lock);
return ti;
}
EXPORT_SYMBOL(get_thermal_instance);
/** /**
* __thermal_zone_get_temp() - returns the temperature of a thermal zone * __thermal_zone_get_temp() - returns the temperature of a thermal zone
* @tz: a valid pointer to a struct thermal_zone_device * @tz: a valid pointer to a struct thermal_zone_device

View File

@ -12,6 +12,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/container_of.h>
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/err.h> #include <linux/err.h>
@ -78,39 +79,38 @@ mode_store(struct device *dev, struct device_attribute *attr,
return count; return count;
} }
#define thermal_trip_of_attr(_ptr_, _attr_) \
({ \
struct thermal_trip_desc *td; \
\
td = container_of(_ptr_, struct thermal_trip_desc, \
trip_attrs._attr_.attr); \
&td->trip; \
})
static ssize_t static ssize_t
trip_point_type_show(struct device *dev, struct device_attribute *attr, trip_point_type_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct thermal_zone_device *tz = to_thermal_zone(dev); struct thermal_trip *trip = thermal_trip_of_attr(attr, type);
int trip_id;
if (sscanf(attr->attr.name, "trip_point_%d_type", &trip_id) != 1) return sprintf(buf, "%s\n", thermal_trip_type_name(trip->type));
return -EINVAL;
return sprintf(buf, "%s\n", thermal_trip_type_name(tz->trips[trip_id].trip.type));
} }
static ssize_t static ssize_t
trip_point_temp_store(struct device *dev, struct device_attribute *attr, trip_point_temp_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct thermal_trip *trip = thermal_trip_of_attr(attr, temp);
struct thermal_zone_device *tz = to_thermal_zone(dev); struct thermal_zone_device *tz = to_thermal_zone(dev);
struct thermal_trip *trip; int ret, temp;
int trip_id, ret;
int temp;
ret = kstrtoint(buf, 10, &temp); ret = kstrtoint(buf, 10, &temp);
if (ret) if (ret)
return -EINVAL; return -EINVAL;
if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip_id) != 1)
return -EINVAL;
mutex_lock(&tz->lock); mutex_lock(&tz->lock);
trip = &tz->trips[trip_id].trip;
if (temp != trip->temperature) { if (temp != trip->temperature) {
if (tz->ops.set_trip_temp) { if (tz->ops.set_trip_temp) {
ret = tz->ops.set_trip_temp(tz, trip, temp); ret = tz->ops.set_trip_temp(tz, trip, temp);
@ -133,39 +133,29 @@ static ssize_t
trip_point_temp_show(struct device *dev, struct device_attribute *attr, trip_point_temp_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct thermal_zone_device *tz = to_thermal_zone(dev); struct thermal_trip *trip = thermal_trip_of_attr(attr, temp);
int trip_id;
if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip_id) != 1) return sprintf(buf, "%d\n", READ_ONCE(trip->temperature));
return -EINVAL;
return sprintf(buf, "%d\n", READ_ONCE(tz->trips[trip_id].trip.temperature));
} }
static ssize_t static ssize_t
trip_point_hyst_store(struct device *dev, struct device_attribute *attr, trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct thermal_trip *trip = thermal_trip_of_attr(attr, hyst);
struct thermal_zone_device *tz = to_thermal_zone(dev); struct thermal_zone_device *tz = to_thermal_zone(dev);
struct thermal_trip *trip; int ret, hyst;
int trip_id, ret;
int hyst;
ret = kstrtoint(buf, 10, &hyst); ret = kstrtoint(buf, 10, &hyst);
if (ret || hyst < 0) if (ret || hyst < 0)
return -EINVAL; return -EINVAL;
if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip_id) != 1)
return -EINVAL;
mutex_lock(&tz->lock); mutex_lock(&tz->lock);
trip = &tz->trips[trip_id].trip;
if (hyst != trip->hysteresis) { if (hyst != trip->hysteresis) {
WRITE_ONCE(trip->hysteresis, hyst); thermal_zone_set_trip_hyst(tz, trip, hyst);
thermal_zone_trip_updated(tz, trip); __thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED);
} }
mutex_unlock(&tz->lock); mutex_unlock(&tz->lock);
@ -177,13 +167,9 @@ static ssize_t
trip_point_hyst_show(struct device *dev, struct device_attribute *attr, trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct thermal_zone_device *tz = to_thermal_zone(dev); struct thermal_trip *trip = thermal_trip_of_attr(attr, hyst);
int trip_id;
if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip_id) != 1) return sprintf(buf, "%d\n", READ_ONCE(trip->hysteresis));
return -EINVAL;
return sprintf(buf, "%d\n", READ_ONCE(tz->trips[trip_id].trip.hysteresis));
} }
static ssize_t static ssize_t
@ -382,87 +368,55 @@ static const struct attribute_group *thermal_zone_attribute_groups[] = {
*/ */
static int create_trip_attrs(struct thermal_zone_device *tz) static int create_trip_attrs(struct thermal_zone_device *tz)
{ {
const struct thermal_trip_desc *td; struct thermal_trip_desc *td;
struct attribute **attrs; struct attribute **attrs;
int i;
/* This function works only for zones with at least one trip */
if (tz->num_trips <= 0)
return -EINVAL;
tz->trip_type_attrs = kcalloc(tz->num_trips, sizeof(*tz->trip_type_attrs),
GFP_KERNEL);
if (!tz->trip_type_attrs)
return -ENOMEM;
tz->trip_temp_attrs = kcalloc(tz->num_trips, sizeof(*tz->trip_temp_attrs),
GFP_KERNEL);
if (!tz->trip_temp_attrs) {
kfree(tz->trip_type_attrs);
return -ENOMEM;
}
tz->trip_hyst_attrs = kcalloc(tz->num_trips,
sizeof(*tz->trip_hyst_attrs),
GFP_KERNEL);
if (!tz->trip_hyst_attrs) {
kfree(tz->trip_type_attrs);
kfree(tz->trip_temp_attrs);
return -ENOMEM;
}
attrs = kcalloc(tz->num_trips * 3 + 1, sizeof(*attrs), GFP_KERNEL); attrs = kcalloc(tz->num_trips * 3 + 1, sizeof(*attrs), GFP_KERNEL);
if (!attrs) { if (!attrs)
kfree(tz->trip_type_attrs);
kfree(tz->trip_temp_attrs);
kfree(tz->trip_hyst_attrs);
return -ENOMEM; return -ENOMEM;
}
i = 0;
for_each_trip_desc(tz, td) { for_each_trip_desc(tz, td) {
int indx = thermal_zone_trip_id(tz, &td->trip); struct thermal_trip_attrs *trip_attrs = &td->trip_attrs;
/* create trip type attribute */ /* create trip type attribute */
snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH, snprintf(trip_attrs->type.name, THERMAL_NAME_LENGTH,
"trip_point_%d_type", indx); "trip_point_%d_type", i);
sysfs_attr_init(&tz->trip_type_attrs[indx].attr.attr); sysfs_attr_init(&trip_attrs->type.attr.attr);
tz->trip_type_attrs[indx].attr.attr.name = trip_attrs->type.attr.attr.name = trip_attrs->type.name;
tz->trip_type_attrs[indx].name; trip_attrs->type.attr.attr.mode = S_IRUGO;
tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO; trip_attrs->type.attr.show = trip_point_type_show;
tz->trip_type_attrs[indx].attr.show = trip_point_type_show; attrs[i] = &trip_attrs->type.attr.attr;
attrs[indx] = &tz->trip_type_attrs[indx].attr.attr;
/* create trip temp attribute */ /* create trip temp attribute */
snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH, snprintf(trip_attrs->temp.name, THERMAL_NAME_LENGTH,
"trip_point_%d_temp", indx); "trip_point_%d_temp", i);
sysfs_attr_init(&tz->trip_temp_attrs[indx].attr.attr); sysfs_attr_init(&trip_attrs->temp.attr.attr);
tz->trip_temp_attrs[indx].attr.attr.name = trip_attrs->temp.attr.attr.name = trip_attrs->temp.name;
tz->trip_temp_attrs[indx].name; trip_attrs->temp.attr.attr.mode = S_IRUGO;
tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO; trip_attrs->temp.attr.show = trip_point_temp_show;
tz->trip_temp_attrs[indx].attr.show = trip_point_temp_show;
if (td->trip.flags & THERMAL_TRIP_FLAG_RW_TEMP) { if (td->trip.flags & THERMAL_TRIP_FLAG_RW_TEMP) {
tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR; trip_attrs->temp.attr.attr.mode |= S_IWUSR;
tz->trip_temp_attrs[indx].attr.store = trip_attrs->temp.attr.store = trip_point_temp_store;
trip_point_temp_store;
} }
attrs[indx + tz->num_trips] = &tz->trip_temp_attrs[indx].attr.attr; attrs[i + tz->num_trips] = &trip_attrs->temp.attr.attr;
snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH, snprintf(trip_attrs->hyst.name, THERMAL_NAME_LENGTH,
"trip_point_%d_hyst", indx); "trip_point_%d_hyst", i);
sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr); sysfs_attr_init(&trip_attrs->hyst.attr.attr);
tz->trip_hyst_attrs[indx].attr.attr.name = trip_attrs->hyst.attr.attr.name = trip_attrs->hyst.name;
tz->trip_hyst_attrs[indx].name; trip_attrs->hyst.attr.attr.mode = S_IRUGO;
tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO; trip_attrs->hyst.attr.show = trip_point_hyst_show;
tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show;
if (td->trip.flags & THERMAL_TRIP_FLAG_RW_HYST) { if (td->trip.flags & THERMAL_TRIP_FLAG_RW_HYST) {
tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR; trip_attrs->hyst.attr.attr.mode |= S_IWUSR;
tz->trip_hyst_attrs[indx].attr.store = trip_attrs->hyst.attr.store = trip_point_hyst_store;
trip_point_hyst_store;
} }
attrs[indx + tz->num_trips * 2] = attrs[i + 2 * tz->num_trips] = &trip_attrs->hyst.attr.attr;
&tz->trip_hyst_attrs[indx].attr.attr; i++;
} }
attrs[tz->num_trips * 3] = NULL; attrs[tz->num_trips * 3] = NULL;
@ -479,13 +433,8 @@ static int create_trip_attrs(struct thermal_zone_device *tz)
*/ */
static void destroy_trip_attrs(struct thermal_zone_device *tz) static void destroy_trip_attrs(struct thermal_zone_device *tz)
{ {
if (!tz) if (tz)
return; kfree(tz->trips_attribute_group.attrs);
kfree(tz->trip_type_attrs);
kfree(tz->trip_temp_attrs);
kfree(tz->trip_hyst_attrs);
kfree(tz->trips_attribute_group.attrs);
} }
int thermal_zone_create_device_groups(struct thermal_zone_device *tz) int thermal_zone_create_device_groups(struct thermal_zone_device *tz)

View File

@ -55,12 +55,6 @@ int thermal_zone_for_each_trip(struct thermal_zone_device *tz,
} }
EXPORT_SYMBOL_GPL(thermal_zone_for_each_trip); EXPORT_SYMBOL_GPL(thermal_zone_for_each_trip);
int thermal_zone_get_num_trips(struct thermal_zone_device *tz)
{
return tz->num_trips;
}
EXPORT_SYMBOL_GPL(thermal_zone_get_num_trips);
/** /**
* thermal_zone_set_trips - Computes the next trip points for the driver * thermal_zone_set_trips - Computes the next trip points for the driver
* @tz: a pointer to a thermal zone device structure * @tz: a pointer to a thermal zone device structure
@ -114,20 +108,6 @@ void thermal_zone_set_trips(struct thermal_zone_device *tz)
dev_err(&tz->device, "Failed to set trips: %d\n", ret); dev_err(&tz->device, "Failed to set trips: %d\n", ret);
} }
int thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
struct thermal_trip *trip)
{
if (!tz || !trip || trip_id < 0 || trip_id >= tz->num_trips)
return -EINVAL;
mutex_lock(&tz->lock);
*trip = tz->trips[trip_id].trip;
mutex_unlock(&tz->lock);
return 0;
}
EXPORT_SYMBOL_GPL(thermal_zone_get_trip);
int thermal_zone_trip_id(const struct thermal_zone_device *tz, int thermal_zone_trip_id(const struct thermal_zone_device *tz,
const struct thermal_trip *trip) const struct thermal_trip *trip)
{ {
@ -138,11 +118,11 @@ int thermal_zone_trip_id(const struct thermal_zone_device *tz,
return trip_to_trip_desc(trip) - tz->trips; return trip_to_trip_desc(trip) - tz->trips;
} }
void thermal_zone_trip_updated(struct thermal_zone_device *tz, void thermal_zone_set_trip_hyst(struct thermal_zone_device *tz,
const struct thermal_trip *trip) struct thermal_trip *trip, int hyst)
{ {
WRITE_ONCE(trip->hysteresis, hyst);
thermal_notify_tz_trip_change(tz, trip); thermal_notify_tz_trip_change(tz, trip);
__thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED);
} }
void thermal_zone_set_trip_temp(struct thermal_zone_device *tz, void thermal_zone_set_trip_temp(struct thermal_zone_device *tz,

View File

@ -203,15 +203,12 @@ static inline void devm_thermal_of_zone_unregister(struct device *dev,
} }
#endif #endif
int thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
struct thermal_trip *trip);
int for_each_thermal_trip(struct thermal_zone_device *tz, int for_each_thermal_trip(struct thermal_zone_device *tz,
int (*cb)(struct thermal_trip *, void *), int (*cb)(struct thermal_trip *, void *),
void *data); void *data);
int thermal_zone_for_each_trip(struct thermal_zone_device *tz, int thermal_zone_for_each_trip(struct thermal_zone_device *tz,
int (*cb)(struct thermal_trip *, void *), int (*cb)(struct thermal_trip *, void *),
void *data); void *data);
int thermal_zone_get_num_trips(struct thermal_zone_device *tz);
void thermal_zone_set_trip_temp(struct thermal_zone_device *tz, void thermal_zone_set_trip_temp(struct thermal_zone_device *tz,
struct thermal_trip *trip, int temp); struct thermal_trip *trip, int temp);