diff options
author | Zhang Rui <rui.zhang@intel.com> | 2012-07-24 04:56:21 -0400 |
---|---|---|
committer | Zhang Rui <rui.zhang@intel.com> | 2012-09-24 02:44:37 -0400 |
commit | f4a821ce6ed41970d0155f55067fb07009974fbe (patch) | |
tree | 6cceeaa90060fb17985fbe7f9b5aa9466cf03d8d | |
parent | 908b9fb792b77663a007af240e7ee89460de2025 (diff) |
Thermal: Introduce locking for cdev.thermal_instances list.
we need to go over all the thermal_instance list of a cooling device
to decide which cooling state to put the cooling device to.
But at this time, as a cooling device may be referenced in multiple
thermal zones, we need to lock the list first in case
another thermal zone is updating this cooling device.
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Reviewed-by: Rafael J. Wysocki <rjw@sisk.pl>
Reviewed-by: Eduardo Valentin <eduardo.valentin@ti.com>
-rw-r--r-- | drivers/thermal/thermal_sys.c | 8 | ||||
-rw-r--r-- | include/linux/thermal.h | 1 |
2 files changed, 9 insertions, 0 deletions
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 6e9d3dc9d89b..5be8728c88a3 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c | |||
@@ -799,6 +799,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, | |||
799 | goto remove_symbol_link; | 799 | goto remove_symbol_link; |
800 | 800 | ||
801 | mutex_lock(&tz->lock); | 801 | mutex_lock(&tz->lock); |
802 | mutex_lock(&cdev->lock); | ||
802 | list_for_each_entry(pos, &tz->thermal_instances, tz_node) | 803 | list_for_each_entry(pos, &tz->thermal_instances, tz_node) |
803 | if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { | 804 | if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { |
804 | result = -EEXIST; | 805 | result = -EEXIST; |
@@ -808,6 +809,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, | |||
808 | list_add_tail(&dev->tz_node, &tz->thermal_instances); | 809 | list_add_tail(&dev->tz_node, &tz->thermal_instances); |
809 | list_add_tail(&dev->cdev_node, &cdev->thermal_instances); | 810 | list_add_tail(&dev->cdev_node, &cdev->thermal_instances); |
810 | } | 811 | } |
812 | mutex_unlock(&cdev->lock); | ||
811 | mutex_unlock(&tz->lock); | 813 | mutex_unlock(&tz->lock); |
812 | 814 | ||
813 | if (!result) | 815 | if (!result) |
@@ -840,14 +842,17 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, | |||
840 | struct thermal_instance *pos, *next; | 842 | struct thermal_instance *pos, *next; |
841 | 843 | ||
842 | mutex_lock(&tz->lock); | 844 | mutex_lock(&tz->lock); |
845 | mutex_lock(&cdev->lock); | ||
843 | list_for_each_entry_safe(pos, next, &tz->thermal_instances, tz_node) { | 846 | list_for_each_entry_safe(pos, next, &tz->thermal_instances, tz_node) { |
844 | if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { | 847 | if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { |
845 | list_del(&pos->tz_node); | 848 | list_del(&pos->tz_node); |
846 | list_del(&pos->cdev_node); | 849 | list_del(&pos->cdev_node); |
850 | mutex_unlock(&cdev->lock); | ||
847 | mutex_unlock(&tz->lock); | 851 | mutex_unlock(&tz->lock); |
848 | goto unbind; | 852 | goto unbind; |
849 | } | 853 | } |
850 | } | 854 | } |
855 | mutex_unlock(&cdev->lock); | ||
851 | mutex_unlock(&tz->lock); | 856 | mutex_unlock(&tz->lock); |
852 | 857 | ||
853 | return -ENODEV; | 858 | return -ENODEV; |
@@ -913,6 +918,7 @@ thermal_cooling_device_register(char *type, void *devdata, | |||
913 | } | 918 | } |
914 | 919 | ||
915 | strcpy(cdev->type, type); | 920 | strcpy(cdev->type, type); |
921 | mutex_init(&cdev->lock); | ||
916 | INIT_LIST_HEAD(&cdev->thermal_instances); | 922 | INIT_LIST_HEAD(&cdev->thermal_instances); |
917 | cdev->ops = ops; | 923 | cdev->ops = ops; |
918 | cdev->updated = true; | 924 | cdev->updated = true; |
@@ -1016,6 +1022,7 @@ static void thermal_cdev_do_update(struct thermal_cooling_device *cdev) | |||
1016 | if (cdev->updated) | 1022 | if (cdev->updated) |
1017 | return; | 1023 | return; |
1018 | 1024 | ||
1025 | mutex_lock(&cdev->lock); | ||
1019 | /* Make sure cdev enters the deepest cooling state */ | 1026 | /* Make sure cdev enters the deepest cooling state */ |
1020 | list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) { | 1027 | list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) { |
1021 | if (instance->target == THERMAL_NO_TARGET) | 1028 | if (instance->target == THERMAL_NO_TARGET) |
@@ -1023,6 +1030,7 @@ static void thermal_cdev_do_update(struct thermal_cooling_device *cdev) | |||
1023 | if (instance->target > target) | 1030 | if (instance->target > target) |
1024 | target = instance->target; | 1031 | target = instance->target; |
1025 | } | 1032 | } |
1033 | mutex_unlock(&cdev->lock); | ||
1026 | cdev->ops->set_cur_state(cdev, target); | 1034 | cdev->ops->set_cur_state(cdev, target); |
1027 | cdev->updated = true; | 1035 | cdev->updated = true; |
1028 | } | 1036 | } |
diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 76d0fe88eb1c..91b34812cd84 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h | |||
@@ -95,6 +95,7 @@ struct thermal_cooling_device { | |||
95 | void *devdata; | 95 | void *devdata; |
96 | const struct thermal_cooling_device_ops *ops; | 96 | const struct thermal_cooling_device_ops *ops; |
97 | bool updated; /* true if the cooling device does not need update */ | 97 | bool updated; /* true if the cooling device does not need update */ |
98 | struct mutex lock; /* protect thermal_instances list */ | ||
98 | struct list_head thermal_instances; | 99 | struct list_head thermal_instances; |
99 | struct list_head node; | 100 | struct list_head node; |
100 | }; | 101 | }; |