From e0e7a7ddf157924368a31f03a086022f1575aff2 Mon Sep 17 00:00:00 2001 From: Rong Dian Date: Fri, 25 Jan 2013 13:45:01 +0800 Subject: [PATCH] ENGR00241739-1 thermal: providing the thermal hot notification Create thermal hot's own hot notificaiton callback register and unregister function. Provide the thermal notification broadcast enable and disable through /sys fs. Signed-off-by: Rong Dian --- drivers/mxc/thermal/cooling.c | 11 +++--- drivers/mxc/thermal/thermal.c | 64 ++++++++++++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 9 deletions(-) diff --git a/drivers/mxc/thermal/cooling.c b/drivers/mxc/thermal/cooling.c index 7019d9949c8a..605c1c458db8 100644 --- a/drivers/mxc/thermal/cooling.c +++ b/drivers/mxc/thermal/cooling.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,7 +57,8 @@ cpufreq, it minor 1, and when we promote cpufreq, it add 1, so if it is 0, mean we didn't change the cpufreq */ static int cpufreq_change_count; -extern int thermal_hot; +extern atomic_t thermal_on; +extern int thermal_notifier_call_chain(unsigned long val); int anatop_thermal_get_cpufreq_cur(void) { int ret = -EINVAL; @@ -238,7 +239,8 @@ imx_processor_set_cur_state(struct thermal_cooling_device *cdev, secondary CPUs that detached by thermal driver */ if (cooling_cpuhotplug) { if (!state) { - thermal_hot = 0; + if (atomic_read(&thermal_on)) + thermal_notifier_call_chain(0); for (i = 1; i < 4; i++) { if (cpu_mask && (0x1 << i)) { anatop_thermal_cpu_hotplug(true); @@ -249,7 +251,8 @@ imx_processor_set_cur_state(struct thermal_cooling_device *cdev, } } else { if (!state) { - thermal_hot = 0; + if (atomic_read(&thermal_on)) + thermal_notifier_call_chain(0); if (cpufreq_change_count < 0) anatop_thermal_cpufreq_up(); else if (cpufreq_change_count > 0) diff --git a/drivers/mxc/thermal/thermal.c b/drivers/mxc/thermal/thermal.c index 0982a7b781bd..109ea2b6cf00 100644 --- a/drivers/mxc/thermal/thermal.c +++ b/drivers/mxc/thermal/thermal.c @@ -3,7 +3,7 @@ * * Copyright (C) 2001, 2002 Andy Grover * Copyright (C) 2001, 2002 Paul Diefenbaugh - * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * This program is free software; you can redistribute it and/or modify @@ -152,8 +152,7 @@ static const struct anatop_device_id thermal_device_ids[] = { {ANATOP_THERMAL_HID}, {""}, }; -int thermal_hot; -EXPORT_SYMBOL(thermal_hot); +atomic_t thermal_on = ATOMIC_INIT(1); enum { DEBUG_USER_STATE = 1U << 0, @@ -568,6 +567,27 @@ static int anatop_thermal_get_crit_temp(struct thermal_zone_device *thermal, return -EINVAL; } +static BLOCKING_NOTIFIER_HEAD(thermal_chain_head); + +int register_thermal_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&thermal_chain_head, nb); +} +EXPORT_SYMBOL_GPL(register_thermal_notifier); + +int unregister_thermal_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&thermal_chain_head, nb); +} +EXPORT_SYMBOL_GPL(unregister_thermal_notifier); + +int thermal_notifier_call_chain(unsigned long val) +{ + return (blocking_notifier_call_chain(&thermal_chain_head, val, NULL) + == NOTIFY_BAD) ? -EINVAL : 0; +} +EXPORT_SYMBOL_GPL(thermal_notifier_call_chain); + static int anatop_thermal_notify(struct thermal_zone_device *thermal, int trip, enum thermal_trip_type trip_type) { @@ -585,7 +605,8 @@ static int anatop_thermal_notify(struct thermal_zone_device *thermal, int trip, printk(KERN_WARNING "thermal_notify: trip_critical reached!\n"); arch_reset(mode, cmd); } else if (trip_type == THERMAL_TRIP_HOT) { - thermal_hot = 1; + if (atomic_read(&thermal_on)) + thermal_notifier_call_chain(1); printk(KERN_DEBUG "thermal_notify: trip_hot reached!\n"); type = ANATOP_THERMAL_NOTIFY_HOT; /* if temperature increase, continue to detach secondary CPUs*/ @@ -600,7 +621,8 @@ static int anatop_thermal_notify(struct thermal_zone_device *thermal, int trip, printk(KERN_INFO "No secondary CPUs detached!\n"); full_run = false; } else { - thermal_hot = 0; + if (atomic_read(&thermal_on)) + thermal_notifier_call_chain(0); if (!full_run) { temperature_cooling = 0; if (cooling_cpuhotplug) @@ -871,6 +893,35 @@ static irqreturn_t anatop_thermal_alarm_handler(int irq, void *dev_id) return IRQ_HANDLED; } +static ssize_t anatop_thermal_flag_show(struct device *dev, + struct device_attribute *attr, char *buf) { + return sprintf(buf, "read thermal_hot_flag:%d\n", + atomic_read(&thermal_on)); +} + +static ssize_t anatop_thermal_flag_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + int ret; + unsigned long data; + ret = strict_strtoul(buf, 10, &data); + if (data == 0) + atomic_set(&thermal_on, 0); + else + atomic_set(&thermal_on, 1); + return count; +} + +static struct device_attribute anatop_thermal_flag_dev_attr = { + .attr = { + .name = "thermal_hot_flag", + .mode = S_IRUSR | S_IWUSR, + }, + .show = anatop_thermal_flag_show, + .store = anatop_thermal_flag_store, +}; + static int anatop_thermal_probe(struct platform_device *pdev) { int retval = 0; @@ -935,6 +986,9 @@ static int anatop_thermal_probe(struct platform_device *pdev) anatop_thermal_add(device); anatop_thermal_cpufreq_init(); + retval = device_create_file(&pdev->dev, &anatop_thermal_flag_dev_attr); + if (retval) + dev_err(&pdev->dev, "create device file failed!\n"); pr_info("%s: default cooling device is cpufreq!\n", __func__); goto success; -- 2.39.5