All of lore.kernel.org
 help / color / mirror / Atom feed
From: Durgadoss R <durgadoss.r@intel.com>
To: lenb@kernel.org, rui.zhang@intel.com
Cc: linux-acpi@vger.kernel.org, eduardo.valentin@ti.com,
	Durgadoss R <durgadoss.r@intel.com>
Subject: [PATCHv2 11/14] Thermal: Remove throttling logic out of thermal_sys.c
Date: Mon, 27 Aug 2012 09:58:23 +0530	[thread overview]
Message-ID: <1346041706-29642-12-git-send-email-durgadoss.r@intel.com> (raw)
In-Reply-To: <1346041706-29642-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 |  337 +++++++++++++++++------------------------
 1 file changed, 136 insertions(+), 201 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 768458b..3f96f3e 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -230,6 +230,142 @@ exit:
 	mutex_unlock(&thermal_list_lock);
 }
 
+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) \
@@ -850,30 +986,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,183 +1309,6 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)
 }
 EXPORT_SYMBOL(thermal_cdev_update);
 
-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_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);
-
 /**
  * create_trip_attrs - create attributes for trip points
  * @tz:		the thermal zone device
-- 
1.7.9.5


  parent reply	other threads:[~2012-08-27  4:29 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-27  4:28 [PATCHv2 00/14] Thermal Framework Enhancements Durgadoss R
2012-08-27  4:28 ` [PATCHv2 01/14] Thermal: Refactor thermal.h file Durgadoss R
2012-08-27  4:28 ` [PATCHv2 02/14] Thermal: Move thermal_instance to thermal_core.h Durgadoss R
2012-08-27  4:28 ` [PATCHv2 03/14] Thermal: Add get trend, get instance API's to thermal_sys Durgadoss R
2012-08-27  8:11   ` Zhang, Rui
2012-08-27  8:47     ` R, Durgadoss
2012-08-27  9:19       ` Zhang, Rui
2012-08-27  9:24         ` R, Durgadoss
2012-08-27  4:28 ` [PATCHv2 04/14] Thermal: Add platform level information to thermal.h Durgadoss R
2012-08-27  8:27   ` Zhang, Rui
2012-08-27  8:57     ` R, Durgadoss
2012-08-27  9:22       ` Zhang, Rui
2012-08-27  9:25         ` R, Durgadoss
2012-08-27  4:28 ` [PATCHv2 05/14] Thermal: Obtain platform data for thermal zone Durgadoss R
2012-08-27  8:29   ` Zhang, Rui
2012-08-27  8:59     ` R, Durgadoss
2012-08-27  4:28 ` [PATCHv2 06/14] Thermal: Add a policy sysfs attribute Durgadoss R
2012-08-27  8:31   ` Zhang, Rui
2012-08-27  9:02     ` R, Durgadoss
2012-08-27  9:25       ` Zhang, Rui
2012-08-27 10:23         ` R, Durgadoss
2012-08-27 10:44           ` Zhang, Rui
2012-08-27  9:35   ` Zhang, Rui
2012-08-27 10:25     ` R, Durgadoss
2012-08-27  4:28 ` [PATCHv2 07/14] Thermal: Update binding logic based on platform data Durgadoss R
2012-08-27  9:50   ` Zhang, Rui
2012-08-27 10:29     ` R, Durgadoss
2012-08-27  4:28 ` [PATCHv2 08/14] Thermal: Make thermal_cdev_update as a global function Durgadoss R
2012-08-27  4:28 ` [PATCHv2 09/14] Thermal: Introduce fair_share thermal governor Durgadoss R
2012-08-27  4:28 ` [PATCHv2 10/14] Thermal: Introduce a step_wise " Durgadoss R
2012-08-27  4:28 ` Durgadoss R [this message]
2012-08-27  4:28 ` [PATCHv2 12/14] Thermal: Add a notification API Durgadoss R
2012-08-27  4:28 ` [PATCHv2 13/14] Thermal: Add documentation for platform layer data Durgadoss R
2012-08-27  4:28 ` [PATCHv2 14/14] Thermal: Platform layer changes to provide thermal data Durgadoss R

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=1346041706-29642-12-git-send-email-durgadoss.r@intel.com \
    --to=durgadoss.r@intel.com \
    --cc=eduardo.valentin@ti.com \
    --cc=lenb@kernel.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=rui.zhang@intel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.