summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-06-10 14:19:02 +1000
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-09 21:33:35 -0700
commit0086b5ec7834b78358dea3f713275a9ae2b229ec (patch)
tree589b4166efe6ab929ee25b20b2e89935efba504e
parent243cd55e021baf28babdd88112ac03ae5cd4bb9c (diff)
downloadop-kernel-dev-0086b5ec7834b78358dea3f713275a9ae2b229ec.zip
op-kernel-dev-0086b5ec7834b78358dea3f713275a9ae2b229ec.tar.gz
[PATCH] ppc32: Fix nasty sleep/wakeup problem
Despite all the care lately in making the powermac sleep/wakeup as robust as possible, there is still a nasty related to the use of cpufreq on PMU based machines. Unfortunately, it affects paulus old powerbook so I have to fix it :) We didn't manage to understand what is precisely going on, it leads to memory corruption and might have to do with RAM not beeing properly refreshed when a cpufreq transition is done right before the sleep. The best workaround (and less intrusive at this point) we could come up with is included in this patch. We basically do _not_ force a switch to high speed on suspend anymore (that is what is causing the problem) on those machines. We still force a speed switch on wakeup (since we don't know what speed we are coming back from sleep at, and that seems to work fine). Since, during this short interval, the actual CPU speed might be incorrect, we also hack around by multiplying loops_per_jiffy by 2 (max speed factor on those machines) during early wakeup stage to make sure udelay's during that time aren't too short. For after 2.6.12, we'll change udelay implementation to use the CPU timebase (which is always constant) instead like we do on ppc64 and thus get rid of all those problems. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/ppc/platforms/pmac_cpufreq.c7
-rw-r--r--drivers/macintosh/via-pmu.c6
2 files changed, 11 insertions, 2 deletions
diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c
index 937f46d..5fdd4f6 100644
--- a/arch/ppc/platforms/pmac_cpufreq.c
+++ b/arch/ppc/platforms/pmac_cpufreq.c
@@ -83,7 +83,7 @@ static u32 frequency_gpio;
static u32 slew_done_gpio;
static int no_schedule;
static int has_cpu_l2lve;
-
+static int is_pmu_based;
/* There are only two frequency states for each processor. Values
* are in kHz for the time being.
@@ -463,7 +463,7 @@ static int __pmac pmac_cpufreq_suspend(struct cpufreq_policy *policy, u32 state)
*/
no_schedule = 1;
sleep_freq = cur_freq;
- if (cur_freq == low_freq)
+ if (cur_freq == low_freq && !is_pmu_based)
do_set_cpu_speed(CPUFREQ_HIGH, 0);
return 0;
}
@@ -588,6 +588,7 @@ static int __pmac pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)
return 1;
hi_freq = (*value) / 1000;
set_speed_proc = pmu_set_cpu_speed;
+ is_pmu_based = 1;
return 0;
}
@@ -692,6 +693,7 @@ static int __init pmac_cpufreq_setup(void)
hi_freq = cur_freq;
low_freq = 400000;
set_speed_proc = pmu_set_cpu_speed;
+ is_pmu_based = 1;
}
/* Else check for TiPb 400 & 500 */
else if (machine_is_compatible("PowerBook3,2")) {
@@ -703,6 +705,7 @@ static int __init pmac_cpufreq_setup(void)
hi_freq = cur_freq;
low_freq = 300000;
set_speed_proc = pmu_set_cpu_speed;
+ is_pmu_based = 1;
}
/* Else check for 750FX */
else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000)
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index bb9f404..b941ee2 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -2593,6 +2593,9 @@ powerbook_sleep_Core99(void)
/* Restore VIA */
restore_via_state();
+ /* tweak LPJ before cpufreq is there */
+ loops_per_jiffy *= 2;
+
/* Restore video */
pmac_call_early_video_resume();
@@ -2613,6 +2616,9 @@ powerbook_sleep_Core99(void)
pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
pmu_wait_complete(&req);
+ /* Restore LPJ, cpufreq will adjust the cpu frequency */
+ loops_per_jiffy /= 2;
+
pmac_wakeup_devices();
return 0;
OpenPOWER on IntegriCloud