Blame view

drivers/idle/intel_idle.c 14.6 KB
267171726   Len Brown   intel_idle: nativ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  /*
   * intel_idle.c - native hardware idle loop for modern Intel processors
   *
   * Copyright (c) 2010, Intel Corporation.
   * Len Brown <len.brown@intel.com>
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms and conditions of the GNU General Public License,
   * version 2, as published by the Free Software Foundation.
   *
   * This program is distributed in the hope it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   * more details.
   *
   * You should have received a copy of the GNU General Public License along with
   * this program; if not, write to the Free Software Foundation, Inc.,
   * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
   */
  
  /*
   * intel_idle is a cpuidle driver that loads on specific Intel processors
   * in lieu of the legacy ACPI processor_idle driver.  The intent is to
   * make Linux more efficient on these processors, as intel_idle knows
   * more than ACPI, as well as make Linux more immune to ACPI BIOS bugs.
   */
  
  /*
   * Design Assumptions
   *
   * All CPUs have same idle states as boot CPU
   *
   * Chipset BM_STS (bus master status) bit is a NOP
   *	for preventing entry into deep C-stats
   */
  
  /*
   * Known limitations
   *
   * The driver currently initializes for_each_online_cpu() upon modprobe.
   * It it unaware of subsequent processors hot-added to the system.
   * This means that if you boot with maxcpus=n and later online
   * processors above n, those processors will use C1 only.
   *
   * ACPI has a .suspend hack to turn off deep c-statees during suspend
   * to avoid complications with the lapic timer workaround.
   * Have not seen issues with suspend, but may need same workaround here.
   *
   * There is currently no kernel-based automatic probing/loading mechanism
   * if the driver is built as a module.
   */
  
  /* un-comment DEBUG to enable pr_debug() statements */
  #define DEBUG
  
  #include <linux/kernel.h>
  #include <linux/cpuidle.h>
  #include <linux/clockchips.h>
  #include <linux/hrtimer.h>	/* ktime_get_real() */
  #include <trace/events/power.h>
  #include <linux/sched.h>
2a2d31c8d   Shaohua Li   intel_idle: open ...
62
63
  #include <linux/notifier.h>
  #include <linux/cpu.h>
7c52d5517   Paul Gortmaker   x86: fix up files...
64
  #include <linux/module.h>
bc83cccc7   H. Peter Anvin   x86, mwait: Move ...
65
  #include <asm/mwait.h>
14796fca2   Len Brown   intel_idle: disab...
66
  #include <asm/msr.h>
267171726   Len Brown   intel_idle: nativ...
67
68
69
  
  #define INTEL_IDLE_VERSION "0.4"
  #define PREFIX "intel_idle: "
267171726   Len Brown   intel_idle: nativ...
70
71
72
73
74
75
  static struct cpuidle_driver intel_idle_driver = {
  	.name = "intel_idle",
  	.owner = THIS_MODULE,
  };
  /* intel_idle.max_cstate=0 disables driver */
  static int max_cstate = MWAIT_MAX_NUM_CSTATES - 1;
267171726   Len Brown   intel_idle: nativ...
76

c4236282e   Len Brown   intel_idle: delet...
77
  static unsigned int mwait_substates;
267171726   Len Brown   intel_idle: nativ...
78

2a2d31c8d   Shaohua Li   intel_idle: open ...
79
  #define LAPIC_TIMER_ALWAYS_RELIABLE 0xFFFFFFFF
267171726   Len Brown   intel_idle: nativ...
80
  /* Reliable LAPIC Timer States, bit 1 for C1 etc.  */
d13780d43   Len Brown   intel_idle: add i...
81
  static unsigned int lapic_timer_reliable_states = (1 << 1);	 /* Default to only C1 */
267171726   Len Brown   intel_idle: nativ...
82

3265eba0b   Namhyung Kim   intel_idle: add m...
83
  static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
46bcfad7a   Deepthi Dharwar   cpuidle: Single/G...
84
85
  static int intel_idle(struct cpuidle_device *dev,
  			struct cpuidle_driver *drv, int index);
