From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-05 18:30:27
Hi!
Here's my latest patchset for suspend to disk on powermac. It also contains
a whole bunch of cleanups and fixes in various other places some of which
are CCed to Andrew (who will hopefully put them into -mm).
Other than that, thanks to the mpic resume/suspend code it appears to work
quite well. Thanks to Michael Buesch for testing with PREEMPT enabled which
uncovered another bug with cpu "hotplug" (where I still don't understand why
the preempt_count is messed up on resume but not when I put a CPU off- and
online via sysfs.)
To actually get proper suspend for a G5 powermac with an Onyx codec you need
to apply the patch at http://patchwork.ozlabs.org/linuxppc/patch?id=8683
Any comments are appreciated, especially on the patch that actually
implements the snapshot code ("powermac: suspend to disk on G5.")
johannes
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-05 18:30:28
Pages that aren't RAM obviously cannot be saved during suspend-to-disk
so skip them.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Andrew Morton <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Pavel Machek requested this be put into -mm for some more
testing although he says it seems fine.
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-05 18:30:29
When the windfarm thread gets a suspend signal it will die instead of
freezing. This fixes it.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Andrew Morton <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Please apply to -mm.
@@ -94,8 +94,6 @@ static int wf_thread_func(void *data)DBG("wf: thread started\n");while(!kthread_should_stop()){-try_to_freeze();-if(time_after_eq(jiffies,next)){wf_notify(WF_EVENT_TICK,NULL);if(wf_overtemp){
@@ -118,8 +116,8 @@ static int wf_thread_func(void *data)if(delay<=HZ)schedule_timeout_interruptible(delay);-/* there should be no signal, but oh well */-if(signal_pending(current)){+/* there should be no non-suspend signal, but oh well */+if(signal_pending(current)&&!try_to_freeze()){printk(KERN_WARNING"windfarm: thread got sigl !\n");break;}--
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-05 18:30:30
kernel/irq.c contains a comment that speaks of -1 and -2 as interrupt
numbers. Replace by NO_IRQ and NO_IRQ_IGNORE.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Andrew Morton <redacted>
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-05 18:30:31
This patch cleans up the powermac PIC initialisation code so that for G5
powermacs we don't even compile the old pmac pic file.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Andrew Morton <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Tested on powerbook and powermac, please apply to -mm.
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-05 18:30:32
This patch removes the time suspend/restore code that was done through
a PMU notifier in arch/platforms/powermac/time.c.
Instead, we introduce arch/powerpc/sysdev/timer.c which creates a sys
device and handles time of day suspend/resume through that.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Andrew Morton <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Tested on powermac with suspend-to-disk and powerbook with
suspend-to-{ram,disk}, please apply to -mm.
@@ -13,6 +13,8 @@ obj-$(CONFIG_FSL_SOC) += fsl_soc.oobj-$(CONFIG_TSI108_BRIDGE)+=tsi108_pci.otsi108_dev.oobj-$(CONFIG_QUICC_ENGINE)+=qe_lib/obj-$(CONFIG_MTD)+=rom.o+# contains only the suspend handler for time+obj-$(CONFIG_PM)+=timer.oifeq($(CONFIG_PPC_MERGE),y)obj-$(CONFIG_PPC_I8259)+=i8259.o---/dev/null1970-01-0100:00:00.000000000+0000+++mb-wireless/arch/powerpc/sysdev/timer.c2007-02-0514:24:37.624526864+0100
@@ -0,0 +1,70 @@+/*+*Commoncodetokeeptimewhenmachinesuspends.+*+*Copyright2007JohannesBerg<johannes@sipsolutions.net>+*+*GPLv2+*/++#include<linux/time.h>+#include<asm/rtc.h>++staticunsignedlongsuspend_rtc_time;++/*+*Resetthetimeafterasleep.+*/+staticinttimer_resume(structsys_device*dev)+{+structtimevaltv;+structtimespects;+structrtc_timecur_rtc_tm;+unsignedlongcur_rtc_time,diff;++/* get current RTC time and convert to seconds */+get_rtc_time(&cur_rtc_tm);+rtc_tm_to_time(&cur_rtc_tm,&cur_rtc_time);++diff=cur_rtc_time-suspend_rtc_time;++/* adjust time of day by seconds that elapsed while+*weweresuspended*/+do_gettimeofday(&tv);+ts.tv_sec=tv.tv_sec+diff;+ts.tv_nsec=tv.tv_usec*NSEC_PER_USEC;+do_settimeofday(&ts);++return0;+}++staticinttimer_suspend(structsys_device*dev,pm_message_tstate)+{+structrtc_timesuspend_rtc_tm;+WARN_ON(!ppc_md.get_rtc_time);++get_rtc_time(&suspend_rtc_tm);+rtc_tm_to_time(&suspend_rtc_tm,&suspend_rtc_time);++return0;+}++staticstructsysdev_classtimer_sysclass={+.resume=timer_resume,+.suspend=timer_suspend,+set_kset_name("timer"),+};++staticstructsys_devicedevice_timer={+.id=0,+.cls=&timer_sysclass,+};++staticinttime_init_device(void)+{+interror=sysdev_class_register(&timer_sysclass);+if(!error)+error=sysdev_register(&device_timer);+returnerror;+}++device_initcall(time_init_device);--
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-05 18:30:33
This adds mpic to the system devices and implements suspend
and resume for them. This is necessary to get interrupts for
modules back to where they were before a suspend to disk.
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
The first hunk is just a tiny whitespace cleanup.
Without this patch, i2sbus (built as a module) for example
doesn't work properly across a suspend-to-disk/resume cycle,
with this patch it works fine.
I'm not entirely sure if there should be some wait logic
after I restore the MPIC registers, it works as-is for me.
@@ -1123,7 +1123,7 @@ void __init mpic_init(struct mpic *mpic)/* Do the HT PIC fixups on U3 broken mpic */DBG("MPIC flags: %x\n",mpic->flags);if((mpic->flags&MPIC_BROKEN_U3)&&(mpic->flags&MPIC_PRIMARY))-mpic_scan_ht_pics(mpic);+mpic_scan_ht_pics(mpic);for(i=0;i<mpic->num_sources;i++){/* start with vector = source number, and masked */
@@ -1147,6 +1147,12 @@ void __init mpic_init(struct mpic *mpic)/* Set current processor priority to 0 */mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI),0);++#ifdef CONFIG_PM+/* allocate memory to save mpic state */+mpic->save_data=alloc_bootmem(mpic->num_sources*sizeof(structmpic_irq_save));+BUG_ON(mpic->save_data==NULL);+#endif}void__initmpic_set_clk_ratio(structmpic*mpic,u32clock_ratio)
@@ -243,6 +244,11 @@ struct mpic_reg_bank {#endif /* CONFIG_PPC_DCR */};+structmpic_irq_save{+u32vecprio,+dest;+};+/* The instance data of a given MPIC */structmpic{
@@ -302,6 +308,12 @@ struct mpic/* link */structmpic*next;++structsys_devicesysdev;++#ifdef CONFIG_PM+structmpic_irq_save*save_data;+#endif};/*--
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-05 18:30:34
This patch allows "hotplugging" of CPUs on G5 machines. CPUs that are
disabled are put into an idle loop with interrupts hard-disabled, to wake
them up again we kick them just like when bringing them up.
Maybe there's some way to actually turn off those CPUs even more?
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
@@ -898,7 +898,7 @@ void smp_core99_cpu_die(unsigned int cpucpu_dead[cpu]=0;}-#endif+#endif /* CONFIG_HOTPLUG_CPU && CONFIG_PP32 *//* Core99 Macs (dual G4s and G5s) */structsmp_ops_tcore99_smp_ops={
@@ -908,8 +908,16 @@ struct smp_ops_t core99_smp_ops = {.setup_cpu=smp_core99_setup_cpu,.give_timebase=smp_core99_give_timebase,.take_timebase=smp_core99_take_timebase,-#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32)+#if defined(CONFIG_HOTPLUG_CPU)+# if defined(CONFIG_PPC32).cpu_disable=smp_core99_cpu_disable,.cpu_die=smp_core99_cpu_die,+# endif+# if defined(CONFIG_PPC64)+.cpu_disable=generic_cpu_disable,+.cpu_die=generic_cpu_die,+/* intentionally do *NOT* assign cpu_enable,+*thegenericcodewillusekick_cputhen!*/+# endif#endif};---mb-wireless.orig/arch/powerpc/platforms/powermac/setup.c2007-02-0516:07:22.024524763+0100+++mb-wireless/arch/powerpc/platforms/powermac/setup.c2007-02-0516:07:50.784524763+0100
@@ -490,6 +490,9 @@ static int pmac_late_init(void)#ifdef CONFIG_SOFTWARE_SUSPENDpm_set_ops(&pmac_pm_ops);#endif /* CONFIG_SOFTWARE_SUSPEND */+/* this is udbg (which is __init) and we can later use it during+*cpuhotplug(insmp_core99_kick_cpu)*/+ppc_md.progress=NULL;return0;}
@@ -716,6 +719,33 @@ static int pmac_pci_probe_mode(struct pcreturnPCI_PROBE_NORMAL;returnPCI_PROBE_DEVTREE;}++#ifdef CONFIG_HOTPLUG_CPU+/* access per cpu vars from generic smp.c */+DECLARE_PER_CPU(int,cpu_state);++staticvoidpmac_cpu_die(void)+{+/* turn off as much as possible, we'll be+*kickedoutasthiswillonlybeinvoked+*oncore99platformsfornow...*/+hard_irq_disable();++printk(KERN_DEBUG"CPU#%d offline\n",smp_processor_id());+__get_cpu_var(cpu_state)=CPU_DEAD;+smp_wmb();+while(1){+ppc64_runlatch_off();+if(ppc_md.power_save){+ppc_md.power_save();+}else{+HMT_low();+HMT_very_low();+}+}+}+#endif+#endifstaticvoid__initpmac_init_irq(void)
@@ -558,6 +558,11 @@ int __devinit start_secondary(void *unuslocal_irq_enable();+/* it seems to be possible that we died from within+*aninterrupt...resetthein-irqcounts*/+task_thread_info(paca[cpu].__current)->preempt_count&=+~(SOFTIRQ_MASK|HARDIRQ_MASK);+cpu_idle();return0;}--
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-05 18:30:35
This implements suspend and resume code for the dart iommu.
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Just come to think of it, I made it conditional on
CONFIG_SOFTWARE_SUSPEND but could imagine that it should
instead depend on CONFIG_PM... There is no lowlevel suspend
to RAM code yet which would call this so for now it's
probably fine.
@@ -54,6 +54,9 @@ static unsigned long dart_tablesize;/* Virtual base address of the DART table */staticu32*dart_vbase;+#ifdef CONFIG_SOFTWARE_SUSPEND+staticu32*dart_copy;+#endif/* Mapped base address for the dart */staticunsignedint__iomem*dart;
@@ -346,6 +349,52 @@ void iommu_init_early_dart(void)pci_dma_ops=&dma_direct_ops;}+#ifdef CONFIG_SOFTWARE_SUSPEND+staticintiommu_init_late_dart(void)+{+unsignedlongi;+structpage*p;++/* this 16MB area is left unmapped because of caching+*considerations.thathappensearlysowecan'tmark+*itthere,doitnowinstead*/+for(i=0;i<(1<<24);i+=PAGE_SIZE)+SetPageNosave(virt_to_page((void*)((unsignedlong)dart_tablebase+i)));++/* if no dart table exists then we don't need to save it */+if(!dart_tablebase)+return0;++/* For suspend we need to copy the dart contents because+*itisnotpartoftheregularmapping(seeabove)and+*thusnotsavedautomatically.Thememoryforthiscopy+*mustbeallocatedearlybecauseweneed2MB.*/+p=alloc_pages(GFP_KERNEL,21-PAGE_SHIFT);+BUG_ON(!p);+dart_copy=page_address(p);++return0;+}++late_initcall(iommu_init_late_dart);++voidiommu_dart_save(void)+{+if(!dart_tablebase)+return;++memcpy(dart_copy,dart_vbase,2*1024*1024);+}++voidiommu_dart_restore(void)+{+if(!dart_tablebase)+return;++memcpy(dart_vbase,dart_copy,2*1024*1024);+dart_tlb_invalidate_all();+}+#endifvoid__initalloc_dart_table(void){---mb-wireless.orig/include/asm-powerpc/iommu.h2007-02-0514:24:05.014526864+0100+++mb-wireless/include/asm-powerpc/iommu.h2007-02-0514:24:40.684526864+0100
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-05 18:30:36
Next revision of my powermac G5 suspend to disk implementation. This part
didn't really change much except for fixes and cleanups.
I still have
set_context(current->active_mm->context.id, current->active_mm->pgd);
ifdef'ed out because I didn't know what it is doing and it works without :)
Can somebody explain what this is about and what the 64-bit equivalent would
be?
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-05 18:30:37
The original code here is wrong, it applies "previous" knowledge.
The way the cpufreq core is designed is that the policy for the
secondary CPU that comes online says that it must in fact not
use this policy but use the same as the other CPUs that are
listed, which in fact is CPU#0.
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: cpufreq list <redacted>
Cc: Jacob Shin <redacted>
---
Not tested yet but from what Jacob said this should work.
@@ -357,13 +357,13 @@ static unsigned int g5_cpufreq_get_speedstaticintg5_cpufreq_cpu_init(structcpufreq_policy*policy){-if(policy->cpu!=0)-return-ENODEV;-policy->governor=CPUFREQ_DEFAULT_GOVERNOR;policy->cpuinfo.transition_latency=CPUFREQ_ETERNAL;policy->cur=g5_cpu_freqs[g5_query_freq()].frequency;-policy->cpus=cpu_possible_map;+/* secondary CPUs are tied to the primary one by the+*cpufreqcoreifinthesecondarypolicywetellitthat+*itactuallymustbeonepolicytogetherwithallothers.*/+policy->cpus=cpu_online_map;cpufreq_frequency_table_get_attr(g5_cpu_freqs,policy->cpu);returncpufreq_frequency_table_cpuinfo(policy,--
From: Christoph Hellwig <hch@lst.de> Date: 2007-02-05 22:43:25
On Mon, Feb 05, 2007 at 07:30:29PM +0100, Johannes Berg wrote:
- /* there should be no signal, but oh well */
- if (signal_pending(current)) {
+ /* there should be no non-suspend signal, but oh well */
+ if (signal_pending(current) && !try_to_freeze()) {
Given that the driver uses the kthread infrastructure and doesn't
explicitly re-enable signals there can't be any other signal.
So just remove the signal_pending check.
From: Andrew Morton <akpm@linux-foundation.org> Date: 2007-02-05 22:54:25
On Mon, 05 Feb 2007 19:30:29 +0100
Johannes Berg [off-list ref] wrote:
quoted hunk
When the windfarm thread gets a suspend signal it will die instead of
freezing. This fixes it.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Andrew Morton <redacted>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Please apply to -mm.
@@ -94,8 +94,6 @@ static int wf_thread_func(void *data)DBG("wf: thread started\n");while(!kthread_should_stop()){-try_to_freeze();-if(time_after_eq(jiffies,next)){wf_notify(WF_EVENT_TICK,NULL);if(wf_overtemp){
@@ -118,8 +116,8 @@ static int wf_thread_func(void *data)if(delay<=HZ)schedule_timeout_interruptible(delay);-/* there should be no signal, but oh well */-if(signal_pending(current)){+/* there should be no non-suspend signal, but oh well */+if(signal_pending(current)&&!try_to_freeze()){printk(KERN_WARNING"windfarm: thread got sigl !\n");break;}--
That sounds like a fairly irritating feature. Should we backport this into 2.6.20?
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-05 22:54:34
When the windfarm thread gets a suspend signal it will die instead of
freezing. This fixes it.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
Adresses Christoph's comment: This keeps the original try_to_freeze() in
place and just remove the code that kills the thread on a signal.
@@ -117,12 +117,6 @@ static int wf_thread_func(void *data)delay=next-jiffies;if(delay<=HZ)schedule_timeout_interruptible(delay);--/* there should be no signal, but oh well */-if(signal_pending(current)){-printk(KERN_WARNING"windfarm: thread got sigl !\n");-break;-}}DBG("wf: thread stopped\n");
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2007-02-05 22:58:36
On Mon, 2007-02-05 at 19:30 +0100, Johannes Berg wrote:
plain text document attachment (windfarm-dont-die-on-signals.patch)
When the windfarm thread gets a suspend signal it will die instead of
freezing. This fixes it.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Andrew Morton <redacted>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
@@ -94,8 +94,6 @@ static int wf_thread_func(void *data)DBG("wf: thread started\n");while(!kthread_should_stop()){-try_to_freeze();-if(time_after_eq(jiffies,next)){wf_notify(WF_EVENT_TICK,NULL);if(wf_overtemp){
@@ -118,8 +116,8 @@ static int wf_thread_func(void *data)if(delay<=HZ)schedule_timeout_interruptible(delay);-/* there should be no signal, but oh well */-if(signal_pending(current)){+/* there should be no non-suspend signal, but oh well */+if(signal_pending(current)&&!try_to_freeze()){printk(KERN_WARNING"windfarm: thread got sigl !\n");break;}--
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2007-02-05 22:59:36
On Mon, 2007-02-05 at 19:30 +0100, Johannes Berg wrote:
plain text document attachment (irq-comment.patch)
kernel/irq.c contains a comment that speaks of -1 and -2 as interrupt
numbers. Replace by NO_IRQ and NO_IRQ_IGNORE.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Andrew Morton <redacted>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2007-02-05 23:04:01
On Mon, 2007-02-05 at 23:54 +0100, Johannes Berg wrote:
When the windfarm thread gets a suspend signal it will die instead of
freezing. This fixes it.
Don't we still need to call try_to_freeze() ?
quoted hunk
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
Adresses Christoph's comment: This keeps the original try_to_freeze() in
place and just remove the code that kills the thread on a signal.
@@ -117,12 +117,6 @@ static int wf_thread_func(void *data)delay=next-jiffies;if(delay<=HZ)schedule_timeout_interruptible(delay);--/* there should be no signal, but oh well */-if(signal_pending(current)){-printk(KERN_WARNING"windfarm: thread got sigl !\n");-break;-}}DBG("wf: thread stopped\n");
From: Andrew Morton <akpm@linux-foundation.org> Date: 2007-02-05 23:18:16
On Tue, 06 Feb 2007 09:59:36 +1100
Benjamin Herrenschmidt [off-list ref] wrote:
On Mon, 2007-02-05 at 19:30 +0100, Johannes Berg wrote:
quoted
plain text document attachment (irq-comment.patch)
kernel/irq.c contains a comment that speaks of -1 and -2 as interrupt
numbers. Replace by NO_IRQ and NO_IRQ_IGNORE.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Andrew Morton <redacted>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
I hope that wasn't acked at me. I was only copied on half this patch
series and I only picked up swsusp-dont-copy-pages-that-arent-ram.patch and
windfarm-dont-die-on-suspend-thread-signal.patch.
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2007-02-05 23:53:47
On Mon, 2007-02-05 at 15:18 -0800, Andrew Morton wrote:
On Tue, 06 Feb 2007 09:59:36 +1100
Benjamin Herrenschmidt [off-list ref] wrote:
quoted
On Mon, 2007-02-05 at 19:30 +0100, Johannes Berg wrote:
quoted
plain text document attachment (irq-comment.patch)
kernel/irq.c contains a comment that speaks of -1 and -2 as interrupt
numbers. Replace by NO_IRQ and NO_IRQ_IGNORE.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Andrew Morton <redacted>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
I hope that wasn't acked at me. I was only copied on half this patch
series and I only picked up swsusp-dont-copy-pages-that-arent-ram.patch and
windfarm-dont-die-on-suspend-thread-signal.patch.
This one is really independant of the rest, so it can be picked up by
either you or paulus or both, whoever jumps on it first :-) I wrote the
code this comment refers to so I just reviewed & acked :-)
Ben.
From: Olof Johansson <hidden> Date: 2007-02-06 01:19:49
On Mon, Feb 05, 2007 at 07:30:35PM +0100, Johannes Berg wrote:
This implements suspend and resume code for the dart iommu.
It's a good start, but it would be even nicer to have more generic iommu
suspend/resume hooks instead, and do the alloc/copy there. Add the hooks
to ppc_md together with the rest of the iommu/tce ops.
Minor code comment below.
@@ -54,6 +54,9 @@ static unsigned long dart_tablesize;/* Virtual base address of the DART table */staticu32*dart_vbase;+#ifdef CONFIG_SOFTWARE_SUSPEND+staticu32*dart_copy;+#endif/* Mapped base address for the dart */staticunsignedint__iomem*dart;
@@ -346,6 +349,52 @@ void iommu_init_early_dart(void)pci_dma_ops=&dma_direct_ops;}+#ifdef CONFIG_SOFTWARE_SUSPEND+staticintiommu_init_late_dart(void)+{+unsignedlongi;+structpage*p;++/* this 16MB area is left unmapped because of caching+*considerations.thathappensearlysowecan'tmark+*itthere,doitnowinstead*/+for(i=0;i<(1<<24);i+=PAGE_SIZE)+SetPageNosave(virt_to_page((void*)((unsignedlong)dart_tablebase+i)));
Please do a local void * instead, makes for much less casting in the loop. :)
quoted hunk
+
+ /* if no dart table exists then we don't need to save it */
+ if (!dart_tablebase)
+ return 0;
+
+ /* For suspend we need to copy the dart contents because
+ * it is not part of the regular mapping (see above) and
+ * thus not saved automatically. The memory for this copy
+ * must be allocated early because we need 2 MB. */
+ p = alloc_pages(GFP_KERNEL, 21 - PAGE_SHIFT);
+ BUG_ON(!p);
+ dart_copy = page_address(p);
+
+ return 0;
+}
+
+late_initcall(iommu_init_late_dart);
+
+void iommu_dart_save(void)
+{
+ if (!dart_tablebase)
+ return;
+
+ memcpy(dart_copy, dart_vbase, 2*1024*1024);
+}
+
+void iommu_dart_restore(void)
+{
+ if (!dart_tablebase)
+ return;
+
+ memcpy(dart_vbase, dart_copy, 2*1024*1024);
+ dart_tlb_invalidate_all();
+}
+#endif
void __init alloc_dart_table(void)
{
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-06 01:26:02
On Mon, 2007-02-05 at 19:19 -0600, Olof Johansson wrote:
On Mon, Feb 05, 2007 at 07:30:35PM +0100, Johannes Berg wrote:
quoted
This implements suspend and resume code for the dart iommu.
It's a good start, but it would be even nicer to have more generic iommu
suspend/resume hooks instead, and do the alloc/copy there. Add the hooks
to ppc_md together with the rest of the iommu/tce ops.
Ok, I'll take a look. I think we should leave the alloc up to the code
and just have generic calls for what now is iommu_dart_{save,restore}, I
see no point in adding a callback for iommu_init_late_dart since any
other iommu can do it as a late_initcall as well.
quoted
+ /* this 16MB area is left unmapped because of caching
+ * considerations. that happens early so we can't mark
+ * it there, do it now instead */
+ for (i = 0; i < (1<<24); i+= PAGE_SIZE)
+ SetPageNosave(virt_to_page((void*)((unsigned long)dart_tablebase + i)));
Please do a local void * instead, makes for much less casting in the loop. :)
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-06 01:52:47
How's this? Needs to go along with the correct changes in the code that
uses it, of course.
I can't use a local void * as you suggested because it needs to be added
to as an unsigned long, but I can use a local unsigned long.
Not even compiled yet.
Btw. What does TCE stand for?
@@ -54,6 +54,9 @@ static unsigned long dart_tablesize;/* Virtual base address of the DART table */staticu32*dart_vbase;+#ifdef CONFIG_PM+staticu32*dart_copy;+#endif/* Mapped base address for the dart */staticunsignedint__iomem*dart;
@@ -346,6 +349,49 @@ void iommu_init_early_dart(void)pci_dma_ops=&dma_direct_ops;}+#ifdef CONFIG_PM+staticvoidiommu_dart_suspend(void)+{+memcpy(dart_copy,dart_vbase,2*1024*1024);+}++staticvoidiommu_dart_restore(void)+{+memcpy(dart_vbase,dart_copy,2*1024*1024);+dart_tlb_invalidate_all();+}++staticintiommu_init_late_dart(void)+{+unsignedlongi,tbase=(unsignedlong)dart_tablebase;+structpage*p;++/* this 16MB area is left unmapped because of caching+*considerations.thathappensearlysowecan'tmark+*itthere,doitnowinstead*/+for(i=0;i<(1<<24);i+=PAGE_SIZE)+SetPageNosave(virt_to_page((void*)(tbase+i)));++/* if no dart table exists then we don't need to save it */+if(!dart_tablebase)+return0;++/* For suspend we need to copy the dart contents because+*itisnotpartoftheregularmapping(seeabove)and+*thusnotsavedautomatically.Thememoryforthiscopy+*mustbeallocatedearlybecauseweneed2MB.*/+p=alloc_pages(GFP_KERNEL,21-PAGE_SHIFT);+BUG_ON(!p);+dart_copy=page_address(p);++ppc_md.iommu_suspend=iommu_dart_suspend;+ppc_md.iommu_resume=iommu_dart_resume;++return0;+}++late_initcall(iommu_init_late_dart);+#endifvoid__initalloc_dart_table(void){---mb-wireless.orig/include/asm-powerpc/iommu.h2007-02-0602:45:34.524524763+0100+++mb-wireless/include/asm-powerpc/iommu.h2007-02-0602:46:28.964524763+0100
From: Pavel Machek <hidden> Date: 2007-02-06 12:40:47
Hi!
This implements suspend and resume code for the dart iommu.
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
quoted hunk
@@ -54,6 +54,9 @@ static unsigned long dart_tablesize; /* Virtual base address of the DART table */ static u32 *dart_vbase;+#ifdef CONFIG_SOFTWARE_SUSPEND+static u32 *dart_copy;+#endif /* Mapped base address for the dart */ static unsigned int __iomem *dart;
@@ -346,6 +349,52 @@ void iommu_init_early_dart(void) pci_dma_ops = &dma_direct_ops; }+#ifdef CONFIG_SOFTWARE_SUSPEND+static int iommu_init_late_dart(void)+{+ unsigned long i;+ struct page *p;++ /* this 16MB area is left unmapped because of caching+ * considerations. that happens early so we can't mark+ * it there, do it now instead */+ for (i = 0; i < (1<<24); i+= PAGE_SIZE)+ SetPageNosave(virt_to_page((void*)((unsigned long)dart_tablebase + i)));+
From: Pavel Machek <hidden> Date: 2007-02-06 12:42:12
Hi!
This patch allows "hotplugging" of CPUs on G5 machines. CPUs that are
disabled are put into an idle loop with interrupts hard-disabled, to wake
them up again we kick them just like when bringing them up.
Maybe there's some way to actually turn off those CPUs even more?
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
@@ -558,6 +558,11 @@ int __devinit start_secondary(void *unuslocal_irq_enable();+/* it seems to be possible that we died from within+*aninterrupt...resetthein-irqcounts*/+task_thread_info(paca[cpu].__current)->preempt_count&=+~(SOFTIRQ_MASK|HARDIRQ_MASK);+cpu_idle();return0;
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-07 11:40:20
Hi,
quoted
+ /* it seems to be possible that we died from within
+ * an interrupt ... reset the in-irq counts */
+ task_thread_info(paca[cpu].__current)->preempt_count &=
+ ~(SOFTIRQ_MASK|HARDIRQ_MASK);
+
cpu_idle();
return 0;
This is quite a nasty hack. Are you sure?
I've seen similar weirdness on pc, and it was caused by
swsusp-copying-code using FPU and incrementing preempt_count...
I know. I'm not really happy with it. But I can't figure out where the
hardirq count can be incremented. The preempt count is fine (well, in my
latest patchset, this one forgot one spot), but the hard irq count is
not. Which is really strange because we only use that for actual in-irq
stuff...
johannes
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-07 12:21:23
On Mon, 2007-02-05 at 19:30 +0100, Johannes Berg wrote:
The original code here is wrong, it applies "previous" knowledge.
The way the cpufreq core is designed is that the policy for the
secondary CPU that comes online says that it must in fact not
use this policy but use the same as the other CPUs that are
listed, which in fact is CPU#0.
Not tested yet but from what Jacob said this should work.
Works great, will resend with proper signed-off-by etc. Thanks again
Jacob for explaining how it should work.
johannes
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-07 12:22:13
On Tue, 2007-02-06 at 02:52 +0100, Johannes Berg wrote:
How's this? Needs to go along with the correct changes in the code that
uses it, of course.
I can't use a local void * as you suggested because it needs to be added
to as an unsigned long, but I can use a local unsigned long.
Not even compiled yet.
which showed, it didn't compile but I sorted it out, will resend.
johannes
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-07 12:23:08
On Mon, 2007-02-05 at 19:30 +0100, Johannes Berg wrote:
This patch allows "hotplugging" of CPUs on G5 machines. CPUs that are
disabled are put into an idle loop with interrupts hard-disabled, to wake
them up again we kick them just like when bringing them up.
testing with forced preemption revealed that the preempt count is messed
up. Will resend with the fix. The hardirq count is still strange...
johannes
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-07 12:24:04
On Mon, 2007-02-05 at 19:30 +0100, Johannes Berg wrote:
plain text document attachment (mpic-suspend.patch)
This adds mpic to the system devices and implements suspend
and resume for them. This is necessary to get interrupts for
modules back to where they were before a suspend to disk.
This patch isn't enough, I forgot about the broken u3 ht interrupt
stuff. Will resend with code that restores those as well which actually
makes all interrupts on my powermac work after resume.
johannes
From: Paul Mackerras <hidden> Date: 2007-02-08 04:41:12
Johannes Berg writes:
This patch cleans up the powermac PIC initialisation code so that for G5
powermacs we don't even compile the old pmac pic file.
On a 32-bit powermac config, with this patch I get:
CC arch/powerpc/platforms/powermac/mpic.o
/home/paulus/kernel/powerpc/arch/powerpc/platforms/powermac/mpic.c: In function ‘pmac_pic_setup_mpic_nmi’:
/home/paulus/kernel/powerpc/arch/powerpc/platforms/powermac/mpic.c:40: error: ‘xmon_action’ undeclared (first use in this function)
/home/paulus/kernel/powerpc/arch/powerpc/platforms/powermac/mpic.c:40: error: (Each undeclared identifier is reported only once
/home/paulus/kernel/powerpc/arch/powerpc/platforms/powermac/mpic.c:40: error: for each function it appears in.)
make[3]: *** [arch/powerpc/platforms/powermac/mpic.o] Error 1
Paul.
From: Johannes Berg <johannes@sipsolutions.net> Date: 2007-02-08 13:03:18
On Thu, 2007-02-08 at 15:41 +1100, Paul Mackerras wrote:
Johannes Berg writes:
quoted
This patch cleans up the powermac PIC initialisation code so that for G5
powermacs we don't even compile the old pmac pic file.
On a 32-bit powermac config, with this patch I get:
CC arch/powerpc/platforms/powermac/mpic.o
/home/paulus/kernel/powerpc/arch/powerpc/platforms/powermac/mpic.c: In function ‘pmac_pic_setup_mpic_nmi’:
/home/paulus/kernel/powerpc/arch/powerpc/platforms/powermac/mpic.c:40: error: ‘xmon_action’ undeclared (first use in this function)
/home/paulus/kernel/powerpc/arch/powerpc/platforms/powermac/mpic.c:40: error: (Each undeclared identifier is reported only once
/home/paulus/kernel/powerpc/arch/powerpc/platforms/powermac/mpic.c:40: error: for each function it appears in.)
make[3]: *** [arch/powerpc/platforms/powermac/mpic.o] Error 1
Yeah. I noticed that yesterday as well, but too late. Sorry about that.
I could fix but it isn't nice, let's just drop this patch instead.
Sorry.
johannes
This patch removes the time suspend/restore code that was done through
a PMU notifier in arch/platforms/powermac/time.c.
Instead, we introduce arch/powerpc/sysdev/timer.c which creates a sys
device and handles time of day suspend/resume through that.
I think there's a problem with this one. In my tests with this patch the
system time is incremented twice, so, looks like some code already takes
care about that. Maybe there's some very indirect code in generic rtc, but
I haven't found anything yet. Anyway, requires more investigation and,
probably, should not be included before we clarify this.
Thanks
Guennadi
---
Guennadi Liakhovetski
This patch removes the time suspend/restore code that was done through
a PMU notifier in arch/platforms/powermac/time.c.
Instead, we introduce arch/powerpc/sysdev/timer.c which creates a sys
device and handles time of day suspend/resume through that.
I think there's a problem with this one. In my tests with this patch the
system time is incremented twice, so, looks like some code already takes
care about that. Maybe there's some very indirect code in generic rtc, but
I haven't found anything yet. Anyway, requires more investigation and,
probably, should not be included before we clarify this.
Ok, it has been a problem with my testing. ATM I don't know of any
problems with it, so, please, consider my objections void.
Thanks
Guennadi
---
Guennadi Liakhovetski