cpuidle: Do not use poll_idle unless user asks for it
[safe/jmp/linux-2.6] / drivers / cpuidle / governors / menu.c
1 /*
2  * menu.c - the menu idle governor
3  *
4  * Copyright (C) 2006-2007 Adam Belay <abelay@novell.com>
5  *
6  * This code is licenced under the GPL.
7  */
8
9 #include <linux/kernel.h>
10 #include <linux/cpuidle.h>
11 #include <linux/pm_qos_params.h>
12 #include <linux/time.h>
13 #include <linux/ktime.h>
14 #include <linux/hrtimer.h>
15 #include <linux/tick.h>
16
17 #define BREAK_FUZZ      4       /* 4 us */
18
19 struct menu_device {
20         int             last_state_idx;
21
22         unsigned int    expected_us;
23         unsigned int    predicted_us;
24         unsigned int    last_measured_us;
25         unsigned int    elapsed_us;
26 };
27
28 static DEFINE_PER_CPU(struct menu_device, menu_devices);
29
30 /**
31  * menu_select - selects the next idle state to enter
32  * @dev: the CPU
33  */
34 static int menu_select(struct cpuidle_device *dev)
35 {
36         struct menu_device *data = &__get_cpu_var(menu_devices);
37         int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
38         int i;
39
40         /* Special case when user has set very strict latency requirement */
41         if (unlikely(latency_req == 0)) {
42                 data->last_state_idx = 0;
43                 return 0;
44         }
45
46         /* determine the expected residency time */
47         data->expected_us =
48                 (u32) ktime_to_ns(tick_nohz_get_sleep_length()) / 1000;
49
50         /* find the deepest idle state that satisfies our constraints */
51         for (i = CPUIDLE_DRIVER_STATE_START + 1; i < dev->state_count; i++) {
52                 struct cpuidle_state *s = &dev->states[i];
53
54                 if (s->target_residency > data->expected_us)
55                         break;
56                 if (s->target_residency > data->predicted_us)
57                         break;
58                 if (s->exit_latency > latency_req)
59                         break;
60         }
61
62         data->last_state_idx = i - 1;
63         return i - 1;
64 }
65
66 /**
67  * menu_reflect - attempts to guess what happened after entry
68  * @dev: the CPU
69  *
70  * NOTE: it's important to be fast here because this operation will add to
71  *       the overall exit latency.
72  */
73 static void menu_reflect(struct cpuidle_device *dev)
74 {
75         struct menu_device *data = &__get_cpu_var(menu_devices);
76         int last_idx = data->last_state_idx;
77         unsigned int measured_us =
78                 cpuidle_get_last_residency(dev) + data->elapsed_us;
79         struct cpuidle_state *target = &dev->states[last_idx];
80
81         /*
82          * Ugh, this idle state doesn't support residency measurements, so we
83          * are basically lost in the dark.  As a compromise, assume we slept
84          * for one full standard timer tick.  However, be aware that this
85          * could potentially result in a suboptimal state transition.
86          */
87         if (!(target->flags & CPUIDLE_FLAG_TIME_VALID))
88                 measured_us = USEC_PER_SEC / HZ;
89
90         /* Predict time remaining until next break event */
91         if (measured_us + BREAK_FUZZ < data->expected_us - target->exit_latency) {
92                 data->predicted_us = max(measured_us, data->last_measured_us);
93                 data->last_measured_us = measured_us;
94                 data->elapsed_us = 0;
95         } else {
96                 if (data->elapsed_us < data->elapsed_us + measured_us)
97                         data->elapsed_us = measured_us;
98                 else
99                         data->elapsed_us = -1;
100                 data->predicted_us = max(measured_us, data->last_measured_us);
101         }
102 }
103
104 /**
105  * menu_enable_device - scans a CPU's states and does setup
106  * @dev: the CPU
107  */
108 static int menu_enable_device(struct cpuidle_device *dev)
109 {
110         struct menu_device *data = &per_cpu(menu_devices, dev->cpu);
111
112         memset(data, 0, sizeof(struct menu_device));
113
114         return 0;
115 }
116
117 static struct cpuidle_governor menu_governor = {
118         .name =         "menu",
119         .rating =       20,
120         .enable =       menu_enable_device,
121         .select =       menu_select,
122         .reflect =      menu_reflect,
123         .owner =        THIS_MODULE,
124 };
125
126 /**
127  * init_menu - initializes the governor
128  */
129 static int __init init_menu(void)
130 {
131         return cpuidle_register_governor(&menu_governor);
132 }
133
134 /**
135  * exit_menu - exits the governor
136  */
137 static void __exit exit_menu(void)
138 {
139         cpuidle_unregister_governor(&menu_governor);
140 }
141
142 MODULE_LICENSE("GPL");
143 module_init(init_menu);
144 module_exit(exit_menu);