blob: 724f1c4bbcdcf3dd97bf6527c3d82f59601af76d [file] [log] [blame]
From 737d2d4833f2e37ca2d92f7aad28571de44fe233 Mon Sep 17 00:00:00 2001
From: Furquan Shaikh <furquan@google.com>
Date: Tue, 8 May 2018 22:33:39 -0700
Subject: [PATCH] CHROMIUM: thermal: Add notifier call chain for hot/critical
events
This will allow drivers to register a callback for important
thermal events and log critical thresholds that cause the system
to shut down.
There are other places this might work, but after consideration
I think it makes sense to have the chain at this level:
The ACPI thermal driver has an existing notify function that is
eventually called into, but that would limit the notifier to only
working on systems that use ACPI.
The cpufreq driver is already getting a notify callback executed
in this path (tz->ops->notify) but the threshold info is not passed
to the cpu_cooling notifier chain so it is not useful for logging.
BUG=b:79449188
TEST=build ok, no visible changes in this commit
[sonnyrao fixed up notifer calls for 3.8]
Signed-off-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/27775
Reviewed-by: Olof Johansson <olofj@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
[rebase44(groeck): Updated subject]
Signed-off-by: Guenter Roeck <groeck@chromium.org>
Change-Id: I8806c0bf844a08580d936d971aa80a3ec579080a
Signed-off-by: Furquan Shaikh <furquan@google.com>
Reviewed-on: https://chromium-review.googlesource.com/1051260
Commit-Ready: Furquan Shaikh <furquan@chromium.org>
Tested-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Conflicts:
drivers/thermal/thermal_core.c
(handle_non_critical_trips argument change)
[rebase54(groeck): Fix conflict]
Signed-off-by: Guenter Roeck <groeck@chromium.org>
Change-Id: I6f7ac14e028767671492f1669e0f6816e642b443
---
drivers/thermal/thermal_core.c | 42 ++++++++++++++++++++++++++++++++--
include/linux/thermal.h | 4 ++++
2 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 117eeaf7dd241e82ca1401ae39501a4c46896bb5..82c532da6f1948d9c4f4092e38bd8588d33fcf85 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/kdev_t.h>
#include <linux/idr.h>
+#include <linux/notifier.h>
#include <linux/thermal.h>
#include <linux/reboot.h>
#include <linux/string.h>
@@ -305,10 +306,44 @@ static void monitor_thermal_zone(struct thermal_zone_device *tz)
thermal_zone_device_set_polling(tz, tz->polling_delay_jiffies);
}
-static void handle_non_critical_trips(struct thermal_zone_device *tz, int trip)
+BLOCKING_NOTIFIER_HEAD(thermal_notifier_list);
+
+/**
+ * register_thermal_notifier - Register function to be called for
+ * critical thermal events.
+ *
+ * @nb: Info about notifier function to be called
+ *
+ * Currently always returns zero, as blocking_notifier_chain_register()
+ * always returns zero.
+ */
+int register_thermal_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&thermal_notifier_list, nb);
+}
+EXPORT_SYMBOL(register_thermal_notifier);
+
+/**
+ * unregister_thermal_notifier - Unregister thermal notifier
+ *
+ * @nb: Hook to be unregistered
+ *
+ * Returns zero on success, or %-ENOENT on failure.
+ */
+int unregister_thermal_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&thermal_notifier_list, nb);
+}
+EXPORT_SYMBOL(unregister_thermal_notifier);
+
+static void handle_non_critical_trips(struct thermal_zone_device *tz, int trip,
+ enum thermal_trip_type trip_type)
{
tz->governor ? tz->governor->throttle(tz, trip) :
def_governor->throttle(tz, trip);
+
+ blocking_notifier_call_chain(&thermal_notifier_list,
+ trip_type, NULL);
}
void thermal_zone_device_critical(struct thermal_zone_device *tz)
@@ -335,6 +370,9 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
trace_thermal_zone_trip(tz, trip, trip_type);
+ blocking_notifier_call_chain(&thermal_notifier_list,
+ trip_type, NULL);
+
if (trip_type == THERMAL_TRIP_HOT && tz->ops->hot)
tz->ops->hot(tz);
else if (trip_type == THERMAL_TRIP_CRITICAL)
@@ -369,7 +407,7 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
handle_critical_trips(tz, trip, trip_temp, type);
else
- handle_non_critical_trips(tz, trip);
+ handle_non_critical_trips(tz, trip, type);
}
static void update_temperature(struct thermal_zone_device *tz)
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 9ecc128944a19ba222cbaf043ec0fa2d9f812788..8eeaf7275981e1d35ea5714b3acc89b265224c67 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -13,6 +13,7 @@
#include <linux/of.h>
#include <linux/idr.h>
#include <linux/device.h>
+#include <linux/notifier.h>
#include <linux/sysfs.h>
#include <linux/workqueue.h>
#include <uapi/linux/thermal.h>
@@ -423,4 +424,7 @@ static inline int thermal_zone_device_disable(struct thermal_zone_device *tz)
{ return -ENODEV; }
#endif /* CONFIG_THERMAL */
+extern int register_thermal_notifier(struct notifier_block *);
+extern int unregister_thermal_notifier(struct notifier_block *);
+
#endif /* __THERMAL_H__ */
--
2.38.1.584.g0f3c55d4c2-goog