aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafał Bilski <rafalbilski@interia.pl>2006-12-24 08:04:23 -0500
committerDave Jones <davej@redhat.com>2006-12-29 15:56:44 -0500
commit264166e604a7e14c278e31cadd1afb06a7d51a11 (patch)
tree335ec9254f885883482a407de8fb2ae2211300db
parent1cfe2014263a879691d0262935a2649c97a02559 (diff)
[CPUFREQ] Longhaul - Fix up powersaver assumptions.
ACPI PM2 register was fallback for "Longhaul ver. 1" CPU's. My assumption that this register isn't present at "PowerSaver" motherboards is so far true, but current code will not work correctly in other case. There are three possible supports: ACPI C3, PM2 and northbridge. That was my assumption that ACPI C3 and northbridge is for PS and northbridge and PM2 is for V1. In current code we can only check if it is ACPI support or not by port22_en. So remove port22_en and add longhaul_flags. If USE_ACPI_C3 and USE_NORTHBRIDGE are both clear then it means ACPI PM2 support. Also change order of support probe from ACPI C3, PM2, northbridge to ACPI C3, northbridge, ACPI PM2. Paranoid protection against port 0x22 cast as ACPI PM2 register. Bit 1 clear in such case - lockup on AGP DMA. And obvious (now) fixup for do_powersaver. Use cx->address only for ACPI C3 ("PowerSaver" processor using PM2 support). Signed-off-by: Rafaż Bilski <rafalbilski@interia.pl> Signed-off-by: Dave Jones <davej@redhat.com>
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c71
1 files changed, 38 insertions, 33 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 087e941b43de..fd70c77acc1c 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -52,6 +52,10 @@
52#define CPU_EZRA_T 4 52#define CPU_EZRA_T 4
53#define CPU_NEHEMIAH 5 53#define CPU_NEHEMIAH 5
54 54
55/* Flags */
56#define USE_ACPI_C3 (1 << 1)
57#define USE_NORTHBRIDGE (1 << 2)
58
55static int cpu_model; 59static int cpu_model;
56static unsigned int numscales=16; 60static unsigned int numscales=16;
57static unsigned int fsb; 61static unsigned int fsb;
@@ -68,7 +72,7 @@ static unsigned int minmult, maxmult;
68static int can_scale_voltage; 72static int can_scale_voltage;
69static struct acpi_processor *pr = NULL; 73static struct acpi_processor *pr = NULL;
70static struct acpi_processor_cx *cx = NULL; 74static struct acpi_processor_cx *cx = NULL;
71static int port22_en; 75static u8 longhaul_flags;
72 76
73/* Module parameters */ 77/* Module parameters */
74static int scale_voltage; 78static int scale_voltage;
@@ -80,7 +84,6 @@ static int ignore_latency;
80/* Clock ratios multiplied by 10 */ 84/* Clock ratios multiplied by 10 */
81static int clock_ratio[32]; 85static int clock_ratio[32];
82static int eblcr_table[32]; 86static int eblcr_table[32];
83static unsigned int highest_speed, lowest_speed; /* kHz */
84static int longhaul_version; 87static int longhaul_version;
85static struct cpufreq_frequency_table *longhaul_table; 88static struct cpufreq_frequency_table *longhaul_table;
86 89
@@ -178,7 +181,7 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
178 safe_halt(); 181 safe_halt();
179 /* Change frequency on next halt or sleep */ 182 /* Change frequency on next halt or sleep */
180 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); 183 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
181 if (port22_en) { 184 if (!cx_address) {
182 ACPI_FLUSH_CPU_CACHE(); 185 ACPI_FLUSH_CPU_CACHE();
183 /* Invoke C1 */ 186 /* Invoke C1 */
184 halt(); 187 halt();
@@ -189,7 +192,6 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
189 /* Dummy op - must do something useless after P_LVL3 read */ 192 /* Dummy op - must do something useless after P_LVL3 read */
190 t = inl(acpi_fadt.xpm_tmr_blk.address); 193 t = inl(acpi_fadt.xpm_tmr_blk.address);
191 } 194 }
192
193 /* Disable bus ratio bit */ 195 /* Disable bus ratio bit */
194 local_irq_disable(); 196 local_irq_disable();
195 longhaul.bits.RevisionKey = longhaul.bits.RevisionID; 197 longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
@@ -243,15 +245,14 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
243 outb(0xFF,0xA1); /* Overkill */ 245 outb(0xFF,0xA1); /* Overkill */
244 outb(0xFE,0x21); /* TMR0 only */ 246 outb(0xFE,0x21); /* TMR0 only */
245 247
246 if (pr->flags.bm_control) { 248 if (longhaul_flags & USE_NORTHBRIDGE) {
249 /* Disable AGP and PCI arbiters */
250 outb(3, 0x22);
251 } else if ((pr != NULL) && pr->flags.bm_control) {
247 /* Disable bus master arbitration */ 252 /* Disable bus master arbitration */
248 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1, 253 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1,
249 ACPI_MTX_DO_NOT_LOCK); 254 ACPI_MTX_DO_NOT_LOCK);
250 } else if (port22_en) {
251 /* Disable AGP and PCI arbiters */
252 outb(3, 0x22);
253 } 255 }
254
255 switch (longhaul_version) { 256 switch (longhaul_version) {
256 257
257 /* 258 /*
@@ -278,22 +279,25 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
278 * to work in practice. 279 * to work in practice.
279 */ 280 */
280 case TYPE_POWERSAVER: 281 case TYPE_POWERSAVER:
281 /* Don't allow wakeup */ 282 if (longhaul_flags & USE_ACPI_C3) {
282 acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0, 283 /* Don't allow wakeup */
283 ACPI_MTX_DO_NOT_LOCK); 284 acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0,
284 do_powersaver(cx->address, clock_ratio_index); 285 ACPI_MTX_DO_NOT_LOCK);
286 do_powersaver(cx->address, clock_ratio_index);
287 } else {
288 do_powersaver(0, clock_ratio_index);
289 }
285 break; 290 break;
286 } 291 }
287 292
288 if (pr->flags.bm_control) { 293 if (longhaul_flags & USE_NORTHBRIDGE) {
294 /* Enable arbiters */
295 outb(0, 0x22);
296 } else if ((pr != NULL) && pr->flags.bm_control) {
289 /* Enable bus master arbitration */ 297 /* Enable bus master arbitration */
290 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, 298 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0,
291 ACPI_MTX_DO_NOT_LOCK); 299 ACPI_MTX_DO_NOT_LOCK);
292 } else if (port22_en) {
293 /* Enable arbiters */
294 outb(0, 0x22);
295 } 300 }
296
297 outb(pic2_mask,0xA1); /* restore mask */ 301 outb(pic2_mask,0xA1); /* restore mask */
298 outb(pic1_mask,0x21); 302 outb(pic1_mask,0x21);
299 303
@@ -691,27 +695,32 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
691 /* Find ACPI data for processor */ 695 /* Find ACPI data for processor */
692 acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 696 acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
693 &longhaul_walk_callback, NULL, (void *)&pr); 697 &longhaul_walk_callback, NULL, (void *)&pr);
694 if (pr == NULL)
695 goto err_acpi;
696 698
697 if (longhaul_version == TYPE_POWERSAVER) { 699 /* Check ACPI support for C3 state */
698 /* Check ACPI support for C3 state */ 700 if ((pr != NULL) && (longhaul_version == TYPE_POWERSAVER)) {
699 cx = &pr->power.states[ACPI_STATE_C3]; 701 cx = &pr->power.states[ACPI_STATE_C3];
700 if (cx->address > 0 && 702 if (cx->address > 0 &&
701 (cx->latency <= 1000 || ignore_latency != 0) ) { 703 (cx->latency <= 1000 || ignore_latency != 0) ) {
704 longhaul_flags |= USE_ACPI_C3;
702 goto print_support_type; 705 goto print_support_type;
703 } 706 }
704 } 707 }
708 /* Check if northbridge is friendly */
709 if (enable_arbiter_disable()) {
710 longhaul_flags |= USE_NORTHBRIDGE;
711 goto print_support_type;
712 }
713
714 /* No ACPI C3 or we can't use it */
705 /* Check ACPI support for bus master arbiter disable */ 715 /* Check ACPI support for bus master arbiter disable */
706 if (!pr->flags.bm_control) { 716 if ((pr == NULL) || !(pr->flags.bm_control)) {
707 if (enable_arbiter_disable()) { 717 printk(KERN_ERR PFX
708 port22_en = 1; 718 "No ACPI support. Unsupported northbridge.\n");
709 } else { 719 return -ENODEV;
710 goto err_acpi;
711 }
712 } 720 }
721
713print_support_type: 722print_support_type:
714 if (!port22_en) { 723 if (!(longhaul_flags & USE_NORTHBRIDGE)) {
715 printk (KERN_INFO PFX "Using ACPI support.\n"); 724 printk (KERN_INFO PFX "Using ACPI support.\n");
716 } else { 725 } else {
717 printk (KERN_INFO PFX "Using northbridge support.\n"); 726 printk (KERN_INFO PFX "Using northbridge support.\n");
@@ -736,10 +745,6 @@ print_support_type:
736 cpufreq_frequency_table_get_attr(longhaul_table, policy->cpu); 745 cpufreq_frequency_table_get_attr(longhaul_table, policy->cpu);
737 746
738 return 0; 747 return 0;
739
740err_acpi:
741 printk(KERN_ERR PFX "No ACPI support. Unsupported northbridge. Aborting.\n");
742 return -ENODEV;
743} 748}
744 749
745static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy) 750static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy)