Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8213b642 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drivers: thermal: Add QTI_THERMAL config"

parents 24d7be2e e836a8ac
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -401,6 +401,18 @@ depends on (ARCH_QCOM && OF) || COMPILE_TEST
source "drivers/thermal/qcom/Kconfig"
endmenu

config QTI_THERMAL
	bool
	prompt "Enable QTI Thermal Framework enhancements"
	depends on THERMAL && QGKI
	default y
	help
	  Enable the QTI enhancements on the thermal framework. This will
	  enable enhancements like handling passive evaluation on high
	  priority queue, using same trip temperature from sensor to algorithm
	  and enabling user space thermal daemon as a separate client of
	  cooling device.

config ZX2967_THERMAL
	tristate "Thermal sensors on zx2967 SoC"
	depends on ARCH_ZX || COMPILE_TEST
+131 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
 *       if the cooling state already equals lower limit,
 *       deactivate the thermal instance
 */
#ifdef CONFIG_QTI_THERMAL
static unsigned long get_target_state(struct thermal_instance *instance,
				enum thermal_trend trend, bool throttle)
{
@@ -110,6 +111,75 @@ static unsigned long get_target_state(struct thermal_instance *instance,

	return next_target;
}
#else
static unsigned long get_target_state(struct thermal_instance *instance,
				enum thermal_trend trend, bool throttle)
{
	struct thermal_cooling_device *cdev = instance->cdev;
	unsigned long cur_state;
	unsigned long next_target;

	/*
	 * We keep this instance the way it is by default.
	 * Otherwise, we use the current state of the
	 * cdev in use to determine the next_target.
	 */
	cdev->ops->get_cur_state(cdev, &cur_state);
	next_target = instance->target;
	dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state);

	if (!instance->initialized) {
		if (throttle) {
			next_target = (cur_state + 1) >= instance->upper ?
					instance->upper :
					((cur_state + 1) < instance->lower ?
					instance->lower : (cur_state + 1));
		} else {
			next_target = THERMAL_NO_TARGET;
		}

		return next_target;
	}

	switch (trend) {
	case THERMAL_TREND_RAISING:
		if (throttle) {
			next_target = cur_state < instance->upper ?
				    (cur_state + 1) : instance->upper;
			if (next_target < instance->lower)
				next_target = instance->lower;
		}
		break;
	case THERMAL_TREND_RAISE_FULL:
		if (throttle)
			next_target = instance->upper;
		break;
	case THERMAL_TREND_DROPPING:
		if (cur_state <= instance->lower) {
			if (!throttle)
				next_target = THERMAL_NO_TARGET;
		} else {
			if (!throttle) {
				next_target = cur_state - 1;
				if (next_target > instance->upper)
					next_target = instance->upper;
			}
		}
		break;
	case THERMAL_TREND_DROP_FULL:
		if (cur_state == instance->lower) {
			if (!throttle)
				next_target = THERMAL_NO_TARGET;
		} else
			next_target = instance->lower;
		break;
	default:
		break;
	}

	return next_target;
}
#endif

static void update_passive_instance(struct thermal_zone_device *tz,
				enum thermal_trip_type type, int value)
@@ -122,6 +192,7 @@ static void update_passive_instance(struct thermal_zone_device *tz,
		tz->passive += value;
}