267171726   Len Brown   intel_idle: nativ...
86
87
88
89
  
  static struct cpuidle_state *cpuidle_state_table;
  
  /*
14796fca2   Len Brown   intel_idle: disab...
90
91
92
93
94
95
   * Hardware C-state auto-demotion may not always be optimal.
   * Indicate which enable bits to clear here.
   */
  static unsigned long long auto_demotion_disable_flags;
  
  /*
956d033fb   Len Brown   cpuidle: CPUIDLE_...
96
97
98
99
100
101
102
103
   * Set this flag for states where the HW flushes the TLB for us
   * and so we don't need cross-calls to keep it consistent.
   * If this flag is set, SW flushes the TLB, so even if the
   * HW doesn't do the flushing, this flag is safe to use.
   */
  #define CPUIDLE_FLAG_TLB_FLUSHED	0x10000
  
  /*
267171726   Len Brown   intel_idle: nativ...
104
105
106
107
108
109
110
   * States are indexed by the cstate number,
   * which is also the index into the MWAIT hint array.
   * Thus C0 is a dummy.
   */
  static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
  	{ /* MWAIT C0 */ },
  	{ /* MWAIT C1 */
15e123e5d   Thomas Renninger   intel_idle: Renam...
111
  		.name = "C1-NHM",
267171726   Len Brown   intel_idle: nativ...
112
  		.desc = "MWAIT 0x00",
267171726   Len Brown   intel_idle: nativ...
113
114
  		.flags = CPUIDLE_FLAG_TIME_VALID,
  		.exit_latency = 3,
267171726   Len Brown   intel_idle: nativ...
115
116
117
  		.target_residency = 6,
  		.enter = &intel_idle },
  	{ /* MWAIT C2 */
15e123e5d   Thomas Renninger   intel_idle: Renam...
118
  		.name = "C3-NHM",
267171726   Len Brown   intel_idle: nativ...
119
  		.desc = "MWAIT 0x10",
6110a1f43   Suresh Siddha   intel_idle: Volun...
120
  		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
267171726   Len Brown   intel_idle: nativ...
121
  		.exit_latency = 20,
267171726   Len Brown   intel_idle: nativ...
122
123
124
  		.target_residency = 80,
  		.enter = &intel_idle },
  	{ /* MWAIT C3 */
15e123e5d   Thomas Renninger   intel_idle: Renam...
125
  		.name = "C6-NHM",
267171726   Len Brown   intel_idle: nativ...
126
  		.desc = "MWAIT 0x20",
6110a1f43   Suresh Siddha   intel_idle: Volun...
127
  		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
267171726   Len Brown   intel_idle: nativ...
128
  		.exit_latency = 200,
267171726   Len Brown   intel_idle: nativ...
129
130
131
  		.target_residency = 800,
  		.enter = &intel_idle },
  };
d13780d43   Len Brown   intel_idle: add i...
132
133
134
  static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
  	{ /* MWAIT C0 */ },
  	{ /* MWAIT C1 */
15e123e5d   Thomas Renninger   intel_idle: Renam...
135
  		.name = "C1-SNB",
d13780d43   Len Brown   intel_idle: add i...
136
  		.desc = "MWAIT 0x00",
d13780d43   Len Brown   intel_idle: add i...
137
138
  		.flags = CPUIDLE_FLAG_TIME_VALID,
  		.exit_latency = 1,
ddbd550d5   Len Brown   intel_idle: updat...
139
  		.target_residency = 1,
d13780d43   Len Brown   intel_idle: add i...
140
141
  		.enter = &intel_idle },
  	{ /* MWAIT C2 */
15e123e5d   Thomas Renninger   intel_idle: Renam...
142
  		.name = "C3-SNB",
d13780d43   Len Brown   intel_idle: add i...
143
  		.desc = "MWAIT 0x10",
00527cc6b   Len Brown   Merge branch 'int...
144
  		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
d13780d43   Len Brown   intel_idle: add i...
145
  		.exit_latency = 80,
ddbd550d5   Len Brown   intel_idle: updat...
146
  		.target_residency = 211,
d13780d43   Len Brown   intel_idle: add i...
147
148
  		.enter = &intel_idle },
  	{ /* MWAIT C3 */
15e123e5d   Thomas Renninger   intel_idle: Renam...
149
  		.name = "C6-SNB",
d13780d43   Len Brown   intel_idle: add i...
150
  		.desc = "MWAIT 0x20",
00527cc6b   Len Brown   Merge branch 'int...
151
  		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
d13780d43   Len Brown   intel_idle: add i...
152
  		.exit_latency = 104,
ddbd550d5   Len Brown   intel_idle: updat...
153
  		.target_residency = 345,
d13780d43   Len Brown   intel_idle: add i...
154
155
  		.enter = &intel_idle },
  	{ /* MWAIT C4 */
15e123e5d   Thomas Renninger   intel_idle: Renam...
156
  		.name = "C7-SNB",
d13780d43   Len Brown   intel_idle: add i...
157
  		.desc = "MWAIT 0x30",
00527cc6b   Len Brown   Merge branch 'int...
158
  		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
d13780d43   Len Brown   intel_idle: add i...
159
  		.exit_latency = 109,
ddbd550d5   Len Brown   intel_idle: updat...
160
  		.target_residency = 345,
d13780d43   Len Brown   intel_idle: add i...
161
162
  		.enter = &intel_idle },
  };
