Thermal: Add start and stop operations in thermal_governor structure
Jinyoung Park [Mon, 17 Dec 2012 13:44:50 +0000 (22:44 +0900)]
Added start and stop operations to initialize and uninitialize governor
in thermal_governor structure.
The start and stop operations will be called when thermal zone is registered
and when change governor via sysfs. They will be not called when cooling
devices are registered or when cooling devices are bound to thermal zones.

Bug 1200111

Change-Id: Ib4037bc1f07a252cf5975aafda7323734e421e26
Signed-off-by: Jinyoung Park <jinyoungp@nvidia.com>
Reviewed-on: http://git-master/r/188035
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Matthew Longnecker <mlongnecker@nvidia.com>
Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>

drivers/thermal/thermal_sys.c
include/linux/thermal.h

index 5979b6e..951480e 100644 (file)
@@ -91,10 +91,17 @@ int thermal_register_governor(struct thermal_governor *governor)
                        name = pos->tzp->governor_name;
                else
                        name = DEFAULT_THERMAL_GOVERNOR;
-               if (!strnicmp(name, governor->name, THERMAL_NAME_LENGTH))
+               if (!strnicmp(name, governor->name, THERMAL_NAME_LENGTH)) {
+                       if (governor->start) {
+                               err = governor->start(pos);
+                               if (err < 0)
+                                       goto exit;
+                       }
                        pos->governor = governor;
+               }
        }
 
+exit:
        mutex_unlock(&thermal_list_lock);
        mutex_unlock(&thermal_governor_lock);
 
@@ -118,8 +125,11 @@ void thermal_unregister_governor(struct thermal_governor *governor)
 
        list_for_each_entry(pos, &thermal_tz_list, node) {
                if (!strnicmp(pos->governor->name, governor->name,
-                                               THERMAL_NAME_LENGTH))
+                                               THERMAL_NAME_LENGTH)) {
+                       if (pos->governor->stop)
+                               pos->governor->stop(pos);
                        pos->governor = NULL;
+               }
        }
 
        mutex_unlock(&thermal_list_lock);
@@ -714,6 +724,23 @@ policy_store(struct device *dev, struct device_attribute *attr,
        if (!gov)
                goto exit;
 
+       if (gov == tz->governor) {
+               ret = count;
+               goto exit;
+       }
+
+       if (tz->governor && tz->governor->stop)
+               tz->governor->stop(tz);
+
+       if (gov->start) {
+               ret = gov->start(tz);
+               if (ret < 0) {
+                       if (tz->governor && tz->governor->start)
+                               tz->governor->start(tz);
+                       goto exit;
+               }
+       }
+
        tz->governor = gov;
        ret = count;
 
@@ -1688,6 +1715,14 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
                }
        }
 
+       if (tz->governor->start) {
+               result = tz->governor->start(tz);
+               if (result < 0) {
+                       mutex_unlock(&thermal_governor_lock);
+                       goto unregister;
+               }
+       }
+
        mutex_unlock(&thermal_governor_lock);
 
        result = thermal_add_hwmon_sysfs(tz);
@@ -1709,6 +1744,9 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
                return tz;
 
 unregister:
+       if (tz->governor && tz->governor->stop)
+               tz->governor->stop(tz);
+       tz->governor = NULL;
        release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
        device_unregister(&tz->device);
        return ERR_PTR(result);
@@ -1773,6 +1811,9 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
        device_remove_file(&tz->device, &dev_attr_policy);
        device_remove_file(&tz->device, &dev_attr_available_policies);
        remove_trip_attrs(tz);
+
+       if (tz->governor && tz->governor->stop)
+               tz->governor->stop(tz);
        tz->governor = NULL;
 
        thermal_remove_hwmon_sysfs(tz);
index 40c5908..3f4f0fe 100644 (file)
@@ -173,6 +173,16 @@ struct thermal_zone_device {
 /* Structure that holds thermal governor information */
 struct thermal_governor {
        char name[THERMAL_NAME_LENGTH];
+
+       /*
+        * The start and stop operations will be called when thermal zone is
+        * registered and when change governor via sysfs. They will not be
+        * called when cooling devices are registered or when cooling devices
+        * are bound to thermal zones.
+        */
+       int (*start)(struct thermal_zone_device *tz);
+       void (*stop)(struct thermal_zone_device *tz);
+
        int (*throttle)(struct thermal_zone_device *tz, int trip);
        struct list_head        governor_list;
        struct module           *owner;