#ifdef CONFIG_QTI_THERMAL
static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
{
	int trip_temp, hyst_temp;
@@ -208,6 +279,66 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)

	mutex_unlock(&tz->lock);
}
#else
static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
{
	int trip_temp;
	enum thermal_trip_type trip_type;
	enum thermal_trend trend;
	struct thermal_instance *instance;
	bool throttle = false;
	int old_target;

	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);
	}

	trend = get_tz_trend(tz, trip);

	if (tz->temperature >= trip_temp) {
		throttle = true;
		trace_thermal_zone_trip(tz, trip, trip_type);
	}

	dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n",
				trip, trip_type, trip_temp, trend, throttle);

	mutex_lock(&tz->lock);

	list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
		if (instance->trip != trip)
			continue;

		old_target = instance->target;
		instance->target = get_target_state(instance, trend, throttle);
		dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n",
					old_target, (int)instance->target);

		if (instance->initialized && old_target == instance->target)
			continue;

		/* Activate a passive thermal instance */
		if (old_target == THERMAL_NO_TARGET &&
			instance->target != THERMAL_NO_TARGET)
			update_passive_instance(tz, trip_type, 1);
		/* Deactivate a passive thermal instance */
		else if (old_target != THERMAL_NO_TARGET &&
			instance->target == THERMAL_NO_TARGET)
			update_passive_instance(tz, trip_type, -1);

		instance->initialized = true;
		mutex_lock(&instance->cdev->lock);
		instance->cdev->updated = false; /* cdev needs update */
		mutex_unlock(&instance->cdev->lock);
	}

	mutex_unlock(&tz->lock);
}
#endif

/**
 * step_wise_throttle - throttles devices associated with the given zone
+210 −56
Original line number Diff line number Diff line
@@ -34,8 +34,6 @@ MODULE_AUTHOR("Zhang Rui");
MODULE_DESCRIPTION("Generic thermal management sysfs support");
MODULE_LICENSE("GPL v2");

#define THERMAL_MAX_ACTIVE	16

static DEFINE_IDA(thermal_tz_ida);
static DEFINE_IDA(thermal_cdev_ida);

@@ -52,8 +50,6 @@ static bool power_off_triggered;

static struct thermal_governor *def_governor;

static struct workqueue_struct *thermal_passive_wq;

/*
 * Governor section: set of functions to handle thermal governors
 *
@@ -297,6 +293,10 @@ static int __init thermal_register_governors(void)
 * - Hot trips will produce a notification to userspace;
 * - Critical trip point will cause a system shutdown.
 */
#ifdef CONFIG_QTI_THERMAL
#define THERMAL_MAX_ACTIVE	16

static struct workqueue_struct *thermal_passive_wq;
static void thermal_zone_device_set_polling(struct workqueue_struct *queue,
					    struct thermal_zone_device *tz,
					    int delay)
@@ -327,6 +327,113 @@ static void monitor_thermal_zone(struct thermal_zone_device *tz)

	mutex_unlock(&tz->lock);
}
static void store_temperature(struct thermal_zone_device *tz, int temp)
{
	mutex_lock(&tz->lock);
	tz->last_temperature = tz->temperature;
	tz->temperature = temp;
	mutex_unlock(&tz->lock);

	trace_thermal_temperature(tz);
	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 update_temperature(struct thermal_zone_device *tz)
{
	int temp, ret;

	ret = thermal_zone_get_temp(tz, &temp);
	if (ret) {
		if (ret != -EAGAIN)
			dev_warn(&tz->device,
				 "failed to read out thermal zone (%d)\n",
				 ret);
		return;
	}
	store_temperature(tz, temp);
}

static void handle_thermal_trip(struct thermal_zone_device *tz, int trip);

void thermal_zone_device_update_temp(struct thermal_zone_device *tz,
				enum thermal_notify_event event, int temp)
{
	int count;

	if (atomic_read(&in_suspend) && tz->polling_delay)
		return;
	trace_thermal_device_update(tz, event);
	store_temperature(tz, temp);

	thermal_zone_set_trips(tz);

	tz->notify_event = event;

	for (count = 0; count < tz->trips; count++)
		handle_thermal_trip(tz, count);
}
EXPORT_SYMBOL(thermal_zone_device_update_temp);
#else
static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
					    int delay)
{
	if (delay > 1000)
		mod_delayed_work(system_freezable_power_efficient_wq,
				 &tz->poll_queue,
				 round_jiffies(msecs_to_jiffies(delay)));
	else if (delay)
		mod_delayed_work(system_freezable_power_efficient_wq,
				 &tz->poll_queue,
				 msecs_to_jiffies(delay));
	else
		cancel_delayed_work_sync(&tz->poll_queue);
}

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 update_temperature(struct thermal_zone_device *tz)
{
	int temp, ret;

	ret = thermal_zone_get_temp(tz, &temp);
	if (ret) {
		if (ret != -EAGAIN)
			dev_warn(&tz->device,
				 "failed to read out thermal zone (%d)\n",
				 ret);
		return;
	}

	mutex_lock(&tz->lock);
	tz->last_temperature = tz->temperature;
	tz->temperature = temp;
	mutex_unlock(&tz->lock);

	trace_thermal_temperature(tz);
	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);
}
#endif

