]> Git Repo - linux.git/blob - drivers/thermal/gov_bang_bang.c
perf/x86/intel: Support Perfmon MSRs aliasing
[linux.git] / drivers / thermal / gov_bang_bang.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  gov_bang_bang.c - A simple thermal throttling governor using hysteresis
4  *
5  *  Copyright (C) 2014 Peter Kaestle <[email protected]>
6  *
7  *  Based on step_wise.c with following Copyrights:
8  *  Copyright (C) 2012 Intel Corp
9  *  Copyright (C) 2012 Durgadoss R <[email protected]>
10  */
11
12 #include <linux/thermal.h>
13
14 #include "thermal_core.h"
15
16 /**
17  * bang_bang_control - controls devices associated with the given zone
18  * @tz: thermal_zone_device
19  * @trip: the trip point
20  * @crossed_up: whether or not the trip has been crossed on the way up
21  *
22  * Regulation Logic: a two point regulation, deliver cooling state depending
23  * on the previous state shown in this diagram:
24  *
25  *                Fan:   OFF    ON
26  *
27  *                              |
28  *                              |
29  *          trip_temp:    +---->+
30  *                        |     |        ^
31  *                        |     |        |
32  *                        |     |   Temperature
33  * (trip_temp - hyst):    +<----+
34  *                        |
35  *                        |
36  *                        |
37  *
38  *   * If the fan is not running and temperature exceeds trip_temp, the fan
39  *     gets turned on.
40  *   * In case the fan is running, temperature must fall below
41  *     (trip_temp - hyst) so that the fan gets turned off again.
42  *
43  */
44 static void bang_bang_control(struct thermal_zone_device *tz,
45                               const struct thermal_trip *trip,
46                               bool crossed_up)
47 {
48         struct thermal_instance *instance;
49
50         lockdep_assert_held(&tz->lock);
51
52         dev_dbg(&tz->device, "Trip%d[temp=%d]:temp=%d:hyst=%d\n",
53                 thermal_zone_trip_id(tz, trip), trip->temperature,
54                 tz->temperature, trip->hysteresis);
55
56         list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
57                 if (instance->trip != trip)
58                         continue;
59
60                 if (instance->target == THERMAL_NO_TARGET)
61                         instance->target = 0;
62
63                 if (instance->target != 0 && instance->target != 1) {
64                         pr_debug("Unexpected state %ld of thermal instance %s in bang-bang\n",
65                                  instance->target, instance->name);
66
67                         instance->target = 1;
68                 }
69
70                 /*
71                  * Enable the fan when the trip is crossed on the way up and
72                  * disable it when the trip is crossed on the way down.
73                  */
74                 if (instance->target == 0 && crossed_up)
75                         instance->target = 1;
76                 else if (instance->target == 1 && !crossed_up)
77                         instance->target = 0;
78
79                 dev_dbg(&instance->cdev->device, "target=%ld\n", instance->target);
80
81                 mutex_lock(&instance->cdev->lock);
82                 instance->cdev->updated = false; /* cdev needs update */
83                 mutex_unlock(&instance->cdev->lock);
84         }
85
86         list_for_each_entry(instance, &tz->thermal_instances, tz_node)
87                 thermal_cdev_update(instance->cdev);
88 }
89
90 static struct thermal_governor thermal_gov_bang_bang = {
91         .name           = "bang_bang",
92         .trip_crossed   = bang_bang_control,
93 };
94 THERMAL_GOVERNOR_DECLARE(thermal_gov_bang_bang);
This page took 0.036611 seconds and 4 git commands to generate.