brintos

brintos / linux-shallow public Read only

0
0
Text · 4.1 KiB · fd55271 Raw
142 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 *  step_wise.c - A step-by-step Thermal throttling governor4 *5 *  Copyright (C) 2012 Intel Corp6 *  Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>7 *8 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~9 *10 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~11 */12 13#include <linux/thermal.h>14#include <linux/minmax.h>15#include "thermal_trace.h"16 17#include "thermal_core.h"18 19/*20 * If the temperature is higher than a trip point,21 *    a. if the trend is THERMAL_TREND_RAISING, use higher cooling22 *       state for this trip point23 *    b. if the trend is THERMAL_TREND_DROPPING, do nothing24 * If the temperature is lower than a trip point,25 *    a. if the trend is THERMAL_TREND_RAISING, do nothing26 *    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling27 *       state for this trip point, if the cooling state already28 *       equals lower limit, deactivate the thermal instance29 */30static unsigned long get_target_state(struct thermal_instance *instance,31				enum thermal_trend trend, bool throttle)32{33	struct thermal_cooling_device *cdev = instance->cdev;34	unsigned long cur_state;35 36	/*37	 * We keep this instance the way it is by default.38	 * Otherwise, we use the current state of the39	 * cdev in use to determine the next_target.40	 */41	cdev->ops->get_cur_state(cdev, &cur_state);42	dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state);43 44	if (!instance->initialized) {45		if (throttle)46			return clamp(cur_state + 1, instance->lower, instance->upper);47 48		return THERMAL_NO_TARGET;49	}50 51	if (throttle) {52		if (trend == THERMAL_TREND_RAISING)53			return clamp(cur_state + 1, instance->lower, instance->upper);54	} else if (trend == THERMAL_TREND_DROPPING) {55		if (cur_state <= instance->lower)56			return THERMAL_NO_TARGET;57 58		/*59		 * If 'throttle' is false, no mitigation is necessary, so60		 * request the lower state for this instance.61		 */62		return instance->lower;63	}64 65	return instance->target;66}67 68static void thermal_zone_trip_update(struct thermal_zone_device *tz,69				     const struct thermal_trip *trip,70				     int trip_threshold)71{72	enum thermal_trend trend = get_tz_trend(tz, trip);73	int trip_id = thermal_zone_trip_id(tz, trip);74	struct thermal_instance *instance;75	bool throttle = false;76 77	if (tz->temperature >= trip_threshold) {78		throttle = true;79		trace_thermal_zone_trip(tz, trip_id, trip->type);80	}81 82	dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n",83		trip_id, trip->type, trip_threshold, trend, throttle);84 85	list_for_each_entry(instance, &tz->thermal_instances, tz_node) {86		int old_target;87 88		if (instance->trip != trip)89			continue;90 91		old_target = instance->target;92		instance->target = get_target_state(instance, trend, throttle);93 94		dev_dbg(&instance->cdev->device, "old_target=%d, target=%ld\n",95			old_target, instance->target);96 97		if (instance->initialized && old_target == instance->target)98			continue;99 100		instance->initialized = true;101 102		mutex_lock(&instance->cdev->lock);103		instance->cdev->updated = false; /* cdev needs update */104		mutex_unlock(&instance->cdev->lock);105	}106}107 108static void step_wise_manage(struct thermal_zone_device *tz)109{110	const struct thermal_trip_desc *td;111	struct thermal_instance *instance;112 113	lockdep_assert_held(&tz->lock);114 115	/*116	 * Throttling Logic: Use the trend of the thermal zone to throttle.117	 * If the thermal zone is 'heating up', throttle all of the cooling118	 * devices associated with each trip point by one step. If the zone119	 * is 'cooling down', it brings back the performance of the devices120	 * by one step.121	 */122	for_each_trip_desc(tz, td) {123		const struct thermal_trip *trip = &td->trip;124 125		if (trip->temperature == THERMAL_TEMP_INVALID ||126		    trip->type == THERMAL_TRIP_CRITICAL ||127		    trip->type == THERMAL_TRIP_HOT)128			continue;129 130		thermal_zone_trip_update(tz, trip, td->threshold);131	}132 133	list_for_each_entry(instance, &tz->thermal_instances, tz_node)134		thermal_cdev_update(instance->cdev);135}136 137static struct thermal_governor thermal_gov_step_wise = {138	.name	= "step_wise",139	.manage	= step_wise_manage,140};141THERMAL_GOVERNOR_DECLARE(thermal_gov_step_wise);142