267171726   Len Brown   intel_idle: nativ...
163
164
165
  static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
  	{ /* MWAIT C0 */ },
  	{ /* MWAIT C1 */
15e123e5d   Thomas Renninger   intel_idle: Renam...
166
  		.name = "C1-ATM",
267171726   Len Brown   intel_idle: nativ...
167
  		.desc = "MWAIT 0x00",
267171726   Len Brown   intel_idle: nativ...
168
169
  		.flags = CPUIDLE_FLAG_TIME_VALID,
  		.exit_latency = 1,
267171726   Len Brown   intel_idle: nativ...
170
171
172
  		.target_residency = 4,
  		.enter = &intel_idle },
  	{ /* MWAIT C2 */
15e123e5d   Thomas Renninger   intel_idle: Renam...
173
  		.name = "C2-ATM",
267171726   Len Brown   intel_idle: nativ...
174
  		.desc = "MWAIT 0x10",
267171726   Len Brown   intel_idle: nativ...
175
176
  		.flags = CPUIDLE_FLAG_TIME_VALID,
  		.exit_latency = 20,
267171726   Len Brown   intel_idle: nativ...
177
178
179
180
  		.target_residency = 80,
  		.enter = &intel_idle },
  	{ /* MWAIT C3 */ },
  	{ /* MWAIT C4 */
15e123e5d   Thomas Renninger   intel_idle: Renam...
181
  		.name = "C4-ATM",
267171726   Len Brown   intel_idle: nativ...
182
  		.desc = "MWAIT 0x30",
6110a1f43   Suresh Siddha   intel_idle: Volun...
183
  		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
267171726   Len Brown   intel_idle: nativ...
184
  		.exit_latency = 100,
267171726   Len Brown   intel_idle: nativ...
185
186
187
188
  		.target_residency = 400,
  		.enter = &intel_idle },
  	{ /* MWAIT C5 */ },
  	{ /* MWAIT C6 */
15e123e5d   Thomas Renninger   intel_idle: Renam...
189
  		.name = "C6-ATM",
7fcca7d90   Len Brown   intel_idle: enabl...
190
  		.desc = "MWAIT 0x52",
6110a1f43   Suresh Siddha   intel_idle: Volun...
191
  		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
7fcca7d90   Len Brown   intel_idle: enabl...
192
  		.exit_latency = 140,
7fcca7d90   Len Brown   intel_idle: enabl...
193
194
  		.target_residency = 560,
  		.enter = &intel_idle },
267171726   Len Brown   intel_idle: nativ...
195
  };
4202735e8   Deepthi Dharwar   cpuidle: Split cp...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
  static int get_driver_data(int cstate)
  {
  	int driver_data;
  	switch (cstate) {
  
  	case 1:	/* MWAIT C1 */
  		driver_data = 0x00;
  		break;
  	case 2:	/* MWAIT C2 */
  		driver_data = 0x10;
  		break;
  	case 3:	/* MWAIT C3 */
  		driver_data = 0x20;
  		break;
  	case 4:	/* MWAIT C4 */
  		driver_data = 0x30;
  		break;
  	case 5:	/* MWAIT C5 */
  		driver_data = 0x40;
  		break;
  	case 6:	/* MWAIT C6 */
  		driver_data = 0x52;
  		break;
  	default:
  		driver_data = 0x00;
  	}
  	return driver_data;
  }
267171726   Len Brown   intel_idle: nativ...
224
225
226
  /**
   * intel_idle
   * @dev: cpuidle_device
46bcfad7a   Deepthi Dharwar   cpuidle: Single/G...
227
   * @drv: cpuidle driver
e978aa7d7   Deepthi Dharwar   cpuidle: Move dev...
228
   * @index: index of cpuidle state
267171726   Len Brown   intel_idle: nativ...
229
230
   *
   */
46bcfad7a   Deepthi Dharwar   cpuidle: Single/G...
231
232
  static int intel_idle(struct cpuidle_device *dev,
  		struct cpuidle_driver *drv, int index)
267171726   Len Brown   intel_idle: nativ...
233
234
  {
  	unsigned long ecx = 1; /* break on interrupt flag */
46bcfad7a   Deepthi Dharwar   cpuidle: Single/G...
235
  	struct cpuidle_state *state = &drv->states[index];
4202735e8   Deepthi Dharwar   cpuidle: Split cp...
236
237
  	struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
  	unsigned long eax = (unsigned long)cpuidle_get_statedata(state_usage);
267171726   Len Brown   intel_idle: nativ...
238
239
240
241
242
243
  	unsigned int cstate;
  	ktime_t kt_before, kt_after;
  	s64 usec_delta;
  	int cpu = smp_processor_id();
  
  	cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1;
267171726   Len Brown   intel_idle: nativ...
244
  	local_irq_disable();
6110a1f43   Suresh Siddha   intel_idle: Volun...
245
  	/*
c8381cc3d   Len Brown   intel_idle: simpl...
246
247
  	 * leave_mm() to avoid costly and often unnecessary wakeups
  	 * for flushing the user TLB's associated with the active mm.
6110a1f43   Suresh Siddha   intel_idle: Volun...
248
  	 */
c8381cc3d   Len Brown   intel_idle: simpl...
249
  	if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED)
6110a1f43   Suresh Siddha   intel_idle: Volun...
250
  		leave_mm(cpu);
267171726   Len Brown   intel_idle: nativ...
251
252
253
254
255
256
  	if (!(lapic_timer_reliable_states & (1 << (cstate))))
  		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
  
  	kt_before = ktime_get_real();
  
  	stop_critical_timings();
267171726   Len Brown   intel_idle: nativ...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
  	if (!need_resched()) {
  
  		__monitor((void *)&current_thread_info()->flags, 0, 0);
  		smp_mb();
  		if (!need_resched())
  			__mwait(eax, ecx);
  	}
  
  	start_critical_timings();
  
  	kt_after = ktime_get_real();
  	usec_delta = ktime_to_us(ktime_sub(kt_after, kt_before));
  
  	local_irq_enable();
  
  	if (!(lapic_timer_reliable_states & (1 << (cstate))))
  		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
e978aa7d7   Deepthi Dharwar   cpuidle: Move dev...
274
275
276
277
  	/* Update cpuidle counters */
  	dev->last_residency = (int)usec_delta;
  
  	return index;
267171726   Len Brown   intel_idle: nativ...
278
  }
2a2d31c8d   Shaohua Li   intel_idle: open ...
279
280
281
282
283
284
285
286
287
288
  static void __setup_broadcast_timer(void *arg)
  {
  	unsigned long reason = (unsigned long)arg;
  	int cpu = smp_processor_id();
  
  	reason = reason ?
  		CLOCK_EVT_NOTIFY_BROADCAST_ON : CLOCK_EVT_NOTIFY_BROADCAST_OFF;
  
  	clockevents_notify(reason, &cpu);
  }
