Skip to content

Commit

Permalink
Thermal: do thermal zone update after a cooling device registered
Browse files Browse the repository at this point in the history
When a new cooling device is registered, we need to update the
thermal zone to set the new registered cooling device to a proper
state.

This fixes a problem that the system is cool, while the fan devices
are left running on full speed after boot, if fan device is registered
after thermal zone device.

Here is the history of why current patch looks like this:
https://patchwork.kernel.org/patch/7273041/

CC: <[email protected]> #3.18+
Reference:https://bugzilla.kernel.org/show_bug.cgi?id=92431
Tested-by: Manuel Krause <[email protected]>
Tested-by: szegad <[email protected]>
Tested-by: prash <[email protected]>
Tested-by: amish <[email protected]>
Reviewed-by: Javi Merino <[email protected]>
Signed-off-by: Zhang Rui <[email protected]>
Signed-off-by: Chen Yu <[email protected]>
  • Loading branch information
yu-chen-surf authored and zhang-rui committed Dec 29, 2015
1 parent ff140fe commit 4511f71
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 1 deletion.
14 changes: 13 additions & 1 deletion drivers/thermal/thermal_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1341,6 +1341,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
if (!result) {
list_add_tail(&dev->tz_node, &tz->thermal_instances);
list_add_tail(&dev->cdev_node, &cdev->thermal_instances);
atomic_set(&tz->need_update, 1);
}
mutex_unlock(&cdev->lock);
mutex_unlock(&tz->lock);
Expand Down Expand Up @@ -1450,6 +1451,7 @@ __thermal_cooling_device_register(struct device_node *np,
const struct thermal_cooling_device_ops *ops)
{
struct thermal_cooling_device *cdev;
struct thermal_zone_device *pos = NULL;
int result;

if (type && strlen(type) >= THERMAL_NAME_LENGTH)
Expand Down Expand Up @@ -1494,6 +1496,12 @@ __thermal_cooling_device_register(struct device_node *np,
/* Update binding information for 'this' new cdev */
bind_cdev(cdev);

mutex_lock(&thermal_list_lock);
list_for_each_entry(pos, &thermal_tz_list, node)
if (atomic_cmpxchg(&pos->need_update, 1, 0))
thermal_zone_device_update(pos);
mutex_unlock(&thermal_list_lock);

return cdev;
}

Expand Down Expand Up @@ -1826,6 +1834,8 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
tz->trips = trips;
tz->passive_delay = passive_delay;
tz->polling_delay = polling_delay;
/* A new thermal zone needs to be updated anyway. */
atomic_set(&tz->need_update, 1);

dev_set_name(&tz->device, "thermal_zone%d", tz->id);
result = device_register(&tz->device);
Expand Down Expand Up @@ -1921,7 +1931,9 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);

thermal_zone_device_reset(tz);
thermal_zone_device_update(tz);
/* Update the new thermal zone and mark it as already updated. */
if (atomic_cmpxchg(&tz->need_update, 1, 0))
thermal_zone_device_update(tz);

return tz;

Expand Down
2 changes: 2 additions & 0 deletions include/linux/thermal.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ struct thermal_attr {
* @forced_passive: If > 0, temperature at which to switch on all ACPI
* processor cooling devices. Currently only used by the
* step-wise governor.
* @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
Expand Down Expand Up @@ -197,6 +198,7 @@ struct thermal_zone_device {
int emul_temperature;
int passive;
unsigned int forced_passive;
atomic_t need_update;
struct thermal_zone_device_ops *ops;
struct thermal_zone_params *tzp;
struct thermal_governor *governor;
Expand Down

0 comments on commit 4511f71

Please sign in to comment.