Merge branches 'thermal-intel', 'thermal-suspend-fix' and 'thermal-soc' into next
authorZhang Rui <rui.zhang@intel.com>
Sat, 23 Jan 2016 03:43:27 +0000 (11:43 +0800)
committerZhang Rui <rui.zhang@intel.com>
Sat, 23 Jan 2016 03:43:27 +0000 (11:43 +0800)
1  2  3 
drivers/thermal/thermal_core.c

index d9e525cc9c1ce24bcd9d55dd59730f375b15d552,ba08b5521382890e66b14a54a5b67e7bc29c69fe,768fb10eb962ddece9790cd79fd750db7477b974..a0a8fd1235e2a21cbe5553c440b26eafecf8042e
   #include <linux/of.h>
   #include <net/netlink.h>
   #include <net/genetlink.h>
+ +#include <linux/suspend.h>
   
   #define CREATE_TRACE_POINTS
   #include <trace/events/thermal.h>
@@@@ -59,6 -60,8 -59,6 +60,8 @@@@ static LIST_HEAD(thermal_governor_list)
   static DEFINE_MUTEX(thermal_list_lock);
   static DEFINE_MUTEX(thermal_governor_lock);
   
+ +static atomic_t in_suspend;
+ +
   static struct thermal_governor *def_governor;
   
   static struct thermal_governor *__find_governor(const char *name)
@@@@ -532,14 -535,31 -532,14 +535,31 @@@@ static void update_temperature(struct t
        mutex_unlock(&tz->lock);
   
        trace_thermal_temperature(tz);
- -     dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
- -                             tz->last_temperature, tz->temperature);
+ +     if (tz->last_temperature == THERMAL_TEMP_INVALID)
+ +             dev_dbg(&tz->device, "last_temperature N/A, current_temperature=%d\n",
+ +                     tz->temperature);
+ +     else
+ +             dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
+ +                     tz->last_temperature, tz->temperature);
+ +}
+ +
+ +static void thermal_zone_device_reset(struct thermal_zone_device *tz)
+ +{
+ +     struct thermal_instance *pos;
+ +
+ +     tz->temperature = THERMAL_TEMP_INVALID;
+ +     tz->passive = 0;
+ +     list_for_each_entry(pos, &tz->thermal_instances, tz_node)
+ +             pos->initialized = false;
   }
   
   void thermal_zone_device_update(struct thermal_zone_device *tz)
   {
        int count;
   
+ +     if (atomic_read(&in_suspend))
+ +             return;
+ +
        if (!tz->ops->get_temp)
                return;
   
@@@@ -676,8 -696,8 -676,12 +696,12 @@@@ trip_point_temp_store(struct device *de
                return -EINVAL;
   
        ret = tz->ops->set_trip_temp(tz, trip, temperature);
++      if (ret)
++              return ret;
   
--      return ret ? ret : count;
++      thermal_zone_device_update(tz);
++ 
++      return count;
   }
   
   static ssize_t
@@@@ -1321,6 -1341,7 -1325,6 +1345,7 @@@@ int thermal_zone_bind_cooling_device(st
        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);
@@@@ -1430,6 -1451,7 -1434,6 +1455,7 @@@@ __thermal_cooling_device_register(struc
                                  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)
        /* 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;
   }
   
@@@@ -1806,6 -1834,8 -1810,6 +1838,8 @@@@ struct thermal_zone_device *thermal_zon
        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);
   
        INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
   
- -     thermal_zone_device_update(tz);
+ +     thermal_zone_device_reset(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;
   
@@@@ -2140,6 -2173,36 -2144,6 +2177,36 @@@@ static void thermal_unregister_governor
        thermal_gov_power_allocator_unregister();
   }
   
+ +static int thermal_pm_notify(struct notifier_block *nb,
+ +                             unsigned long mode, void *_unused)
+ +{
+ +     struct thermal_zone_device *tz;
+ +
+ +     switch (mode) {
+ +     case PM_HIBERNATION_PREPARE:
+ +     case PM_RESTORE_PREPARE:
+ +     case PM_SUSPEND_PREPARE:
+ +             atomic_set(&in_suspend, 1);
+ +             break;
+ +     case PM_POST_HIBERNATION:
+ +     case PM_POST_RESTORE:
+ +     case PM_POST_SUSPEND:
+ +             atomic_set(&in_suspend, 0);
+ +             list_for_each_entry(tz, &thermal_tz_list, node) {
+ +                     thermal_zone_device_reset(tz);
+ +                     thermal_zone_device_update(tz);
+ +             }
+ +             break;
+ +     default:
+ +             break;
+ +     }
+ +     return 0;
+ +}
+ +
+ +static struct notifier_block thermal_pm_nb = {
+ +     .notifier_call = thermal_pm_notify,
+ +};
+ +
   static int __init thermal_init(void)
   {
        int result;
        if (result)
                goto exit_netlink;
   
+ +     result = register_pm_notifier(&thermal_pm_nb);
+ +     if (result)
+ +             pr_warn("Thermal: Can not register suspend notifier, return %d\n",
+ +                     result);
+ +
        return 0;
   
   exit_netlink:
@@@@ -2179,6 -2247,7 -2183,6 +2251,7 @@@@ error
   
   static void __exit thermal_exit(void)
   {
+ +     unregister_pm_notifier(&thermal_pm_nb);
        of_thermal_destroy_zones();
        genetlink_exit();
        class_unregister(&thermal_class);