summaryrefslogtreecommitdiffstats
path: root/drivers/thermal/thermal_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/thermal/thermal_core.c')
-rw-r--r--drivers/thermal/thermal_core.c95
1 files changed, 47 insertions, 48 deletions
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 5975bf3808..28888ac43c 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -273,7 +273,6 @@ static int __init thermal_register_governors(void)
/*
* Zone update section: main control loop applied to each zone while monitoring
- *
* in polling mode. The monitoring is done using a workqueue.
* Same update may be done on a zone by calling thermal_zone_device_update().
*
@@ -356,9 +355,9 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
trace_thermal_zone_trip(tz, thermal_zone_trip_id(tz, trip), trip->type);
if (trip->type == THERMAL_TRIP_CRITICAL)
- tz->ops->critical(tz);
- else if (tz->ops->hot)
- tz->ops->hot(tz);
+ tz->ops.critical(tz);
+ else if (tz->ops.hot)
+ tz->ops.hot(tz);
}
static void handle_thermal_trip(struct thermal_zone_device *tz,
@@ -494,8 +493,8 @@ static int thermal_zone_device_set_mode(struct thermal_zone_device *tz,
return ret;
}
- if (tz->ops->change_mode)
- ret = tz->ops->change_mode(tz, mode);
+ if (tz->ops.change_mode)
+ ret = tz->ops.change_mode(tz, mode);
if (!ret)
tz->mode = mode;
@@ -868,8 +867,8 @@ static void bind_cdev(struct thermal_cooling_device *cdev)
struct thermal_zone_device *pos = NULL;
list_for_each_entry(pos, &thermal_tz_list, node) {
- if (pos->ops->bind) {
- ret = pos->ops->bind(pos, cdev);
+ if (pos->ops.bind) {
+ ret = pos->ops.bind(pos, cdev);
if (ret)
print_bind_err_msg(pos, cdev, ret);
}
@@ -937,9 +936,17 @@ __thermal_cooling_device_register(struct device_node *np,
if (ret)
goto out_cdev_type;
+ /*
+ * The cooling device's current state is only needed for debug
+ * initialization below, so a failure to get it does not cause
+ * the entire cooling device initialization to fail. However,
+ * the debug will not work for the device if its initial state
+ * cannot be determined and drivers are responsible for ensuring
+ * that this will not happen.
+ */
ret = cdev->ops->get_cur_state(cdev, &current_state);
if (ret)
- goto out_cdev_type;
+ current_state = ULONG_MAX;
thermal_cooling_device_setup_sysfs(cdev);
@@ -954,7 +961,8 @@ __thermal_cooling_device_register(struct device_node *np,
return ERR_PTR(ret);
}
- thermal_debug_cdev_add(cdev, current_state);
+ if (current_state <= cdev->max_state)
+ thermal_debug_cdev_add(cdev, current_state);
/* Add 'this' new cdev to the global cdev list */
mutex_lock(&thermal_list_lock);
@@ -1190,8 +1198,8 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
/* Unbind all thermal zones associated with 'this' cdev */
list_for_each_entry(tz, &thermal_tz_list, node) {
- if (tz->ops->unbind)
- tz->ops->unbind(tz, cdev);
+ if (tz->ops.unbind)
+ tz->ops.unbind(tz, cdev);
}
mutex_unlock(&thermal_list_lock);
@@ -1205,13 +1213,13 @@ static void bind_tz(struct thermal_zone_device *tz)
int ret;
struct thermal_cooling_device *pos = NULL;
- if (!tz->ops->bind)
+ if (!tz->ops.bind)
return;
mutex_lock(&thermal_list_lock);
list_for_each_entry(pos, &thermal_cdev_list, node) {
- ret = tz->ops->bind(tz, pos);
+ ret = tz->ops.bind(tz, pos);
if (ret)
print_bind_err_msg(tz, pos, ret);
}
@@ -1230,11 +1238,8 @@ int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp)
{
int i, ret = -EINVAL;
- if (tz->ops->get_crit_temp)
- return tz->ops->get_crit_temp(tz, temp);
-
- if (!tz->trips)
- return -EINVAL;
+ if (tz->ops.get_crit_temp)
+ return tz->ops.get_crit_temp(tz, temp);
mutex_lock(&tz->lock);
@@ -1257,7 +1262,6 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_crit_temp);
* @type: the thermal zone device type
* @trips: a pointer to an array of thermal trips
* @num_trips: the number of trip points the thermal zone support
- * @mask: a bit string indicating the writeablility of trip points
* @devdata: private device data
* @ops: standard thermal zone device callbacks
* @tzp: thermal zone platform parameters
@@ -1278,10 +1282,12 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_crit_temp);
* IS_ERR*() helpers.
*/
struct thermal_zone_device *
-thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *trips, int num_trips, int mask,
- void *devdata, struct thermal_zone_device_ops *ops,
- const struct thermal_zone_params *tzp, int passive_delay,
- int polling_delay)
+thermal_zone_device_register_with_trips(const char *type,
+ const struct thermal_trip *trips,
+ int num_trips, void *devdata,
+ const struct thermal_zone_device_ops *ops,
+ const struct thermal_zone_params *tzp,
+ int passive_delay, int polling_delay)
{
struct thermal_zone_device *tz;
int id;
@@ -1299,20 +1305,7 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
return ERR_PTR(-EINVAL);
}
- /*
- * Max trip count can't exceed 31 as the "mask >> num_trips" condition.
- * For example, shifting by 32 will result in compiler warning:
- * warning: right shift count >= width of type [-Wshift-count- overflow]
- *
- * Also "mask >> num_trips" will always be true with 32 bit shift.
- * E.g. mask = 0x80000000 for trip id 31 to be RW. Then
- * mask >> 32 = 0x80000000
- * This will result in failure for the below condition.
- *
- * Check will be true when the bit 31 of the mask is set.
- * 32 bit shift will cause overflow of 4 byte integer.
- */
- if (num_trips > (BITS_PER_TYPE(int) - 1) || num_trips < 0 || mask >> num_trips) {
+ if (num_trips < 0) {
pr_err("Incorrect number of thermal trips\n");
return ERR_PTR(-EINVAL);
}
@@ -1328,7 +1321,7 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
if (!thermal_class)
return ERR_PTR(-ENODEV);
- tz = kzalloc(sizeof(*tz), GFP_KERNEL);
+ tz = kzalloc(struct_size(tz, trips, num_trips), GFP_KERNEL);
if (!tz)
return ERR_PTR(-ENOMEM);
@@ -1354,21 +1347,21 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
tz->id = id;
strscpy(tz->type, type, sizeof(tz->type));
- if (!ops->critical)
- ops->critical = thermal_zone_device_critical;
+ tz->ops = *ops;
+ if (!tz->ops.critical)
+ tz->ops.critical = thermal_zone_device_critical;
- tz->ops = ops;
tz->device.class = thermal_class;
tz->devdata = devdata;
- tz->trips = trips;
tz->num_trips = num_trips;
+ memcpy(tz->trips, trips, num_trips * sizeof(*trips));
thermal_set_delay_jiffies(&tz->passive_delay_jiffies, passive_delay);
thermal_set_delay_jiffies(&tz->polling_delay_jiffies, polling_delay);
/* sys I/F */
/* Add nodes that are always present via .groups */
- result = thermal_zone_create_device_groups(tz, mask);
+ result = thermal_zone_create_device_groups(tz);
if (result)
goto remove_id;
@@ -1443,10 +1436,10 @@ EXPORT_SYMBOL_GPL(thermal_zone_device_register_with_trips);
struct thermal_zone_device *thermal_tripless_zone_device_register(
const char *type,
void *devdata,
- struct thermal_zone_device_ops *ops,
+ const struct thermal_zone_device_ops *ops,
const struct thermal_zone_params *tzp)
{
- return thermal_zone_device_register_with_trips(type, NULL, 0, 0, devdata,
+ return thermal_zone_device_register_with_trips(type, NULL, 0, devdata,
ops, tzp, 0, 0);
}
EXPORT_SYMBOL_GPL(thermal_tripless_zone_device_register);
@@ -1505,8 +1498,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
/* Unbind all cdevs associated with 'this' thermal zone */
list_for_each_entry(cdev, &thermal_cdev_list, node)
- if (tz->ops->unbind)
- tz->ops->unbind(tz, cdev);
+ if (tz->ops.unbind)
+ tz->ops.unbind(tz, cdev);
mutex_unlock(&thermal_list_lock);
@@ -1640,6 +1633,12 @@ static int thermal_pm_notify(struct notifier_block *nb,
static struct notifier_block thermal_pm_nb = {
.notifier_call = thermal_pm_notify,
+ /*
+ * Run at the lowest priority to avoid interference between the thermal
+ * zone resume work items spawned by thermal_pm_notify() and the other
+ * PM notifiers.
+ */
+ .priority = INT_MIN,
};
static int __init thermal_init(void)