summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafał Bilski <rafalbilski@interia.pl>2007-05-17 22:39:02 +0200
committerDave Jones <davej@redhat.com>2007-05-29 16:56:39 -0400
commit489dc5cb18932d3cedaef03e84890475db17a843 (patch)
tree32f97c945aa842daa8d7ffeccc6633c6377980ea
parent1b11d4ca6d9d7ea3ace9d241e52cc5fe3cfe3d8f (diff)
downloadlwn-489dc5cb18932d3cedaef03e84890475db17a843.tar.gz
lwn-489dc5cb18932d3cedaef03e84890475db17a843.zip
[CPUFREQ] Longhaul - Check ACPI "BM DMA in progress" bit
It is good idea to wait for PCI bus to become idle before frequency change. Thanks to ACPI it is possible. It makes sense only when northbridge support is in use because it is only case in which we can disable arbiter after check if PCI bus is busy. Signed-off-by: Rafal Bilski <rafalbilski@interia.pl> Signed-off-by: Dave Jones <davej@redhat.com>
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 504c6c9107d5..ff4829666472 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -254,6 +254,8 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
struct cpufreq_freqs freqs;
unsigned long flags;
unsigned int pic1_mask, pic2_mask;
+ u32 bm_status = 0;
+ u32 bm_timeout = 100000;
if (old_ratio == clock_ratio_index)
return;
@@ -284,6 +286,18 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
outb(0xFF,0xA1); /* Overkill */
outb(0xFE,0x21); /* TMR0 only */
+ /* Wait while PCI bus is busy. */
+ if (longhaul_flags & USE_NORTHBRIDGE
+ || ((pr != NULL) && pr->flags.bm_control)) {
+ acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status);
+ while (bm_status && bm_timeout) {
+ acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
+ bm_timeout--;
+ acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS,
+ &bm_status);
+ }
+ }
+
if (longhaul_flags & USE_NORTHBRIDGE) {
/* Disable AGP and PCI arbiters */
outb(3, 0x22);
@@ -335,6 +349,10 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
freqs.new = calc_speed(longhaul_get_cpu_mult());
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ if (!bm_timeout)
+ printk(KERN_INFO PFX "Warning: Timeout while waiting for "
+ "idle PCI bus.\n");
}
/*