.enter = &intel_idle },
};
-- -- static int get_driver_data(int cstate)
++ +++static long 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;
+}
+
/**
* intel_idle
* @dev: cpuidle_device
- * @state: cpuidle state
+ * @drv: cpuidle driver
+ * @index: index of cpuidle state
*
++ +++ * Must be called under local_irq_disable().
*/
-static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
+static int intel_idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
{
unsigned long ecx = 1; /* break on interrupt flag */
- unsigned long eax = (unsigned long)cpuidle_get_statedata(state);
+ struct cpuidle_state *state = &drv->states[index];
+ struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+ unsigned long eax = (unsigned long)cpuidle_get_statedata(state_usage);
unsigned int cstate;
ktime_t kt_before, kt_after;
s64 usec_delta;
return;
}
/*
- * intel_idle_cpuidle_devices_init()
+ * 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\n",
+ 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);
++ +++ on_each_cpu(auto_demotion_disable, NULL, 1);
+
+ return 0;
+}
+
+
+/*
--- - * intel_idle_cpuidle_devices_init()
+++ ++ * intel_idle_cpu_init()
* allocate, initialize, register cpuidle_devices
+++ ++ * @cpu: cpu/core to initialize
*/
--- --static int intel_idle_cpuidle_devices_init(void)
+++ ++int intel_idle_cpu_init(int cpu)
{
--- -- int i, cstate;
+++ ++ int 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 = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
--- - dev->state_count = 1;
- for_each_online_cpu(i) {
- dev = per_cpu_ptr(intel_idle_cpuidle_devices, i);
+++ ++ dev->state_count = 1;
- 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\n",
- 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");
+++ ++ for (cstate = 1; cstate < MWAIT_MAX_NUM_CSTATES; ++cstate) {
+++ ++ int num_substates;
--- - if (cstate > max_cstate) {
--- - printk(PREFIX "max_cstate %d reached\n",
--- - max_cstate);
--- - break;
--- - }
- dev->states[dev->state_count] = /* structure copy */
- cpuidle_state_table[cstate];
+++ ++ if (cstate > max_cstate) {
+++ ++ printk(PREFIX "max_cstate %d reached\n",
+++ ++ 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) {
--- - continue;
--- - }
+++ ++ /* 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)
+++ ++ continue;
+
--- - dev->states_usage[dev->state_count].driver_data =
--- - (void *)get_driver_data(cstate);
+++ ++ dev->states_usage[dev->state_count].driver_data =
+++ ++ (void *)get_driver_data(cstate);
dev->state_count += 1;
}
+++ ++ dev->cpu = cpu;
--- -- dev->cpu = i;
--- -- if (cpuidle_register_device(dev)) {
--- -- pr_debug(PREFIX "cpuidle_register_device %d failed!\n",
--- -- i);
--- -- intel_idle_cpuidle_devices_uninit();
--- -- return -EIO;
--- -- }
+++ ++ if (cpuidle_register_device(dev)) {
+++ ++ pr_debug(PREFIX "cpuidle_register_device %d failed!\n", cpu);
+++ ++ intel_idle_cpuidle_devices_uninit();
+++ ++ return -EIO;
}
- smp_call_function(auto_demotion_disable, NULL, 1);
+
+++ + if (auto_demotion_disable_flags)
+++ ++ smp_call_function_single(cpu, auto_demotion_disable, NULL, 1);
+++ +
return 0;
}