Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/cpuidle/governor.c
26278 views
1
/*
2
* governor.c - governor support
3
*
4
* (C) 2006-2007 Venkatesh Pallipadi <[email protected]>
5
* Shaohua Li <[email protected]>
6
* Adam Belay <[email protected]>
7
*
8
* This code is licenced under the GPL.
9
*/
10
11
#include <linux/cpu.h>
12
#include <linux/cpuidle.h>
13
#include <linux/mutex.h>
14
#include <linux/module.h>
15
#include <linux/pm_qos.h>
16
17
#include "cpuidle.h"
18
19
char param_governor[CPUIDLE_NAME_LEN];
20
21
LIST_HEAD(cpuidle_governors);
22
struct cpuidle_governor *cpuidle_curr_governor;
23
struct cpuidle_governor *cpuidle_prev_governor;
24
25
/**
26
* cpuidle_find_governor - finds a governor of the specified name
27
* @str: the name
28
*
29
* Must be called with cpuidle_lock acquired.
30
*/
31
struct cpuidle_governor *cpuidle_find_governor(const char *str)
32
{
33
struct cpuidle_governor *gov;
34
35
list_for_each_entry(gov, &cpuidle_governors, governor_list)
36
if (!strncasecmp(str, gov->name, CPUIDLE_NAME_LEN))
37
return gov;
38
39
return NULL;
40
}
41
42
/**
43
* cpuidle_switch_governor - changes the governor
44
* @gov: the new target governor
45
* Must be called with cpuidle_lock acquired.
46
*/
47
int cpuidle_switch_governor(struct cpuidle_governor *gov)
48
{
49
struct cpuidle_device *dev;
50
51
if (!gov)
52
return -EINVAL;
53
54
if (gov == cpuidle_curr_governor)
55
return 0;
56
57
cpuidle_uninstall_idle_handler();
58
59
if (cpuidle_curr_governor) {
60
list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
61
cpuidle_disable_device(dev);
62
}
63
64
cpuidle_curr_governor = gov;
65
66
list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
67
cpuidle_enable_device(dev);
68
69
cpuidle_install_idle_handler();
70
pr_info("cpuidle: using governor %s\n", gov->name);
71
72
return 0;
73
}
74
75
/**
76
* cpuidle_register_governor - registers a governor
77
* @gov: the governor
78
*/
79
int cpuidle_register_governor(struct cpuidle_governor *gov)
80
{
81
int ret = -EEXIST;
82
83
if (!gov || !gov->select)
84
return -EINVAL;
85
86
if (cpuidle_disabled())
87
return -ENODEV;
88
89
mutex_lock(&cpuidle_lock);
90
if (cpuidle_find_governor(gov->name) == NULL) {
91
ret = 0;
92
list_add_tail(&gov->governor_list, &cpuidle_governors);
93
if (!cpuidle_curr_governor ||
94
!strncasecmp(param_governor, gov->name, CPUIDLE_NAME_LEN) ||
95
(cpuidle_curr_governor->rating < gov->rating &&
96
strncasecmp(param_governor, cpuidle_curr_governor->name,
97
CPUIDLE_NAME_LEN)))
98
cpuidle_switch_governor(gov);
99
}
100
mutex_unlock(&cpuidle_lock);
101
102
return ret;
103
}
104
105
/**
106
* cpuidle_governor_latency_req - Compute a latency constraint for CPU
107
* @cpu: Target CPU
108
*/
109
s64 cpuidle_governor_latency_req(unsigned int cpu)
110
{
111
struct device *device = get_cpu_device(cpu);
112
int device_req = dev_pm_qos_raw_resume_latency(device);
113
int global_req = cpu_latency_qos_limit();
114
115
if (device_req > global_req)
116
device_req = global_req;
117
118
return (s64)device_req * NSEC_PER_USEC;
119
}
120
121