@@ -271,8 +271,11 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
if (!pr)
return -EINVAL;
+ /* Newer dual-core CPUs use C1E instead of C2 and C3 and
+ * usually do not have _CST definitions or PBLK entries.
+ * ACPI specification allows for that so return zero here */
if (!pr->pblk)
- return -ENODEV;
+ return 0;
/* if info is obtained from pblk/fadt, type equals state */
pr->power.states[ACPI_STATE_C2].type = ACPI_STATE_C2;
@@ -312,6 +315,11 @@ static int acpi_processor_get_power_info_default(struct acpi_processor *pr)
pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1;
pr->power.states[ACPI_STATE_C1].valid = 1;
pr->power.states[ACPI_STATE_C1].entry_method = ACPI_CSTATE_HALT;
+ snprintf(pr->power.states[ACPI_STATE_C1].desc, ACPI_CX_DESC_LEN, "ACPI HLT");
+ if (!pr->power.states[ACPI_STATE_C1].latency)
+ pr->power.states[ACPI_STATE_C1].latency = 1;
+ if (!pr->power.states[ACPI_STATE_C1].power)
+ pr->power.states[ACPI_STATE_C1].power = 1000;
}
/* the C0 state only exists as a filler in our array */
pr->power.states[ACPI_STATE_C0].valid = 1;
@@ -653,24 +661,23 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr)
memset(pr->power.states, 0, sizeof(pr->power.states));
result = acpi_processor_get_power_info_cst(pr);
- if (result == -ENODEV)
- result = acpi_processor_get_power_info_fadt(pr);
-
if (result)
- return result;
+ result = acpi_processor_get_power_info_fadt(pr);
+ /* No valid _CST and FADT, but C1 must be supported,
+ * so here we go */
acpi_processor_get_power_info_default(pr);
pr->power.count = acpi_processor_power_verify(pr);
/*
- * if one state of type C2 or C3 is available, mark this
+ * if one state of type C1(e), C2 or C3 is available, mark this
* CPU as being "idle manageable"
*/
for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
if (pr->power.states[i].valid) {
pr->power.count = i;
- if (pr->power.states[i].type >= ACPI_STATE_C2)
+ if (pr->power.states[i].type >= ACPI_STATE_C1)
pr->flags.power = 1;
}
}
@@ -821,6 +828,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
{
ktime_t kt1, kt2;
s64 idle_time;
+ s64 sleep_ticks = 0;
struct acpi_processor *pr;
struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
@@ -844,10 +852,14 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
kt2 = ktime_get_real();
idle_time = ktime_to_us(ktime_sub(kt2, kt1));
+ sleep_ticks = us_to_pm_timer_ticks(idle_time);
+
local_irq_enable();
+
cx->usage++;
- lapic_timer_state_broadcast(pr, cx, 0);
+ lapic_timer_state_broadcast(pr, cx, 0);
+ cx->time += sleep_ticks;
return idle_time;
}