diff options
author | Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> | 2007-11-20 01:48:00 +0100 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-11-20 03:25:23 +0100 |
commit | c9c860e5349ef62cd9226694b3aa625ef66f504e (patch) | |
tree | 19ce87dd625256a6a3c73b6eac147b3818d93b18 /drivers/acpi/processor_idle.c | |
parent | cpuidle: remove unused exports (diff) | |
download | linux-c9c860e5349ef62cd9226694b3aa625ef66f504e.tar.xz linux-c9c860e5349ef62cd9226694b3aa625ef66f504e.zip |
cpuidle: fix C3 for no bus-master control case
Port 18eab8550397f1f3d4b8b2c5257c88dae25d58ed
(Enable C3 even when PM2_control is zero) to cpuidle.
Without this patch, some systems will notice a regression
when enabling CPU_IDLE -- C3 would no longer be available.
Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/processor_idle.c')
-rw-r--r-- | drivers/acpi/processor_idle.c | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 0cad56ca342b..943a88069001 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -1514,23 +1514,38 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, } else { acpi_idle_update_bm_rld(pr, cx); - spin_lock(&c3_lock); - c3_cpu_count++; - /* Disable bus master arbitration when all CPUs are in C3 */ - if (c3_cpu_count == num_online_cpus()) - acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); - spin_unlock(&c3_lock); + /* + * disable bus master + * bm_check implies we need ARB_DIS + * !bm_check implies we need cache flush + * bm_control implies whether we can do ARB_DIS + * + * That leaves a case where bm_check is set and bm_control is + * not set. In that case we cannot do much, we enter C3 + * without doing anything. + */ + if (pr->flags.bm_check && pr->flags.bm_control) { + spin_lock(&c3_lock); + c3_cpu_count++; + /* Disable bus master arbitration when all CPUs are in C3 */ + if (c3_cpu_count == num_online_cpus()) + acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); + spin_unlock(&c3_lock); + } else if (!pr->flags.bm_check) { + ACPI_FLUSH_CPU_CACHE(); + } t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); acpi_idle_do_entry(cx); t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); - spin_lock(&c3_lock); /* Re-enable bus master arbitration */ - if (c3_cpu_count == num_online_cpus()) + if (pr->flags.bm_check && pr->flags.bm_control) { + spin_lock(&c3_lock); acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); - c3_cpu_count--; - spin_unlock(&c3_lock); + c3_cpu_count--; + spin_unlock(&c3_lock); + } } #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) |