diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-07 13:13:52 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-07 13:13:52 -0500 |
commit | 3c00303206c3a1ccd86579efdc90bc35f140962e (patch) | |
tree | 66170c84b5ddaeb102aea3530517a26657b6ea29 /drivers/cpuidle/governors | |
parent | 83dbb15e9cd78a3619e3db36777e2f81d09b2914 (diff) | |
parent | efb90582c575084723cc14302c1300cb26c7e01f (diff) |
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux:
cpuidle: Single/Global registration of idle states
cpuidle: Split cpuidle_state structure and move per-cpu statistics fields
cpuidle: Remove CPUIDLE_FLAG_IGNORE and dev->prepare()
cpuidle: Move dev->last_residency update to driver enter routine; remove dev->last_state
ACPI: Fix CONFIG_ACPI_DOCK=n compiler warning
ACPI: Export FADT pm_profile integer value to userspace
thermal: Prevent polling from happening during system suspend
ACPI: Drop ACPI_NO_HARDWARE_INIT
ACPI atomicio: Convert width in bits to bytes in __acpi_ioremap_fast()
PNPACPI: Simplify disabled resource registration
ACPI: Fix possible recursive locking in hwregs.c
ACPI: use kstrdup()
mrst pmu: update comment
tools/power turbostat: less verbose debugging
Diffstat (limited to 'drivers/cpuidle/governors')
-rw-r--r-- | drivers/cpuidle/governors/ladder.c | 41 | ||||
-rw-r--r-- | drivers/cpuidle/governors/menu.c | 29 |
2 files changed, 47 insertions, 23 deletions
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c index 3b8fce20f023..b6a09ea859b1 100644 --- a/drivers/cpuidle/governors/ladder.c +++ b/drivers/cpuidle/governors/ladder.c | |||
@@ -60,9 +60,11 @@ static inline void ladder_do_selection(struct ladder_device *ldev, | |||
60 | 60 | ||
61 | /** | 61 | /** |
62 | * ladder_select_state - selects the next state to enter | 62 | * ladder_select_state - selects the next state to enter |
63 | * @drv: cpuidle driver | ||
63 | * @dev: the CPU | 64 | * @dev: the CPU |
64 | */ | 65 | */ |
65 | static int ladder_select_state(struct cpuidle_device *dev) | 66 | static int ladder_select_state(struct cpuidle_driver *drv, |
67 | struct cpuidle_device *dev) | ||
66 | { | 68 | { |
67 | struct ladder_device *ldev = &__get_cpu_var(ladder_devices); | 69 | struct ladder_device *ldev = &__get_cpu_var(ladder_devices); |
68 | struct ladder_device_state *last_state; | 70 | struct ladder_device_state *last_state; |
@@ -77,15 +79,17 @@ static int ladder_select_state(struct cpuidle_device *dev) | |||
77 | 79 | ||
78 | last_state = &ldev->states[last_idx]; | 80 | last_state = &ldev->states[last_idx]; |
79 | 81 | ||
80 | if (dev->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID) | 82 | if (drv->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID) { |
81 | last_residency = cpuidle_get_last_residency(dev) - dev->states[last_idx].exit_latency; | 83 | last_residency = cpuidle_get_last_residency(dev) - \ |
84 | drv->states[last_idx].exit_latency; | ||
85 | } | ||
82 | else | 86 | else |
83 | last_residency = last_state->threshold.promotion_time + 1; | 87 | last_residency = last_state->threshold.promotion_time + 1; |
84 | 88 | ||
85 | /* consider promotion */ | 89 | /* consider promotion */ |
86 | if (last_idx < dev->state_count - 1 && | 90 | if (last_idx < drv->state_count - 1 && |
87 | last_residency > last_state->threshold.promotion_time && | 91 | last_residency > last_state->threshold.promotion_time && |
88 | dev->states[last_idx + 1].exit_latency <= latency_req) { | 92 | drv->states[last_idx + 1].exit_latency <= latency_req) { |
89 | last_state->stats.promotion_count++; | 93 | last_state->stats.promotion_count++; |
90 | last_state->stats.demotion_count = 0; | 94 | last_state->stats.demotion_count = 0; |
91 | if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) { | 95 | if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) { |
@@ -96,11 +100,11 @@ static int ladder_select_state(struct cpuidle_device *dev) | |||
96 | 100 | ||
97 | /* consider demotion */ | 101 | /* consider demotion */ |
98 | if (last_idx > CPUIDLE_DRIVER_STATE_START && | 102 | if (last_idx > CPUIDLE_DRIVER_STATE_START && |
99 | dev->states[last_idx].exit_latency > latency_req) { | 103 | drv->states[last_idx].exit_latency > latency_req) { |
100 | int i; | 104 | int i; |
101 | 105 | ||
102 | for (i = last_idx - 1; i > CPUIDLE_DRIVER_STATE_START; i--) { | 106 | for (i = last_idx - 1; i > CPUIDLE_DRIVER_STATE_START; i--) { |
103 | if (dev->states[i].exit_latency <= latency_req) | 107 | if (drv->states[i].exit_latency <= latency_req) |
104 | break; | 108 | break; |
105 | } | 109 | } |
106 | ladder_do_selection(ldev, last_idx, i); | 110 | ladder_do_selection(ldev, last_idx, i); |
@@ -123,9 +127,11 @@ static int ladder_select_state(struct cpuidle_device *dev) | |||
123 | 127 | ||
124 | /** | 128 | /** |
125 | * ladder_enable_device - setup for the governor | 129 | * ladder_enable_device - setup for the governor |
130 | * @drv: cpuidle driver | ||
126 | * @dev: the CPU | 131 | * @dev: the CPU |
127 | */ | 132 | */ |
128 | static int ladder_enable_device(struct cpuidle_device *dev) | 133 | static int ladder_enable_device(struct cpuidle_driver *drv, |
134 | struct cpuidle_device *dev) | ||
129 | { | 135 | { |
130 | int i; | 136 | int i; |
131 | struct ladder_device *ldev = &per_cpu(ladder_devices, dev->cpu); | 137 | struct ladder_device *ldev = &per_cpu(ladder_devices, dev->cpu); |
@@ -134,8 +140,8 @@ static int ladder_enable_device(struct cpuidle_device *dev) | |||
134 | 140 | ||
135 | ldev->last_state_idx = CPUIDLE_DRIVER_STATE_START; | 141 | ldev->last_state_idx = CPUIDLE_DRIVER_STATE_START; |
136 | 142 | ||
137 | for (i = 0; i < dev->state_count; i++) { | 143 | for (i = 0; i < drv->state_count; i++) { |
138 | state = &dev->states[i]; | 144 | state = &drv->states[i]; |
139 | lstate = &ldev->states[i]; | 145 | lstate = &ldev->states[i]; |
140 | 146 | ||
141 | lstate->stats.promotion_count = 0; | 147 | lstate->stats.promotion_count = 0; |
@@ -144,7 +150,7 @@ static int ladder_enable_device(struct cpuidle_device *dev) | |||
144 | lstate->threshold.promotion_count = PROMOTION_COUNT; | 150 | lstate->threshold.promotion_count = PROMOTION_COUNT; |
145 | lstate->threshold.demotion_count = DEMOTION_COUNT; | 151 | lstate->threshold.demotion_count = DEMOTION_COUNT; |
146 | 152 | ||
147 | if (i < dev->state_count - 1) | 153 | if (i < drv->state_count - 1) |
148 | lstate->threshold.promotion_time = state->exit_latency; | 154 | lstate->threshold.promotion_time = state->exit_latency; |
149 | if (i > 0) | 155 | if (i > 0) |
150 | lstate->threshold.demotion_time = state->exit_latency; | 156 | lstate->threshold.demotion_time = state->exit_latency; |
@@ -153,11 +159,24 @@ static int ladder_enable_device(struct cpuidle_device *dev) | |||
153 | return 0; | 159 | return 0; |
154 | } | 160 | } |
155 | 161 | ||
162 | /** | ||
163 | * ladder_reflect - update the correct last_state_idx | ||
164 | * @dev: the CPU | ||
165 | * @index: the index of actual state entered | ||
166 | */ | ||
167 | static void ladder_reflect(struct cpuidle_device *dev, int index) | ||
168 | { | ||
169 | struct ladder_device *ldev = &__get_cpu_var(ladder_devices); | ||
170 | if (index > 0) | ||
171 | ldev->last_state_idx = index; | ||
172 | } | ||
173 | |||
156 | static struct cpuidle_governor ladder_governor = { | 174 | static struct cpuidle_governor ladder_governor = { |
157 | .name = "ladder", | 175 | .name = "ladder", |
158 | .rating = 10, | 176 | .rating = 10, |
159 | .enable = ladder_enable_device, | 177 | .enable = ladder_enable_device, |
160 | .select = ladder_select_state, | 178 | .select = ladder_select_state, |
179 | .reflect = ladder_reflect, | ||
161 | .owner = THIS_MODULE, | 180 | .owner = THIS_MODULE, |
162 | }; | 181 | }; |
163 | 182 | ||
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 00275244ce2f..ad0952601ae2 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
@@ -183,7 +183,7 @@ static inline int performance_multiplier(void) | |||
183 | 183 | ||
184 | static DEFINE_PER_CPU(struct menu_device, menu_devices); | 184 | static DEFINE_PER_CPU(struct menu_device, menu_devices); |
185 | 185 | ||
186 | static void menu_update(struct cpuidle_device *dev); | 186 | static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev); |
187 | 187 | ||
188 | /* This implements DIV_ROUND_CLOSEST but avoids 64 bit division */ | 188 | /* This implements DIV_ROUND_CLOSEST but avoids 64 bit division */ |
189 | static u64 div_round64(u64 dividend, u32 divisor) | 189 | static u64 div_round64(u64 dividend, u32 divisor) |
@@ -229,9 +229,10 @@ static void detect_repeating_patterns(struct menu_device *data) | |||
229 | 229 | ||
230 | /** | 230 | /** |
231 | * menu_select - selects the next idle state to enter | 231 | * menu_select - selects the next idle state to enter |
232 | * @drv: cpuidle driver containing state data | ||
232 | * @dev: the CPU | 233 | * @dev: the CPU |
233 | */ | 234 | */ |
234 | static int menu_select(struct cpuidle_device *dev) | 235 | static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) |
235 | { | 236 | { |
236 | struct menu_device *data = &__get_cpu_var(menu_devices); | 237 | struct menu_device *data = &__get_cpu_var(menu_devices); |
237 | int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); | 238 | int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); |
@@ -241,7 +242,7 @@ static int menu_select(struct cpuidle_device *dev) | |||
241 | struct timespec t; | 242 | struct timespec t; |
242 | 243 | ||
243 | if (data->needs_update) { | 244 | if (data->needs_update) { |
244 | menu_update(dev); | 245 | menu_update(drv, dev); |
245 | data->needs_update = 0; | 246 | data->needs_update = 0; |
246 | } | 247 | } |
247 | 248 | ||
@@ -286,11 +287,9 @@ static int menu_select(struct cpuidle_device *dev) | |||
286 | * Find the idle state with the lowest power while satisfying | 287 | * Find the idle state with the lowest power while satisfying |
287 | * our constraints. | 288 | * our constraints. |
288 | */ | 289 | */ |
289 | for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++) { | 290 | for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { |
290 | struct cpuidle_state *s = &dev->states[i]; | 291 | struct cpuidle_state *s = &drv->states[i]; |
291 | 292 | ||
292 | if (s->flags & CPUIDLE_FLAG_IGNORE) | ||
293 | continue; | ||
294 | if (s->target_residency > data->predicted_us) | 293 | if (s->target_residency > data->predicted_us) |
295 | continue; | 294 | continue; |
296 | if (s->exit_latency > latency_req) | 295 | if (s->exit_latency > latency_req) |
@@ -311,26 +310,30 @@ static int menu_select(struct cpuidle_device *dev) | |||
311 | /** | 310 | /** |
312 | * menu_reflect - records that data structures need update | 311 | * menu_reflect - records that data structures need update |
313 | * @dev: the CPU | 312 | * @dev: the CPU |
313 | * @index: the index of actual entered state | ||
314 | * | 314 | * |
315 | * NOTE: it's important to be fast here because this operation will add to | 315 | * NOTE: it's important to be fast here because this operation will add to |
316 | * the overall exit latency. | 316 | * the overall exit latency. |
317 | */ | 317 | */ |
318 | static void menu_reflect(struct cpuidle_device *dev) | 318 | static void menu_reflect(struct cpuidle_device *dev, int index) |
319 | { | 319 | { |
320 | struct menu_device *data = &__get_cpu_var(menu_devices); | 320 | struct menu_device *data = &__get_cpu_var(menu_devices); |
321 | data->needs_update = 1; | 321 | data->last_state_idx = index; |
322 | if (index >= 0) | ||
323 | data->needs_update = 1; | ||
322 | } | 324 | } |
323 | 325 | ||
324 | /** | 326 | /** |
325 | * menu_update - attempts to guess what happened after entry | 327 | * menu_update - attempts to guess what happened after entry |
328 | * @drv: cpuidle driver containing state data | ||
326 | * @dev: the CPU | 329 | * @dev: the CPU |
327 | */ | 330 | */ |
328 | static void menu_update(struct cpuidle_device *dev) | 331 | static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) |
329 | { | 332 | { |
330 | struct menu_device *data = &__get_cpu_var(menu_devices); | 333 | struct menu_device *data = &__get_cpu_var(menu_devices); |
331 | int last_idx = data->last_state_idx; | 334 | int last_idx = data->last_state_idx; |
332 | unsigned int last_idle_us = cpuidle_get_last_residency(dev); | 335 | unsigned int last_idle_us = cpuidle_get_last_residency(dev); |
333 | struct cpuidle_state *target = &dev->states[last_idx]; | 336 | struct cpuidle_state *target = &drv->states[last_idx]; |
334 | unsigned int measured_us; | 337 | unsigned int measured_us; |
335 | u64 new_factor; | 338 | u64 new_factor; |
336 | 339 | ||
@@ -384,9 +387,11 @@ static void menu_update(struct cpuidle_device *dev) | |||
384 | 387 | ||
385 | /** | 388 | /** |
386 | * menu_enable_device - scans a CPU's states and does setup | 389 | * menu_enable_device - scans a CPU's states and does setup |
390 | * @drv: cpuidle driver | ||
387 | * @dev: the CPU | 391 | * @dev: the CPU |
388 | */ | 392 | */ |
389 | static int menu_enable_device(struct cpuidle_device *dev) | 393 | static int menu_enable_device(struct cpuidle_driver *drv, |
394 | struct cpuidle_device *dev) | ||
390 | { | 395 | { |
391 | struct menu_device *data = &per_cpu(menu_devices, dev->cpu); | 396 | struct menu_device *data = &per_cpu(menu_devices, dev->cpu); |
392 | 397 | ||