static void handle_non_critical_trips(struct thermal_zone_device *tz, int trip)
{
@@ -393,7 +500,9 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
	if (trip_temp <= 0 || tz->temperature < trip_temp)
		return;

#ifdef CONFIG_QTI_THERMAL
	trace_thermal_zone_trip(tz, trip, trip_type, true);
#endif

	if (tz->ops->notify)
		tz->ops->notify(tz, trip, trip_type);
@@ -435,38 +544,9 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
	 * So, start monitoring again.
	 */
	monitor_thermal_zone(tz);
#ifdef CONFIG_QTI_THERMAL
	trace_thermal_handle_trip(tz, trip);
}

static void store_temperature(struct thermal_zone_device *tz, int temp)
{
	mutex_lock(&tz->lock);
	tz->last_temperature = tz->temperature;
	tz->temperature = temp;
	mutex_unlock(&tz->lock);

	trace_thermal_temperature(tz);
	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 update_temperature(struct thermal_zone_device *tz)
{
	int temp, ret;

	ret = thermal_zone_get_temp(tz, &temp);
	if (ret) {
		if (ret != -EAGAIN)
			dev_warn(&tz->device,
				 "failed to read out thermal zone (%d)\n",
				 ret);
		return;
	}
	store_temperature(tz, temp);
#endif
}

static void thermal_zone_device_init(struct thermal_zone_device *tz)
@@ -483,36 +563,22 @@ static void thermal_zone_device_reset(struct thermal_zone_device *tz)
	thermal_zone_device_init(tz);
}

void thermal_zone_device_update_temp(struct thermal_zone_device *tz,
				enum thermal_notify_event event, int temp)
{
	int count;

	if (atomic_read(&in_suspend) && tz->polling_delay)
		return;
	trace_thermal_device_update(tz, event);
	store_temperature(tz, temp);

	thermal_zone_set_trips(tz);

	tz->notify_event = event;

	for (count = 0; count < tz->trips; count++)
		handle_thermal_trip(tz, count);
}
EXPORT_SYMBOL(thermal_zone_device_update_temp);

void thermal_zone_device_update(struct thermal_zone_device *tz,
				enum thermal_notify_event event)
{
	int count;

	if (!tz->ops->get_temp)
		return;
#ifdef CONFIG_QTI_THERMAL
	if (atomic_read(&in_suspend) && tz->polling_delay)
		return;
	if (!tz->ops->get_temp)
	trace_thermal_device_update(tz, event);
#else
	if (atomic_read(&in_suspend))
		return;
#endif

	trace_thermal_device_update(tz, event);
	update_temperature(tz);

	thermal_zone_set_trips(tz);
@@ -741,6 +807,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
	if (ret)
		return ret;

#ifdef CONFIG_QTI_THERMAL
	/*
	 * If upper or lower has a MACRO to define the mitigation state,
	 * based on the MACRO determine the default state to use or the
@@ -761,6 +828,11 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
		else
			lower =  max_state - (THERMAL_MAX_LIMIT - lower);
	}
#else
	/* lower default 0, upper default max_state */
	lower = lower == THERMAL_NO_LIMIT ? 0 : lower;
	upper = upper == THERMAL_NO_LIMIT ? max_state : upper;
#endif

	if (lower > upper || upper > max_state)
		return -EINVAL;
@@ -883,6 +955,7 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
}
EXPORT_SYMBOL_GPL(thermal_zone_unbind_cooling_device);

