thermal: power_allocator: don't require tzp to be present for the thermal zone
[deliverable/linux.git] / drivers / thermal / power_allocator.c
index ea57759eb095c5b4f6a75cc6eff463862516936e..718363f5be400aac71ce5f119ebd29834ac1c774 100644 (file)
@@ -58,6 +58,8 @@ static inline s64 div_frac(s64 x, s64 y)
 
 /**
  * struct power_allocator_params - parameters for the power allocator governor
+ * @allocated_tzp:     whether we have allocated tzp for this thermal zone and
+ *                     it needs to be freed on unbind
  * @err_integral:      accumulated error in the PID controller.
  * @prev_err:  error in the previous iteration of the PID controller.
  *             Used to calculate the derivative term.
@@ -70,6 +72,7 @@ static inline s64 div_frac(s64 x, s64 y)
  *                                     controlling for.
  */
 struct power_allocator_params {
+       bool allocated_tzp;
        s64 err_integral;
        s32 prev_err;
        int trip_switch_on;
@@ -527,8 +530,7 @@ static void allow_maximum_power(struct thermal_zone_device *tz)
  * Initialize the PID controller parameters and bind it to the thermal
  * zone.
  *
- * Return: 0 on success, -EINVAL if the thermal zone doesn't have tzp or -ENOMEM
- * if we ran out of memory.
+ * Return: 0 on success, or -ENOMEM if we ran out of memory.
  */
 static int power_allocator_bind(struct thermal_zone_device *tz)
 {
@@ -536,13 +538,20 @@ static int power_allocator_bind(struct thermal_zone_device *tz)
        struct power_allocator_params *params;
        int control_temp;
 
-       if (!tz->tzp)
-               return -EINVAL;
-
        params = kzalloc(sizeof(*params), GFP_KERNEL);
        if (!params)
                return -ENOMEM;
 
+       if (!tz->tzp) {
+               tz->tzp = kzalloc(sizeof(*tz->tzp), GFP_KERNEL);
+               if (!tz->tzp) {
+                       ret = -ENOMEM;
+                       goto free_params;
+               }
+
+               params->allocated_tzp = true;
+       }
+
        if (!tz->tzp->sustainable_power)
                dev_warn(&tz->device, "power_allocator: sustainable_power will be estimated\n");
 
@@ -563,11 +572,24 @@ static int power_allocator_bind(struct thermal_zone_device *tz)
        tz->governor_data = params;
 
        return 0;
+
+free_params:
+       kfree(params);
+
+       return ret;
 }
 
 static void power_allocator_unbind(struct thermal_zone_device *tz)
 {
+       struct power_allocator_params *params = tz->governor_data;
+
        dev_dbg(&tz->device, "Unbinding from thermal zone %d\n", tz->id);
+
+       if (params->allocated_tzp) {
+               kfree(tz->tzp);
+               tz->tzp = NULL;
+       }
+
        kfree(tz->governor_data);
        tz->governor_data = NULL;
 }
This page took 0.028842 seconds and 5 git commands to generate.