Commit 9a0b841586c3c6c846effdbe75885c2ebc0031b0
Committed by
Len Brown
1 parent
9b12e18cdc
Exists in
master
and in
20 other branches
cpuidle: Add a poll_idle method
Add a default poll idle state with 0 latency. Provides an option to users to use poll_idle by using 0 as the latency requirement. Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Showing 4 changed files with 57 additions and 4 deletions Side-by-side Diff
arch/x86/Kconfig
drivers/acpi/processor_idle.c
... | ... | @@ -1628,7 +1628,7 @@ |
1628 | 1628 | */ |
1629 | 1629 | static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) |
1630 | 1630 | { |
1631 | - int i, count = 0; | |
1631 | + int i, count = CPUIDLE_DRIVER_STATE_START; | |
1632 | 1632 | struct acpi_processor_cx *cx; |
1633 | 1633 | struct cpuidle_state *state; |
1634 | 1634 | struct cpuidle_device *dev = &pr->power.dev; |
... | ... | @@ -1687,6 +1687,8 @@ |
1687 | 1687 | } |
1688 | 1688 | |
1689 | 1689 | count++; |
1690 | + if (count == CPUIDLE_STATE_MAX) | |
1691 | + break; | |
1690 | 1692 | } |
1691 | 1693 | |
1692 | 1694 | dev->state_count = count; |
drivers/cpuidle/cpuidle.c
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | #include <linux/pm_qos_params.h> |
16 | 16 | #include <linux/cpu.h> |
17 | 17 | #include <linux/cpuidle.h> |
18 | +#include <linux/ktime.h> | |
18 | 19 | |
19 | 20 | #include "cpuidle.h" |
20 | 21 | |
... | ... | @@ -180,6 +181,44 @@ |
180 | 181 | |
181 | 182 | EXPORT_SYMBOL_GPL(cpuidle_disable_device); |
182 | 183 | |
184 | +#ifdef CONFIG_ARCH_HAS_CPU_RELAX | |
185 | +static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st) | |
186 | +{ | |
187 | + ktime_t t1, t2; | |
188 | + s64 diff; | |
189 | + int ret; | |
190 | + | |
191 | + t1 = ktime_get(); | |
192 | + local_irq_enable(); | |
193 | + while (!need_resched()) | |
194 | + cpu_relax(); | |
195 | + | |
196 | + t2 = ktime_get(); | |
197 | + diff = ktime_to_us(ktime_sub(t2, t1)); | |
198 | + if (diff > INT_MAX) | |
199 | + diff = INT_MAX; | |
200 | + | |
201 | + ret = (int) diff; | |
202 | + return ret; | |
203 | +} | |
204 | + | |
205 | +static void poll_idle_init(struct cpuidle_device *dev) | |
206 | +{ | |
207 | + struct cpuidle_state *state = &dev->states[0]; | |
208 | + | |
209 | + cpuidle_set_statedata(state, NULL); | |
210 | + | |
211 | + snprintf(state->name, CPUIDLE_NAME_LEN, "C0 (poll idle)"); | |
212 | + state->exit_latency = 0; | |
213 | + state->target_residency = 0; | |
214 | + state->power_usage = -1; | |
215 | + state->flags = CPUIDLE_FLAG_POLL | CPUIDLE_FLAG_TIME_VALID; | |
216 | + state->enter = poll_idle; | |
217 | +} | |
218 | +#else | |
219 | +static void poll_idle_init(struct cpuidle_device *dev) {} | |
220 | +#endif /* CONFIG_ARCH_HAS_CPU_RELAX */ | |
221 | + | |
183 | 222 | /** |
184 | 223 | * cpuidle_register_device - registers a CPU's idle PM feature |
185 | 224 | * @dev: the cpu |
... | ... | @@ -197,6 +236,8 @@ |
197 | 236 | init_completion(&dev->kobj_unregister); |
198 | 237 | |
199 | 238 | mutex_lock(&cpuidle_lock); |
239 | + | |
240 | + poll_idle_init(dev); | |
200 | 241 | |
201 | 242 | per_cpu(cpuidle_devices, dev->cpu) = dev; |
202 | 243 | list_add(&dev->device_list, &cpuidle_detected_devices); |
include/linux/cpuidle.h
... | ... | @@ -46,9 +46,10 @@ |
46 | 46 | /* Idle State Flags */ |
47 | 47 | #define CPUIDLE_FLAG_TIME_VALID (0x01) /* is residency time measurable? */ |
48 | 48 | #define CPUIDLE_FLAG_CHECK_BM (0x02) /* BM activity will exit state */ |
49 | -#define CPUIDLE_FLAG_SHALLOW (0x10) /* low latency, minimal savings */ | |
50 | -#define CPUIDLE_FLAG_BALANCED (0x20) /* medium latency, moderate savings */ | |
51 | -#define CPUIDLE_FLAG_DEEP (0x40) /* high latency, large savings */ | |
49 | +#define CPUIDLE_FLAG_POLL (0x10) /* no latency, no savings */ | |
50 | +#define CPUIDLE_FLAG_SHALLOW (0x20) /* low latency, minimal savings */ | |
51 | +#define CPUIDLE_FLAG_BALANCED (0x40) /* medium latency, moderate savings */ | |
52 | +#define CPUIDLE_FLAG_DEEP (0x80) /* high latency, large savings */ | |
52 | 53 | |
53 | 54 | #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000) |
54 | 55 | |
... | ... | @@ -176,6 +177,12 @@ |
176 | 177 | {return 0;} |
177 | 178 | static inline void cpuidle_unregister_governor(struct cpuidle_governor *gov) { } |
178 | 179 | |
180 | +#endif | |
181 | + | |
182 | +#ifdef CONFIG_ARCH_HAS_CPU_RELAX | |
183 | +#define CPUIDLE_DRIVER_STATE_START 1 | |
184 | +#else | |
185 | +#define CPUIDLE_DRIVER_STATE_START 0 | |
179 | 186 | #endif |
180 | 187 | |
181 | 188 | #endif /* _LINUX_CPUIDLE_H */ |