#ifdef CONFIG_QTI_THERMAL
static void thermal_release(struct device *dev)
{
	struct thermal_zone_device *tz;
@@ -906,6 +979,24 @@ static void thermal_release(struct device *dev)
		kfree(cdev);
	}
}
#else
static void thermal_release(struct device *dev)
{
	struct thermal_zone_device *tz;
	struct thermal_cooling_device *cdev;

	if (!strncmp(dev_name(dev), "thermal_zone",
		     sizeof("thermal_zone") - 1)) {
		tz = to_thermal_zone(dev);
		thermal_zone_destroy_device_groups(tz);
		kfree(tz);
	} else if (!strncmp(dev_name(dev), "cooling_device",
			    sizeof("cooling_device") - 1)) {
		cdev = to_cooling_device(dev);
		kfree(cdev);
	}
}
#endif

static struct class thermal_class = {
	.name = "thermal",
@@ -1008,7 +1099,9 @@ __thermal_cooling_device_register(struct device_node *np,
	struct thermal_cooling_device *cdev;
	struct thermal_zone_device *pos = NULL;
	int result;
#ifdef CONFIG_QTI_THERMAL
	struct thermal_instance *instance;
#endif

	if (type && strlen(type) >= THERMAL_NAME_LENGTH)
		return ERR_PTR(-EINVAL);
@@ -1021,16 +1114,20 @@ __thermal_cooling_device_register(struct device_node *np,
	if (!cdev)
		return ERR_PTR(-ENOMEM);

#ifdef CONFIG_QTI_THERMAL
	instance = kzalloc(sizeof(*instance), GFP_KERNEL);
	if (!instance) {
		kfree(cdev);
		return ERR_PTR(-ENOMEM);
	}
#endif

	result = ida_simple_get(&thermal_cdev_ida, 0, 0, GFP_KERNEL);
	if (result < 0) {
		kfree(cdev);
#ifdef CONFIG_QTI_THERMAL
		kfree(instance);
#endif
		return ERR_PTR(result);
	}

@@ -1038,8 +1135,10 @@ __thermal_cooling_device_register(struct device_node *np,
	strlcpy(cdev->type, type ? : "", sizeof(cdev->type));
	mutex_init(&cdev->lock);
	INIT_LIST_HEAD(&cdev->thermal_instances);
#ifdef CONFIG_QTI_THERMAL
	instance->target = THERMAL_NO_TARGET;
	list_add_tail(&instance->cdev_node, &cdev->thermal_instances);
#endif
	cdev->np = np;
	cdev->ops = ops;
	cdev->updated = false;
@@ -1410,7 +1509,11 @@ thermal_zone_device_register(const char *type, int trips, int mask,
	/* Bind cooling devices for this zone */
	bind_tz(tz);

#ifdef CONFIG_QTI_THERMAL
	INIT_DEFERRABLE_WORK(&(tz->poll_queue), thermal_zone_device_check);
#else
	INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check);
#endif

	thermal_zone_device_reset(tz);
	/* Update the new thermal zone and mark it as already updated. */
@@ -1641,9 +1744,14 @@ static int thermal_pm_notify(struct notifier_block *nb,
			if (tz->ops->get_mode)
				tz->ops->get_mode(tz, &tz_mode);

#ifdef CONFIG_QTI_THERMAL
			if (tz_mode == THERMAL_DEVICE_DISABLED ||
				tz->polling_delay == 0)
				continue;
#else
			if (tz_mode == THERMAL_DEVICE_DISABLED)
				continue;
#endif

			thermal_zone_device_init(tz);
			thermal_zone_device_update(tz,
@@ -1660,6 +1768,7 @@ static struct notifier_block thermal_pm_nb = {
	.notifier_call = thermal_pm_notify,
};

#ifdef CONFIG_QTI_THERMAL
static int __init thermal_init(void)
{
	int result;
@@ -1737,3 +1846,48 @@ static int __init thermal_netlink_init(void)

subsys_initcall(thermal_init);
fs_initcall(thermal_netlink_init);
#else
static int __init thermal_init(void)
{
	int result;

	mutex_init(&poweroff_lock);
	result = thermal_register_governors();
	if (result)
		goto error;

	result = class_register(&thermal_class);
	if (result)
		goto unregister_governors;

	result = genetlink_init();
	if (result)
		goto unregister_class;

	result = of_parse_thermal_zones();
	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:
	genetlink_exit();
unregister_class:
	class_unregister(&thermal_class);
unregister_governors:
	thermal_unregister_governors();
error:
	ida_destroy(&thermal_tz_ida);
	ida_destroy(&thermal_cdev_ida);
	mutex_destroy(&thermal_list_lock);
	mutex_destroy(&thermal_governor_lock);
	mutex_destroy(&poweroff_lock);
	return result;
}
fs_initcall(thermal_init);
#endif
+9 −6
Original line number Diff line number Diff line
@@ -98,12 +98,6 @@ int of_thermal_get_ntrips(struct thermal_zone_device *);
bool of_thermal_is_trip_valid(struct thermal_zone_device *, int);
const struct thermal_trip *
of_thermal_get_trip_points(struct thermal_zone_device *);
int of_thermal_aggregate_trip(struct thermal_zone_device *tz,
			      enum thermal_trip_type type,
			      int *low, int *high);
void of_thermal_handle_trip(struct thermal_zone_device *tz);
void of_thermal_handle_trip_temp(struct thermal_zone_device *tz,
					int trip_temp);
#else
static inline int of_parse_thermal_zones(void) { return 0; }
static inline void of_thermal_destroy_zones(void) { }
@@ -121,6 +115,15 @@ of_thermal_get_trip_points(struct thermal_zone_device *tz)
{
	return NULL;
}
#endif
#if (defined(CONFIG_QTI_THERMAL) && defined(CONFIG_THERMAL_OF))
int of_thermal_aggregate_trip(struct thermal_zone_device *tz,
			      enum thermal_trip_type type,
			      int *low, int *high);
void of_thermal_handle_trip(struct thermal_zone_device *tz);
void of_thermal_handle_trip_temp(struct thermal_zone_device *tz,
					int trip_temp);
#else
static inline int of_thermal_aggregate_trip(struct thermal_zone_device *tz,
					    enum thermal_trip_type type,
					    int *low, int *high)
+14 −0
Original line number Diff line number Diff line
@@ -107,7 +107,9 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
		if (!ret && *temp < crit_temp)
			*temp = tz->emul_temperature;
	}
#ifdef CONFIG_QTI_THERMAL
	trace_thermal_query_temp(tz, *temp);
#endif
	mutex_unlock(&tz->lock);
exit:
	return ret;
@@ -141,6 +143,11 @@ void thermal_zone_set_trips(struct thermal_zone_device *tz)
			high = trip_temp;
	}

#ifndef CONFIG_QTI_THERMAL
	/* No need to change trip points */
	if (tz->prev_low_trip == low && tz->prev_high_trip == high)
		goto exit;
#endif
	tz->prev_low_trip = low;
	tz->prev_high_trip = high;

@@ -154,7 +161,9 @@ void thermal_zone_set_trips(struct thermal_zone_device *tz)
	ret = tz->ops->set_trips(tz, low, high);
	if (ret)
		dev_err(&tz->device, "Failed to set trips: %d\n", ret);
#ifdef CONFIG_QTI_THERMAL
	trace_thermal_set_trip(tz);
#endif

exit:
	mutex_unlock(&tz->lock);
@@ -175,6 +184,7 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)

	/* Make sure cdev enters the deepest cooling state */
	list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) {
#ifdef CONFIG_QTI_THERMAL
		if (list_is_first(&instance->cdev_node,
					&cdev->thermal_instances))
			dev_dbg(&cdev->device, "userspace->target=%lu\n",
@@ -182,6 +192,10 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)
		else
			dev_dbg(&cdev->device, "zone%d->target=%lu\n",
				instance->tz->id, instance->target);
#else
		dev_dbg(&cdev->device, "zone%d->target=%lu\n",
			instance->tz->id, instance->target);
#endif
		if (instance->target == THERMAL_NO_TARGET)
			continue;
		if (instance->target > target)
Loading