From: Durgadoss R <durgadoss.r@intel.com>
To: lenb@kernel.org, rui.zhang@intel.com, rjw@sisk.pl,
linux-acpi@vger.kernel.org, linux-pm@vger.kernel.org
Cc: eduardo.valentin@ti.com, amit.kachhap@linaro.org, wni@nvidia.com,
Durgadoss R <durgadoss.r@intel.com>
Subject: [PATCH 10/13] Thermal: Remove throttling logic out of thermal_sys.c
Date: Thu, 9 Aug 2012 18:16:02 +0530 [thread overview]
Message-ID: <1344516365-7230-11-git-send-email-durgadoss.r@intel.com> (raw)
In-Reply-To: <1344516365-7230-1-git-send-email-durgadoss.r@intel.com>
This patch removes the throttling logic out of
thermal_sys.c; also refactors the code into smaller
functions so that are easy to read/maintain.
* Seperates the handling of critical and non-critical trips
* Re-arranges the set_polling and device_check methods, so
that all related functions are arranged in one place.
* Removes the 'do_update' and 'trip_update' method, as part
of moving the throttling logic out of thermal_sys.c
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
drivers/thermal/thermal_sys.c | 359 ++++++++++++++++-------------------------
include/linux/thermal.h | 2 +-
2 files changed, 137 insertions(+), 224 deletions(-)
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 748b12f..193d071 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -259,6 +259,142 @@ static void do_binding(struct thermal_zone_device *tz)
}
}
+static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
+ int delay)
+{
+ cancel_delayed_work(&(tz->poll_queue));
+
+ if (!delay)
+ return;
+
+ if (delay > 1000)
+ queue_delayed_work(system_freezable_wq, &(tz->poll_queue),
+ round_jiffies(msecs_to_jiffies(delay)));
+ else
+ queue_delayed_work(system_freezable_wq, &(tz->poll_queue),
+ msecs_to_jiffies(delay));
+}
+
+static void monitor_thermal_zone(struct thermal_zone_device *tz)
+{
+ mutex_lock(&tz->lock);
+
+ if (tz->passive)
+ thermal_zone_device_set_polling(tz, tz->passive_delay);
+ else if (tz->polling_delay)
+ thermal_zone_device_set_polling(tz, tz->polling_delay);
+ else
+ thermal_zone_device_set_polling(tz, 0);
+
+ mutex_unlock(&tz->lock);
+}
+
+static void notify_user_space(struct thermal_zone_device *tz, int trip)
+{
+ mutex_lock(&tz->lock);
+
+ kobject_uevent(&tz->device.kobj, KOBJ_CHANGE);
+
+ mutex_unlock(&tz->lock);
+}
+
+static void handle_non_critical_trips(struct thermal_zone_device *tz,
+ int trip, enum thermal_trip_type trip_type)
+{
+ int throttle_policy = THERMAL_STEP_WISE;
+
+ if (tz->tzp)
+ throttle_policy = tz->tzp->throttle_policy;
+
+ switch (throttle_policy) {
+ case THERMAL_FAIR_SHARE:
+ fair_share_throttle(tz, trip);
+ break;
+ case THERMAL_STEP_WISE:
+ step_wise_throttle(tz, trip);
+ break;
+ case THERMAL_USER_SPACE:
+ notify_user_space(tz, trip);
+ break;
+ }
+}
+
+static void handle_critical_trips(struct thermal_zone_device *tz,
+ int trip, enum thermal_trip_type trip_type)
+{
+ long trip_temp;
+
+ tz->ops->get_trip_temp(tz, trip, &trip_temp);
+
+ /* If we have not crossed the trip_temp, we do not care. */
+ if (tz->temperature < trip_temp)
+ return;
+
+ if (tz->ops->notify)
+ tz->ops->notify(tz, trip, trip_type);
+
+ if (trip_type == THERMAL_TRIP_CRITICAL) {
+ pr_emerg("Critical temperature reached(%d C),shutting down\n",
+ tz->temperature / 1000);
+ orderly_poweroff(true);
+ }
+}
+
+static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
+{
+ enum thermal_trip_type type;
+
+ tz->ops->get_trip_type(tz, trip, &type);
+
+ if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
+ handle_critical_trips(tz, trip, type);
+ else
+ handle_non_critical_trips(tz, trip, type);
+ /*
+ * Alright, we handled this trip successfully.
+ * So, start monitoring again.
+ */
+ monitor_thermal_zone(tz);
+}
+
+static void update_temperature(struct thermal_zone_device *tz)
+{
+ long temp;
+ int ret;
+
+ mutex_lock(&tz->lock);
+
+ ret = tz->ops->get_temp(tz, &temp);
+ if (ret) {
+ pr_warn("failed to read out thermal zone %d\n", tz->id);
+ return;
+ }
+
+ tz->last_temperature = tz->temperature;
+ tz->temperature = temp;
+
+ mutex_unlock(&tz->lock);
+}
+
+void thermal_zone_device_update(struct thermal_zone_device *tz)
+{
+ int count;
+
+ update_temperature(tz);
+
+ for (count = 0; count < tz->trips; count++)
+ handle_thermal_trip(tz, count);
+}
+EXPORT_SYMBOL(thermal_zone_device_update);
+
+static void thermal_zone_device_check(struct work_struct *work)
+{
+ struct thermal_zone_device *tz = container_of(work, struct
+ thermal_zone_device,
+ poll_queue.work);
+ thermal_zone_device_update(tz);
+}
+
/* sys I/F for thermal zone */
#define to_thermal_zone(_dev) \
@@ -878,30 +1014,6 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
}
#endif
-static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
- int delay)
-{
- cancel_delayed_work(&(tz->poll_queue));
-
- if (!delay)
- return;
-
- if (delay > 1000)
- queue_delayed_work(system_freezable_wq, &(tz->poll_queue),
- round_jiffies(msecs_to_jiffies(delay)));
- else
- queue_delayed_work(system_freezable_wq, &(tz->poll_queue),
- msecs_to_jiffies(delay));
-}
-
-static void thermal_zone_device_check(struct work_struct *work)
-{
- struct thermal_zone_device *tz = container_of(work, struct
- thermal_zone_device,
- poll_queue.work);
- thermal_zone_device_update(tz);
-}
-
/**
* thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone
* @tz: thermal zone device
@@ -1197,205 +1309,6 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
}
EXPORT_SYMBOL(thermal_cooling_device_unregister);
-static void thermal_cdev_do_update(struct thermal_cooling_device *cdev)
-{
- struct thermal_instance *instance;
- unsigned long target = 0;
-
- /* cooling device is updated*/
- if (cdev->updated)
- return;
-
- mutex_lock(&cdev->lock);
- /* Make sure cdev enters the deepest cooling state */
- list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) {
- if (instance->target == THERMAL_NO_TARGET)
- continue;
- if (instance->target > target)
- target = instance->target;
- }
- mutex_unlock(&cdev->lock);
- cdev->ops->set_cur_state(cdev, target);
- cdev->updated = true;
-}
-
-static void thermal_zone_do_update(struct thermal_zone_device *tz)
-{
- struct thermal_instance *instance;
-
- list_for_each_entry(instance, &tz->thermal_instances, tz_node)
- thermal_cdev_do_update(instance->cdev);
-}
-
-/*
- * Cooling algorithm for both active and passive cooling
- *
- * 1. if the temperature is higher than a trip point,
- * a. if the trend is THERMAL_TREND_RAISING, use higher cooling
- * state for this trip point
- * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
- * state for this trip point
- *
- * 2. if the temperature is lower than a trip point, use lower
- * cooling state for this trip point
- *
- * Note that this behaves the same as the previous passive cooling
- * algorithm.
- */
-
-static void thermal_zone_trip_update(struct thermal_zone_device *tz,
- int trip, long temp)
-{
- struct thermal_instance *instance;
- struct thermal_cooling_device *cdev = NULL;
- unsigned long cur_state, max_state;
- long trip_temp;
- enum thermal_trip_type trip_type;
- enum thermal_trend trend;
-
- if (trip == THERMAL_TRIPS_NONE) {
- trip_temp = tz->forced_passive;
- trip_type = THERMAL_TRIPS_NONE;
- } else {
- tz->ops->get_trip_temp(tz, trip, &trip_temp);
- tz->ops->get_trip_type(tz, trip, &trip_type);
- }
-
- if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) {
- /*
- * compare the current temperature and previous temperature
- * to get the thermal trend, if no special requirement
- */
- if (tz->temperature > tz->last_temperature)
- trend = THERMAL_TREND_RAISING;
- else if (tz->temperature < tz->last_temperature)
- trend = THERMAL_TREND_DROPPING;
- else
- trend = THERMAL_TREND_STABLE;
- }
-
- if (temp >= trip_temp) {
- list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
- if (instance->trip != trip)
- continue;
-
- cdev = instance->cdev;
-
- cdev->ops->get_cur_state(cdev, &cur_state);
- cdev->ops->get_max_state(cdev, &max_state);
-
- if (trend == THERMAL_TREND_RAISING) {
- cur_state = cur_state < instance->upper ?
- (cur_state + 1) : instance->upper;
- } else if (trend == THERMAL_TREND_DROPPING) {
- cur_state = cur_state > instance->lower ?
- (cur_state - 1) : instance->lower;
- }
-
- /* activate a passive thermal instance */
- if ((trip_type == THERMAL_TRIP_PASSIVE ||
- trip_type == THERMAL_TRIPS_NONE) &&
- instance->target == THERMAL_NO_TARGET)
- tz->passive++;
-
- instance->target = cur_state;
- cdev->updated = false; /* cooling device needs update */
- }
- } else { /* below trip */
- list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
- if (instance->trip != trip)
- continue;
-
- /* Do not use the inactive thermal instance */
- if (instance->target == THERMAL_NO_TARGET)
- continue;
- cdev = instance->cdev;
- cdev->ops->get_cur_state(cdev, &cur_state);
-
- cur_state = cur_state > instance->lower ?
- (cur_state - 1) : THERMAL_NO_TARGET;
-
- /* deactivate a passive thermal instance */
- if ((trip_type == THERMAL_TRIP_PASSIVE ||
- trip_type == THERMAL_TRIPS_NONE) &&
- cur_state == THERMAL_NO_TARGET)
- tz->passive--;
- instance->target = cur_state;
- cdev->updated = false; /* cooling device needs update */
- }
- }
-
- return;
-}
-/**
- * thermal_zone_device_update - force an update of a thermal zone's state
- * @ttz: the thermal zone to update
- */
-
-void thermal_zone_device_update(struct thermal_zone_device *tz)
-{
- int count, ret = 0;
- long temp, trip_temp;
- enum thermal_trip_type trip_type;
-
- mutex_lock(&tz->lock);
-
- if (tz->ops->get_temp(tz, &temp)) {
- /* get_temp failed - retry it later */
- pr_warn("failed to read out thermal zone %d\n", tz->id);
- goto leave;
- }
-
- tz->last_temperature = tz->temperature;
- tz->temperature = temp;
-
- for (count = 0; count < tz->trips; count++) {
- tz->ops->get_trip_type(tz, count, &trip_type);
- tz->ops->get_trip_temp(tz, count, &trip_temp);
-
- switch (trip_type) {
- case THERMAL_TRIP_CRITICAL:
- if (temp >= trip_temp) {
- if (tz->ops->notify)
- ret = tz->ops->notify(tz, count,
- trip_type);
- if (!ret) {
- pr_emerg("Critical temperature reached (%ld C), shutting down\n",
- temp/1000);
- orderly_poweroff(true);
- }
- }
- break;
- case THERMAL_TRIP_HOT:
- if (temp >= trip_temp)
- if (tz->ops->notify)
- tz->ops->notify(tz, count, trip_type);
- break;
- case THERMAL_TRIP_ACTIVE:
- thermal_zone_trip_update(tz, count, temp);
- break;
- case THERMAL_TRIP_PASSIVE:
- if (temp >= trip_temp || tz->passive)
- thermal_zone_trip_update(tz, count, temp);
- break;
- }
- }
-
- if (tz->forced_passive)
- thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE, temp);
- thermal_zone_do_update(tz);
-
-leave:
- if (tz->passive)
- thermal_zone_device_set_polling(tz, tz->passive_delay);
- else if (tz->polling_delay)
- thermal_zone_device_set_polling(tz, tz->polling_delay);
- else
- thermal_zone_device_set_polling(tz, 0);
- mutex_unlock(&tz->lock);
-}
-EXPORT_SYMBOL(thermal_zone_device_update);
-
static int create_policy_attr(struct thermal_zone_device *tz)
{
sysfs_attr_init(&tz->policy_attr.attr);
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 60d2743..3bdf5f2 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -236,12 +236,12 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
unsigned long, unsigned long);
int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int,
struct thermal_cooling_device *);
-void thermal_zone_device_update(struct thermal_zone_device *);
struct thermal_cooling_device *thermal_cooling_device_register(char *, void *,
const struct thermal_cooling_device_ops *);
void thermal_cooling_device_unregister(struct thermal_cooling_device *);
+void thermal_zone_device_update(struct thermal_zone_device *);
int get_tz_trend(struct thermal_zone_device *, int);
struct thermal_cooling_device *get_cdev_by_name(const char *);
struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
--
1.7.9.5
next prev parent reply other threads:[~2012-08-09 12:46 UTC|newest]
Thread overview: 61+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-08-09 12:45 [PATCH 00/13] Thermal Framework Enhancements Durgadoss R
2012-08-09 12:45 ` [PATCH 01/13] Thermal: Refactor thermal.h file Durgadoss R
2012-08-20 15:58 ` Eduardo Valentin
2012-08-20 16:42 ` R, Durgadoss
2012-08-20 17:53 ` Eduardo Valentin
2012-08-09 12:45 ` [PATCH 02/13] Thermal: Move thermal_instance to thermal.h Durgadoss R
2012-08-16 6:14 ` Zhang Rui
2012-08-16 6:19 ` R, Durgadoss
2012-08-16 6:29 ` Zhang Rui
2012-08-16 6:31 ` R, Durgadoss
2012-08-16 7:12 ` Zhang Rui
2012-08-20 20:41 ` Eduardo Valentin
2012-08-09 12:45 ` [PATCH 03/13] Thermal: Add get trend, get instance API's to thermal_sys Durgadoss R
2012-08-20 20:58 ` Eduardo Valentin
2012-08-09 12:45 ` [PATCH 04/13] Thermal: Add platform level information to thermal.h Durgadoss R
2012-08-13 6:27 ` Zhang Rui
2012-08-13 6:31 ` R, Durgadoss
2012-08-16 6:16 ` Zhang Rui
2012-08-20 21:11 ` Eduardo Valentin
2012-08-09 12:45 ` [PATCH 05/13] Thermal: Obtain platform data for thermal zone Durgadoss R
2012-08-21 5:20 ` Eduardo Valentin
2012-08-09 12:45 ` [PATCH 06/13] Thermal: Add a policy sysfs attribute Durgadoss R
2012-08-13 6:28 ` Zhang Rui
2012-08-13 6:34 ` R, Durgadoss
2012-08-13 7:07 ` Zhang Rui
2012-08-21 5:31 ` Eduardo Valentin
2012-08-09 12:45 ` [PATCH 07/13] Thermal: Update binding logic based on platform data Durgadoss R
2012-08-13 6:41 ` Zhang Rui
2012-08-13 15:41 ` R, Durgadoss
2012-08-15 6:53 ` Zhang Rui
2012-08-15 9:17 ` R, Durgadoss
2012-08-16 3:30 ` Zhang Rui
2012-08-16 3:31 ` R, Durgadoss
2012-08-20 18:11 ` Eduardo Valentin
2012-08-09 12:46 ` [PATCH 08/13] Thermal: Introduce fair_share thermal governor Durgadoss R
2012-08-21 5:33 ` Eduardo Valentin
2012-08-21 5:59 ` R, Durgadoss
2012-08-21 14:16 ` Eduardo Valentin
2012-08-09 12:46 ` [PATCH 09/13] Thermal: Introduce a step_wise " Durgadoss R
2012-08-21 5:35 ` Eduardo Valentin
2012-08-09 12:46 ` Durgadoss R [this message]
2012-08-13 7:00 ` [PATCH 10/13] Thermal: Remove throttling logic out of thermal_sys.c Zhang Rui
2012-08-13 8:04 ` R, Durgadoss
2012-08-21 5:36 ` Eduardo Valentin
2012-08-09 12:46 ` [PATCH 11/13] Thermal: Add a notification API Durgadoss R
2012-08-13 7:02 ` Zhang Rui
2012-08-13 7:46 ` R, Durgadoss
2012-08-21 5:17 ` Eduardo Valentin
2012-08-09 12:46 ` [PATCH 12/13] Thermal: Add documentation for platform layer data Durgadoss R
2012-08-21 5:38 ` Eduardo Valentin
2012-08-21 5:51 ` R, Durgadoss
2012-08-09 12:46 ` [PATCH 13/13] Thermal: Platform layer changes to provide thermal data Durgadoss R
2012-08-21 5:39 ` Eduardo Valentin
2012-08-21 5:52 ` R, Durgadoss
2012-08-21 5:55 ` Zhang Rui
2012-08-21 6:41 ` R, Durgadoss
2012-08-21 6:52 ` Zhang Rui
2012-08-21 8:51 ` Eduardo Valentin
2012-08-23 0:11 ` Zhang Rui
2012-08-21 9:28 ` R, Durgadoss
2012-08-23 0:23 ` Zhang Rui
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1344516365-7230-11-git-send-email-durgadoss.r@intel.com \
--to=durgadoss.r@intel.com \
--cc=amit.kachhap@linaro.org \
--cc=eduardo.valentin@ti.com \
--cc=lenb@kernel.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=rjw@sisk.pl \
--cc=rui.zhang@intel.com \
--cc=wni@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).