cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

gov_step_wise.c (5836B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  step_wise.c - A step-by-step Thermal throttling governor
      4 *
      5 *  Copyright (C) 2012 Intel Corp
      6 *  Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
      7 *
      8 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      9 *
     10 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     11 */
     12
     13#include <linux/thermal.h>
     14#include <trace/events/thermal.h>
     15
     16#include "thermal_core.h"
     17
     18/*
     19 * If the temperature is higher than a trip point,
     20 *    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
     21 *       state for this trip point
     22 *    b. if the trend is THERMAL_TREND_DROPPING, do nothing
     23 *    c. if the trend is THERMAL_TREND_RAISE_FULL, use upper limit
     24 *       for this trip point
     25 *    d. if the trend is THERMAL_TREND_DROP_FULL, use lower limit
     26 *       for this trip point
     27 * If the temperature is lower than a trip point,
     28 *    a. if the trend is THERMAL_TREND_RAISING, do nothing
     29 *    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
     30 *       state for this trip point, if the cooling state already
     31 *       equals lower limit, deactivate the thermal instance
     32 *    c. if the trend is THERMAL_TREND_RAISE_FULL, do nothing
     33 *    d. if the trend is THERMAL_TREND_DROP_FULL, use lower limit,
     34 *       if the cooling state already equals lower limit,
     35 *       deactivate the thermal instance
     36 */
     37static unsigned long get_target_state(struct thermal_instance *instance,
     38				enum thermal_trend trend, bool throttle)
     39{
     40	struct thermal_cooling_device *cdev = instance->cdev;
     41	unsigned long cur_state;
     42	unsigned long next_target;
     43
     44	/*
     45	 * We keep this instance the way it is by default.
     46	 * Otherwise, we use the current state of the
     47	 * cdev in use to determine the next_target.
     48	 */
     49	cdev->ops->get_cur_state(cdev, &cur_state);
     50	next_target = instance->target;
     51	dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state);
     52
     53	if (!instance->initialized) {
     54		if (throttle) {
     55			next_target = (cur_state + 1) >= instance->upper ?
     56					instance->upper :
     57					((cur_state + 1) < instance->lower ?
     58					instance->lower : (cur_state + 1));
     59		} else {
     60			next_target = THERMAL_NO_TARGET;
     61		}
     62
     63		return next_target;
     64	}
     65
     66	switch (trend) {
     67	case THERMAL_TREND_RAISING:
     68		if (throttle) {
     69			next_target = cur_state < instance->upper ?
     70				    (cur_state + 1) : instance->upper;
     71			if (next_target < instance->lower)
     72				next_target = instance->lower;
     73		}
     74		break;
     75	case THERMAL_TREND_RAISE_FULL:
     76		if (throttle)
     77			next_target = instance->upper;
     78		break;
     79	case THERMAL_TREND_DROPPING:
     80		if (cur_state <= instance->lower) {
     81			if (!throttle)
     82				next_target = THERMAL_NO_TARGET;
     83		} else {
     84			if (!throttle) {
     85				next_target = cur_state - 1;
     86				if (next_target > instance->upper)
     87					next_target = instance->upper;
     88			}
     89		}
     90		break;
     91	case THERMAL_TREND_DROP_FULL:
     92		if (cur_state == instance->lower) {
     93			if (!throttle)
     94				next_target = THERMAL_NO_TARGET;
     95		} else
     96			next_target = instance->lower;
     97		break;
     98	default:
     99		break;
    100	}
    101
    102	return next_target;
    103}
    104
    105static void update_passive_instance(struct thermal_zone_device *tz,
    106				enum thermal_trip_type type, int value)
    107{
    108	/*
    109	 * If value is +1, activate a passive instance.
    110	 * If value is -1, deactivate a passive instance.
    111	 */
    112	if (type == THERMAL_TRIP_PASSIVE)
    113		tz->passive += value;
    114}
    115
    116static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
    117{
    118	int trip_temp;
    119	enum thermal_trip_type trip_type;
    120	enum thermal_trend trend;
    121	struct thermal_instance *instance;
    122	bool throttle = false;
    123	int old_target;
    124
    125	tz->ops->get_trip_temp(tz, trip, &trip_temp);
    126	tz->ops->get_trip_type(tz, trip, &trip_type);
    127
    128	trend = get_tz_trend(tz, trip);
    129
    130	if (tz->temperature >= trip_temp) {
    131		throttle = true;
    132		trace_thermal_zone_trip(tz, trip, trip_type);
    133	}
    134
    135	dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n",
    136				trip, trip_type, trip_temp, trend, throttle);
    137
    138	mutex_lock(&tz->lock);
    139
    140	list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
    141		if (instance->trip != trip)
    142			continue;
    143
    144		old_target = instance->target;
    145		instance->target = get_target_state(instance, trend, throttle);
    146		dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n",
    147					old_target, (int)instance->target);
    148
    149		if (instance->initialized && old_target == instance->target)
    150			continue;
    151
    152		/* Activate a passive thermal instance */
    153		if (old_target == THERMAL_NO_TARGET &&
    154			instance->target != THERMAL_NO_TARGET)
    155			update_passive_instance(tz, trip_type, 1);
    156		/* Deactivate a passive thermal instance */
    157		else if (old_target != THERMAL_NO_TARGET &&
    158			instance->target == THERMAL_NO_TARGET)
    159			update_passive_instance(tz, trip_type, -1);
    160
    161		instance->initialized = true;
    162		mutex_lock(&instance->cdev->lock);
    163		instance->cdev->updated = false; /* cdev needs update */
    164		mutex_unlock(&instance->cdev->lock);
    165	}
    166
    167	mutex_unlock(&tz->lock);
    168}
    169
    170/**
    171 * step_wise_throttle - throttles devices associated with the given zone
    172 * @tz: thermal_zone_device
    173 * @trip: trip point index
    174 *
    175 * Throttling Logic: This uses the trend of the thermal zone to throttle.
    176 * If the thermal zone is 'heating up' this throttles all the cooling
    177 * devices associated with the zone and its particular trip point, by one
    178 * step. If the zone is 'cooling down' it brings back the performance of
    179 * the devices by one step.
    180 */
    181static int step_wise_throttle(struct thermal_zone_device *tz, int trip)
    182{
    183	struct thermal_instance *instance;
    184
    185	thermal_zone_trip_update(tz, trip);
    186
    187	mutex_lock(&tz->lock);
    188
    189	list_for_each_entry(instance, &tz->thermal_instances, tz_node)
    190		thermal_cdev_update(instance->cdev);
    191
    192	mutex_unlock(&tz->lock);
    193
    194	return 0;
    195}
    196
    197static struct thermal_governor thermal_gov_step_wise = {
    198	.name		= "step_wise",
    199	.throttle	= step_wise_throttle,
    200};
    201THERMAL_GOVERNOR_DECLARE(thermal_gov_step_wise);