aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/processor_idle.c25
-rw-r--r--drivers/cpuidle/cpuidle.c11
-rw-r--r--drivers/cpuidle/sysfs.c19
-rw-r--r--drivers/idle/intel_idle.c46
4 files changed, 65 insertions, 36 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 9cd08cecb347..b98c75285690 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -745,14 +745,13 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx)
745 * 745 *
746 * This is equivalent to the HALT instruction. 746 * This is equivalent to the HALT instruction.
747 */ 747 */
748static int acpi_idle_enter_c1(struct cpuidle_device *dev, 748static int acpi_idle_enter_c1(struct cpuidle_device *dev, int index)
749 int index)
750{ 749{
751 ktime_t kt1, kt2; 750 ktime_t kt1, kt2;
752 s64 idle_time; 751 s64 idle_time;
753 struct acpi_processor *pr; 752 struct acpi_processor *pr;
754 struct cpuidle_state *state = &dev->states[index]; 753 struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
755 struct acpi_processor_cx *cx = cpuidle_get_statedata(state); 754 struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
756 755
757 pr = __this_cpu_read(processors); 756 pr = __this_cpu_read(processors);
758 dev->last_residency = 0; 757 dev->last_residency = 0;
@@ -790,12 +789,11 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
790 * @dev: the target CPU 789 * @dev: the target CPU
791 * @index: the index of suggested state 790 * @index: the index of suggested state
792 */ 791 */
793static int acpi_idle_enter_simple(struct cpuidle_device *dev, 792static int acpi_idle_enter_simple(struct cpuidle_device *dev, int index)
794 int index)
795{ 793{
796 struct acpi_processor *pr; 794 struct acpi_processor *pr;
797 struct cpuidle_state *state = &dev->states[index]; 795 struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
798 struct acpi_processor_cx *cx = cpuidle_get_statedata(state); 796 struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
799 ktime_t kt1, kt2; 797 ktime_t kt1, kt2;
800 s64 idle_time_ns; 798 s64 idle_time_ns;
801 s64 idle_time; 799 s64 idle_time;
@@ -875,12 +873,11 @@ static DEFINE_SPINLOCK(c3_lock);
875 * 873 *
876 * If BM is detected, the deepest non-C3 idle state is entered instead. 874 * If BM is detected, the deepest non-C3 idle state is entered instead.
877 */ 875 */
878static int acpi_idle_enter_bm(struct cpuidle_device *dev, 876static int acpi_idle_enter_bm(struct cpuidle_device *dev, int index)
879 int index)
880{ 877{
881 struct acpi_processor *pr; 878 struct acpi_processor *pr;
882 struct cpuidle_state *state = &dev->states[index]; 879 struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
883 struct acpi_processor_cx *cx = cpuidle_get_statedata(state); 880 struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
884 ktime_t kt1, kt2; 881 ktime_t kt1, kt2;
885 s64 idle_time_ns; 882 s64 idle_time_ns;
886 s64 idle_time; 883 s64 idle_time;
@@ -1004,6 +1001,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
1004 int i, count = CPUIDLE_DRIVER_STATE_START; 1001 int i, count = CPUIDLE_DRIVER_STATE_START;
1005 struct acpi_processor_cx *cx; 1002 struct acpi_processor_cx *cx;
1006 struct cpuidle_state *state; 1003 struct cpuidle_state *state;
1004 struct cpuidle_state_usage *state_usage;
1007 struct cpuidle_device *dev = &pr->power.dev; 1005 struct cpuidle_device *dev = &pr->power.dev;
1008 1006
1009 if (!pr->flags.power_setup_done) 1007 if (!pr->flags.power_setup_done)
@@ -1026,6 +1024,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
1026 for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) { 1024 for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
1027 cx = &pr->power.states[i]; 1025 cx = &pr->power.states[i];
1028 state = &dev->states[count]; 1026 state = &dev->states[count];
1027 state_usage = &dev->states_usage[count];
1029 1028
1030 if (!cx->valid) 1029 if (!cx->valid)
1031 continue; 1030 continue;
@@ -1036,7 +1035,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
1036 !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) 1035 !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
1037 continue; 1036 continue;
1038#endif 1037#endif
1039 cpuidle_set_statedata(state, cx); 1038 cpuidle_set_statedata(state_usage, cx);
1040 1039
1041 snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i); 1040 snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i);
1042 strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN); 1041 strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index f66bcf9bfe93..7127e92fa8a1 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -105,9 +105,9 @@ int cpuidle_idle_call(void)
105 /* This can be moved to within driver enter routine 105 /* This can be moved to within driver enter routine
106 * but that results in multiple copies of same code. 106 * but that results in multiple copies of same code.
107 */ 107 */
108 dev->states[entered_state].time += 108 dev->states_usage[entered_state].time +=
109 (unsigned long long)dev->last_residency; 109 (unsigned long long)dev->last_residency;
110 dev->states[entered_state].usage++; 110 dev->states_usage[entered_state].usage++;
111 } 111 }
112 112
113 /* give the governor an opportunity to reflect on the outcome */ 113 /* give the governor an opportunity to reflect on the outcome */
@@ -186,8 +186,9 @@ static int poll_idle(struct cpuidle_device *dev, int index)
186static void poll_idle_init(struct cpuidle_device *dev) 186static void poll_idle_init(struct cpuidle_device *dev)
187{ 187{
188 struct cpuidle_state *state = &dev->states[0]; 188 struct cpuidle_state *state = &dev->states[0];
189 struct cpuidle_state_usage *state_usage = &dev->states_usage[0];
189 190
190 cpuidle_set_statedata(state, NULL); 191 cpuidle_set_statedata(state_usage, NULL);
191 192
192 snprintf(state->name, CPUIDLE_NAME_LEN, "POLL"); 193 snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
193 snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE"); 194 snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
@@ -235,8 +236,8 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
235 goto fail_sysfs; 236 goto fail_sysfs;
236 237
237 for (i = 0; i < dev->state_count; i++) { 238 for (i = 0; i < dev->state_count; i++) {
238 dev->states[i].usage = 0; 239 dev->states_usage[i].usage = 0;
239 dev->states[i].time = 0; 240 dev->states_usage[i].time = 0;
240 } 241 }
241 dev->last_residency = 0; 242 dev->last_residency = 0;
242 243
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index be7917ec40c9..8a1ace104476 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -216,7 +216,8 @@ static struct kobj_type ktype_cpuidle = {
216 216
217struct cpuidle_state_attr { 217struct cpuidle_state_attr {
218 struct attribute attr; 218 struct attribute attr;
219 ssize_t (*show)(struct cpuidle_state *, char *); 219 ssize_t (*show)(struct cpuidle_state *, \
220 struct cpuidle_state_usage *, char *);
220 ssize_t (*store)(struct cpuidle_state *, const char *, size_t); 221 ssize_t (*store)(struct cpuidle_state *, const char *, size_t);
221}; 222};
222 223
@@ -224,19 +225,22 @@ struct cpuidle_state_attr {
224static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0444, show, NULL) 225static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0444, show, NULL)
225 226
226#define define_show_state_function(_name) \ 227#define define_show_state_function(_name) \
227static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \ 228static ssize_t show_state_##_name(struct cpuidle_state *state, \
229 struct cpuidle_state_usage *state_usage, char *buf) \
228{ \ 230{ \
229 return sprintf(buf, "%u\n", state->_name);\ 231 return sprintf(buf, "%u\n", state->_name);\
230} 232}
231 233
232#define define_show_state_ull_function(_name) \ 234#define define_show_state_ull_function(_name) \
233static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \ 235static ssize_t show_state_##_name(struct cpuidle_state *state, \
236 struct cpuidle_state_usage *state_usage, char *buf) \
234{ \ 237{ \
235 return sprintf(buf, "%llu\n", state->_name);\ 238 return sprintf(buf, "%llu\n", state_usage->_name);\
236} 239}
237 240
238#define define_show_state_str_function(_name) \ 241#define define_show_state_str_function(_name) \
239static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \ 242static ssize_t show_state_##_name(struct cpuidle_state *state, \
243 struct cpuidle_state_usage *state_usage, char *buf) \
240{ \ 244{ \
241 if (state->_name[0] == '\0')\ 245 if (state->_name[0] == '\0')\
242 return sprintf(buf, "<null>\n");\ 246 return sprintf(buf, "<null>\n");\
@@ -269,16 +273,18 @@ static struct attribute *cpuidle_state_default_attrs[] = {
269 273
270#define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj) 274#define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
271#define kobj_to_state(k) (kobj_to_state_obj(k)->state) 275#define kobj_to_state(k) (kobj_to_state_obj(k)->state)
276#define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage)
272#define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr) 277#define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr)
273static ssize_t cpuidle_state_show(struct kobject * kobj, 278static ssize_t cpuidle_state_show(struct kobject * kobj,
274 struct attribute * attr ,char * buf) 279 struct attribute * attr ,char * buf)
275{ 280{
276 int ret = -EIO; 281 int ret = -EIO;
277 struct cpuidle_state *state = kobj_to_state(kobj); 282 struct cpuidle_state *state = kobj_to_state(kobj);
283 struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj);
278 struct cpuidle_state_attr * cattr = attr_to_stateattr(attr); 284 struct cpuidle_state_attr * cattr = attr_to_stateattr(attr);
279 285
280 if (cattr->show) 286 if (cattr->show)
281 ret = cattr->show(state, buf); 287 ret = cattr->show(state, state_usage, buf);
282 288
283 return ret; 289 return ret;
284} 290}
@@ -323,6 +329,7 @@ int cpuidle_add_state_sysfs(struct cpuidle_device *device)
323 if (!kobj) 329 if (!kobj)
324 goto error_state; 330 goto error_state;
325 kobj->state = &device->states[i]; 331 kobj->state = &device->states[i];
332 kobj->state_usage = &device->states_usage[i];
326 init_completion(&kobj->kobj_unregister); 333 init_completion(&kobj->kobj_unregister);
327 334
328 ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle, &device->kobj, 335 ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle, &device->kobj,
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index a1c888d2216a..3aa8d4cb6dca 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -109,7 +109,6 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
109 { /* MWAIT C1 */ 109 { /* MWAIT C1 */
110 .name = "C1-NHM", 110 .name = "C1-NHM",
111 .desc = "MWAIT 0x00", 111 .desc = "MWAIT 0x00",
112 .driver_data = (void *) 0x00,
113 .flags = CPUIDLE_FLAG_TIME_VALID, 112 .flags = CPUIDLE_FLAG_TIME_VALID,
114 .exit_latency = 3, 113 .exit_latency = 3,
115 .target_residency = 6, 114 .target_residency = 6,
@@ -117,7 +116,6 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
117 { /* MWAIT C2 */ 116 { /* MWAIT C2 */
118 .name = "C3-NHM", 117 .name = "C3-NHM",
119 .desc = "MWAIT 0x10", 118 .desc = "MWAIT 0x10",
120 .driver_data = (void *) 0x10,
121 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 119 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
122 .exit_latency = 20, 120 .exit_latency = 20,
123 .target_residency = 80, 121 .target_residency = 80,
@@ -125,7 +123,6 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
125 { /* MWAIT C3 */ 123 { /* MWAIT C3 */
126 .name = "C6-NHM", 124 .name = "C6-NHM",
127 .desc = "MWAIT 0x20", 125 .desc = "MWAIT 0x20",
128 .driver_data = (void *) 0x20,
129 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 126 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
130 .exit_latency = 200, 127 .exit_latency = 200,
131 .target_residency = 800, 128 .target_residency = 800,
@@ -137,7 +134,6 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
137 { /* MWAIT C1 */ 134 { /* MWAIT C1 */
138 .name = "C1-SNB", 135 .name = "C1-SNB",
139 .desc = "MWAIT 0x00", 136 .desc = "MWAIT 0x00",
140 .driver_data = (void *) 0x00,
141 .flags = CPUIDLE_FLAG_TIME_VALID, 137 .flags = CPUIDLE_FLAG_TIME_VALID,
142 .exit_latency = 1, 138 .exit_latency = 1,
143 .target_residency = 1, 139 .target_residency = 1,
@@ -145,7 +141,6 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
145 { /* MWAIT C2 */ 141 { /* MWAIT C2 */
146 .name = "C3-SNB", 142 .name = "C3-SNB",
147 .desc = "MWAIT 0x10", 143 .desc = "MWAIT 0x10",
148 .driver_data = (void *) 0x10,
149 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 144 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
150 .exit_latency = 80, 145 .exit_latency = 80,
151 .target_residency = 211, 146 .target_residency = 211,
@@ -153,7 +148,6 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
153 { /* MWAIT C3 */ 148 { /* MWAIT C3 */
154 .name = "C6-SNB", 149 .name = "C6-SNB",
155 .desc = "MWAIT 0x20", 150 .desc = "MWAIT 0x20",
156 .driver_data = (void *) 0x20,
157 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 151 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
158 .exit_latency = 104, 152 .exit_latency = 104,
159 .target_residency = 345, 153 .target_residency = 345,
@@ -161,7 +155,6 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
161 { /* MWAIT C4 */ 155 { /* MWAIT C4 */
162 .name = "C7-SNB", 156 .name = "C7-SNB",
163 .desc = "MWAIT 0x30", 157 .desc = "MWAIT 0x30",
164 .driver_data = (void *) 0x30,
165 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 158 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
166 .exit_latency = 109, 159 .exit_latency = 109,
167 .target_residency = 345, 160 .target_residency = 345,
@@ -173,7 +166,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
173 { /* MWAIT C1 */ 166 { /* MWAIT C1 */
174 .name = "C1-ATM", 167 .name = "C1-ATM",
175 .desc = "MWAIT 0x00", 168 .desc = "MWAIT 0x00",
176 .driver_data = (void *) 0x00,
177 .flags = CPUIDLE_FLAG_TIME_VALID, 169 .flags = CPUIDLE_FLAG_TIME_VALID,
178 .exit_latency = 1, 170 .exit_latency = 1,
179 .target_residency = 4, 171 .target_residency = 4,
@@ -181,7 +173,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
181 { /* MWAIT C2 */ 173 { /* MWAIT C2 */
182 .name = "C2-ATM", 174 .name = "C2-ATM",
183 .desc = "MWAIT 0x10", 175 .desc = "MWAIT 0x10",
184 .driver_data = (void *) 0x10,
185 .flags = CPUIDLE_FLAG_TIME_VALID, 176 .flags = CPUIDLE_FLAG_TIME_VALID,
186 .exit_latency = 20, 177 .exit_latency = 20,
187 .target_residency = 80, 178 .target_residency = 80,
@@ -190,7 +181,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
190 { /* MWAIT C4 */ 181 { /* MWAIT C4 */
191 .name = "C4-ATM", 182 .name = "C4-ATM",
192 .desc = "MWAIT 0x30", 183 .desc = "MWAIT 0x30",
193 .driver_data = (void *) 0x30,
194 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 184 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
195 .exit_latency = 100, 185 .exit_latency = 100,
196 .target_residency = 400, 186 .target_residency = 400,
@@ -199,13 +189,41 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
199 { /* MWAIT C6 */ 189 { /* MWAIT C6 */
200 .name = "C6-ATM", 190 .name = "C6-ATM",
201 .desc = "MWAIT 0x52", 191 .desc = "MWAIT 0x52",
202 .driver_data = (void *) 0x52,
203 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 192 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
204 .exit_latency = 140, 193 .exit_latency = 140,
205 .target_residency = 560, 194 .target_residency = 560,
206 .enter = &intel_idle }, 195 .enter = &intel_idle },
207}; 196};
208 197
198static int get_driver_data(int cstate)
199{
200 int driver_data;
201 switch (cstate) {
202
203 case 1: /* MWAIT C1 */
204 driver_data = 0x00;
205 break;
206 case 2: /* MWAIT C2 */
207 driver_data = 0x10;
208 break;
209 case 3: /* MWAIT C3 */
210 driver_data = 0x20;
211 break;
212 case 4: /* MWAIT C4 */
213 driver_data = 0x30;
214 break;
215 case 5: /* MWAIT C5 */
216 driver_data = 0x40;
217 break;
218 case 6: /* MWAIT C6 */
219 driver_data = 0x52;
220 break;
221 default:
222 driver_data = 0x00;
223 }
224 return driver_data;
225}
226
209/** 227/**
210 * intel_idle 228 * intel_idle
211 * @dev: cpuidle_device 229 * @dev: cpuidle_device
@@ -216,7 +234,8 @@ static int intel_idle(struct cpuidle_device *dev, int index)
216{ 234{
217 unsigned long ecx = 1; /* break on interrupt flag */ 235 unsigned long ecx = 1; /* break on interrupt flag */
218 struct cpuidle_state *state = &dev->states[index]; 236 struct cpuidle_state *state = &dev->states[index];
219 unsigned long eax = (unsigned long)cpuidle_get_statedata(state); 237 struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
238 unsigned long eax = (unsigned long)cpuidle_get_statedata(state_usage);
220 unsigned int cstate; 239 unsigned int cstate;
221 ktime_t kt_before, kt_after; 240 ktime_t kt_before, kt_after;
222 s64 usec_delta; 241 s64 usec_delta;
@@ -451,6 +470,9 @@ static int intel_idle_cpuidle_devices_init(void)
451 dev->states[dev->state_count] = /* structure copy */ 470 dev->states[dev->state_count] = /* structure copy */
452 cpuidle_state_table[cstate]; 471 cpuidle_state_table[cstate];
453 472
473 dev->states_usage[dev->state_count].driver_data =
474 (void *)get_driver_data(cstate);
475
454 dev->state_count += 1; 476 dev->state_count += 1;
455 } 477 }
456 478