ec30f343d   Shaohua Li   fix a shutdown re...
289
  static int setup_broadcast_cpuhp_notify(struct notifier_block *n,
2a2d31c8d   Shaohua Li   intel_idle: open ...
290
291
292
293
294
295
296
297
298
  		unsigned long action, void *hcpu)
  {
  	int hotcpu = (unsigned long)hcpu;
  
  	switch (action & 0xf) {
  	case CPU_ONLINE:
  		smp_call_function_single(hotcpu, __setup_broadcast_timer,
  			(void *)true, 1);
  		break;
2a2d31c8d   Shaohua Li   intel_idle: open ...
299
300
301
  	}
  	return NOTIFY_OK;
  }
ec30f343d   Shaohua Li   fix a shutdown re...
302
  static struct notifier_block setup_broadcast_notifier = {
2a2d31c8d   Shaohua Li   intel_idle: open ...
303
304
  	.notifier_call = setup_broadcast_cpuhp_notify,
  };
14796fca2   Len Brown   intel_idle: disab...
305
306
307
308
309
310
311
312
  static void auto_demotion_disable(void *dummy)
  {
  	unsigned long long msr_bits;
  
  	rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
  	msr_bits &= ~auto_demotion_disable_flags;
  	wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
  }
267171726   Len Brown   intel_idle: nativ...
313
314
315
316
317
  /*
   * intel_idle_probe()
   */
  static int intel_idle_probe(void)
  {
c4236282e   Len Brown   intel_idle: delet...
318
  	unsigned int eax, ebx, ecx;
267171726   Len Brown   intel_idle: nativ...
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
  
  	if (max_cstate == 0) {
  		pr_debug(PREFIX "disabled
  ");
  		return -EPERM;
  	}
  
  	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
  		return -ENODEV;
  
  	if (!boot_cpu_has(X86_FEATURE_MWAIT))
  		return -ENODEV;
  
  	if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF)
  		return -ENODEV;
c4236282e   Len Brown   intel_idle: delet...
334
  	cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &mwait_substates);
267171726   Len Brown   intel_idle: nativ...
335
336
337
338
  
  	if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
  		!(ecx & CPUID5_ECX_INTERRUPT_BREAK))
  			return -ENODEV;
267171726   Len Brown   intel_idle: nativ...
339

c4236282e   Len Brown   intel_idle: delet...
340
341
  	pr_debug(PREFIX "MWAIT substates: 0x%x
  ", mwait_substates);
267171726   Len Brown   intel_idle: nativ...
342

267171726   Len Brown   intel_idle: nativ...
343
344
345
346
347
348
349
350
351
352
  
  	if (boot_cpu_data.x86 != 6)	/* family 6 */
  		return -ENODEV;
  
  	switch (boot_cpu_data.x86_model) {
  
  	case 0x1A:	/* Core i7, Xeon 5500 series */
  	case 0x1E:	/* Core i7 and i5 Processor - Lynnfield Jasper Forest */
  	case 0x1F:	/* Core i7 and i5 Processor - Nehalem */
  	case 0x2E:	/* Nehalem-EX Xeon */
ec67a2ba3   Len Brown   intel_idle: add s...
353
  	case 0x2F:	/* Westmere-EX Xeon */
267171726   Len Brown   intel_idle: nativ...
354
355
356
  	case 0x25:	/* Westmere */
  	case 0x2C:	/* Westmere */
  		cpuidle_state_table = nehalem_cstates;
14796fca2   Len Brown   intel_idle: disab...
357
358
  		auto_demotion_disable_flags =
  			(NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE);
267171726   Len Brown   intel_idle: nativ...
359
360
361
  		break;
  
  	case 0x1C:	/* 28 - Atom Processor */
bfb53ccf1   Len Brown   intel_idle: disab...
362
363
  		cpuidle_state_table = atom_cstates;
  		break;
4725fd3ce   Arjan van de Ven   intel_idle: recog...
364
  	case 0x26:	/* 38 - Lincroft Atom Processor */
267171726   Len Brown   intel_idle: nativ...
365
  		cpuidle_state_table = atom_cstates;
bfb53ccf1   Len Brown   intel_idle: disab...
366
  		auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE;
267171726   Len Brown   intel_idle: nativ...
367
  		break;
d13780d43   Len Brown   intel_idle: add i...
368
369
370
371
  
  	case 0x2A:	/* SNB */
  	case 0x2D:	/* SNB Xeon */
  		cpuidle_state_table = snb_cstates;
d13780d43   Len Brown   intel_idle: add i...
372
  		break;
267171726   Len Brown   intel_idle: nativ...
373
374
375
376
377
378
379
  
  	default:
  		pr_debug(PREFIX "does not run on family %d model %d
  ",
  			boot_cpu_data.x86, boot_cpu_data.x86_model);
  		return -ENODEV;
  	}
56b9aea3b   Len Brown   intel_idle: recog...
380
  	if (boot_cpu_has(X86_FEATURE_ARAT))	/* Always Reliable APIC Timer */
2a2d31c8d   Shaohua Li   intel_idle: open ...
381
382
383
384
385
  		lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
  	else {
  		smp_call_function(__setup_broadcast_timer, (void *)true, 1);
  		register_cpu_notifier(&setup_broadcast_notifier);
  	}
56b9aea3b   Len Brown   intel_idle: recog...
386

267171726   Len Brown   intel_idle: nativ...
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
  	pr_debug(PREFIX "v" INTEL_IDLE_VERSION
  		" model 0x%X
  ", boot_cpu_data.x86_model);
  
  	pr_debug(PREFIX "lapic_timer_reliable_states 0x%x
  ",
  		lapic_timer_reliable_states);
  	return 0;
  }
  
  /*
   * intel_idle_cpuidle_devices_uninit()
   * unregister, free cpuidle_devices
   */
  static void intel_idle_cpuidle_devices_uninit(void)
  {
  	int i;
  	struct cpuidle_device *dev;
  
  	for_each_online_cpu(i) {
  		dev = per_cpu_ptr(intel_idle_cpuidle_devices, i);
  		cpuidle_unregister_device(dev);
  	}
  
  	free_percpu(intel_idle_cpuidle_devices);
  	return;
  }
  /*
46bcfad7a   Deepthi Dharwar   cpuidle: Single/G...
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
   * intel_idle_cpuidle_driver_init()
   * allocate, initialize cpuidle_states
   */
  static int intel_idle_cpuidle_driver_init(void)
  {
  	int cstate;
  	struct cpuidle_driver *drv = &intel_idle_driver;
  
  	drv->state_count = 1;
  
  	for (cstate = 1; cstate < MWAIT_MAX_NUM_CSTATES; ++cstate) {
  		int num_substates;
  
  		if (cstate > max_cstate) {
  			printk(PREFIX "max_cstate %d reached
  ",
  				max_cstate);
  			break;
  		}
  
  		/* does the state exist in CPUID.MWAIT? */
  		num_substates = (mwait_substates >> ((cstate) * 4))
  					& MWAIT_SUBSTATE_MASK;
  		if (num_substates == 0)
  			continue;
  		/* is the state not enabled? */
  		if (cpuidle_state_table[cstate].enter == NULL) {
  			/* does the driver not know about the state? */
  			if (*cpuidle_state_table[cstate].name == '\0')
  				pr_debug(PREFIX "unaware of model 0x%x"
  					" MWAIT %d please"
  					" contact lenb@kernel.org",
  				boot_cpu_data.x86_model, cstate);
  			continue;
  		}
  
  		if ((cstate > 2) &&
  			!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
  			mark_tsc_unstable("TSC halts in idle"
  					" states deeper than C2");
  
  		drv->states[drv->state_count] =	/* structure copy */
  			cpuidle_state_table[cstate];
  
  		drv->state_count += 1;
  	}
  
  	if (auto_demotion_disable_flags)
  		smp_call_function(auto_demotion_disable, NULL, 1);
  
  	return 0;
  }
  
  
  /*
267171726   Len Brown   intel_idle: nativ...
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
   * intel_idle_cpuidle_devices_init()
   * allocate, initialize, register cpuidle_devices
   */
  static int intel_idle_cpuidle_devices_init(void)
  {
  	int i, cstate;
  	struct cpuidle_device *dev;
  
  	intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
  	if (intel_idle_cpuidle_devices == NULL)
  		return -ENOMEM;
  
  	for_each_online_cpu(i) {
  		dev = per_cpu_ptr(intel_idle_cpuidle_devices, i);
  
  		dev->state_count = 1;
  
  		for (cstate = 1; cstate < MWAIT_MAX_NUM_CSTATES; ++cstate) {
  			int num_substates;
  
  			if (cstate > max_cstate) {
  				printk(PREFIX "max_cstate %d reached
  ",
  					max_cstate);
  				break;
  			}
  
  			/* does the state exist in CPUID.MWAIT? */
c4236282e   Len Brown   intel_idle: delet...
498
  			num_substates = (mwait_substates >> ((cstate) * 4))
267171726   Len Brown   intel_idle: nativ...
499
500
501
502
503
  						& MWAIT_SUBSTATE_MASK;
  			if (num_substates == 0)
  				continue;
  			/* is the state not enabled? */
  			if (cpuidle_state_table[cstate].enter == NULL) {
267171726   Len Brown   intel_idle: nativ...
504
505
  				continue;
  			}
4202735e8   Deepthi Dharwar   cpuidle: Split cp...
506
507
  			dev->states_usage[dev->state_count].driver_data =
  				(void *)get_driver_data(cstate);
267171726   Len Brown   intel_idle: nativ...
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
  
  			dev->state_count += 1;
  		}
  
  		dev->cpu = i;
  		if (cpuidle_register_device(dev)) {
  			pr_debug(PREFIX "cpuidle_register_device %d failed!
  ",
  				 i);
  			intel_idle_cpuidle_devices_uninit();
  			return -EIO;
  		}
  	}
  
  	return 0;
  }
  
  
  static int __init intel_idle_init(void)
  {
  	int retval;
d18960494   Thomas Renninger   ACPI, intel_idle:...
529
530
531
  	/* Do not load intel_idle at all for now if idle= is passed */
  	if (boot_option_idle_override != IDLE_NO_OVERRIDE)
  		return -ENODEV;
267171726   Len Brown   intel_idle: nativ...
532
533
534
  	retval = intel_idle_probe();
  	if (retval)
  		return retval;
46bcfad7a   Deepthi Dharwar   cpuidle: Single/G...
535
  	intel_idle_cpuidle_driver_init();
267171726   Len Brown   intel_idle: nativ...
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
  	retval = cpuidle_register_driver(&intel_idle_driver);
  	if (retval) {
  		printk(KERN_DEBUG PREFIX "intel_idle yielding to %s",
  			cpuidle_get_driver()->name);
  		return retval;
  	}
  
  	retval = intel_idle_cpuidle_devices_init();
  	if (retval) {
  		cpuidle_unregister_driver(&intel_idle_driver);
  		return retval;
  	}
  
  	return 0;
  }
  
  static void __exit intel_idle_exit(void)
  {
  	intel_idle_cpuidle_devices_uninit();
  	cpuidle_unregister_driver(&intel_idle_driver);
2a2d31c8d   Shaohua Li   intel_idle: open ...
556
557
558
559
  	if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE) {
  		smp_call_function(__setup_broadcast_timer, (void *)false, 1);
  		unregister_cpu_notifier(&setup_broadcast_notifier);
  	}
267171726   Len Brown   intel_idle: nativ...
560
561
562
563
564
  	return;
  }
  
  module_init(intel_idle_init);
  module_exit(intel_idle_exit);
267171726   Len Brown   intel_idle: nativ...
565
  module_param(max_cstate, int, 0444);
267171726   Len Brown   intel_idle: nativ...
566
567
568
569
  
  MODULE_AUTHOR("Len Brown <len.brown@intel.com>");
  MODULE_DESCRIPTION("Cpuidle driver for Intel Hardware v" INTEL_IDLE_VERSION);
  MODULE_LICENSE("GPL");