All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/12] powerpc/powermac power management patches
@ 2007-02-07 12:45 Johannes Berg
  2007-02-07 12:45   ` Johannes Berg
                   ` (12 more replies)
  0 siblings, 13 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

Here's my current patch series that grew from implementing suspend to disk
for my powermac to a general suspend code cleanup.

One of the nice patches in this series allows you to finally suspend
via
  echo mem > /sys/power/state
on powerbooks!

I've tested this whole patchset on my powerbook as well as my powermac
(which can with it suspend for the first time) and it all works well.

I expect that you will be finding problems with this, but I hope to
get this included some time in the not-too-distant future.

This patchset depends on the patches
 * snd-aoa: fix onyx resume
 * windfarm: don't die on suspend thread signal
to work, but will probably not apply unless you also have
 * powermac: clean up PIC initialisation code

johannes

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 01/12] powerpc: MPIC sys_device & suspend/resume
  2007-02-07 12:45 [PATCH 00/12] powerpc/powermac power management patches Johannes Berg
@ 2007-02-07 12:45   ` Johannes Berg
  2007-02-07 12:45   ` Johannes Berg
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

[-- Attachment #1: mpic-suspend.patch --]
[-- Type: text/plain, Size: 5042 bytes --]

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.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>

---
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.

Over the previous version of this patch this changes that
it also restores the HT interrupts if necessary, making my
quad G5 actually work.

--- linux-2.6-git.orig/arch/powerpc/sysdev/mpic.c	2007-02-07 02:55:06.708884289 +0100
+++ linux-2.6-git/arch/powerpc/sysdev/mpic.c	2007-02-07 04:40:38.190855996 +0100
@@ -354,6 +354,12 @@ static void mpic_startup_ht_interrupt(st
 		tmp |= 0x22;
 	writel(tmp, fixup->base + 4);
 	spin_unlock_irqrestore(&mpic->fixup_lock, flags);
+
+#ifdef CONFIG_PM
+	/* use the lowest bit inverted to the actual HW,
+	 * set if this fixup was enabled, clear otherwise */
+	mpic->save_data[source].fixup_data = tmp | 1;
+#endif
 }
 
 static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
@@ -375,6 +381,12 @@ static void mpic_shutdown_ht_interrupt(s
 	tmp |= 1;
 	writel(tmp, fixup->base + 4);
 	spin_unlock_irqrestore(&mpic->fixup_lock, flags);
+
+#ifdef CONFIG_PM
+	/* use the lowest bit inverted to the actual HW,
+	 * set if this fixup was enabled, clear otherwise */
+	mpic->save_data[source].fixup_data = tmp & ~1;
+#endif
 }
 
 static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
@@ -1123,7 +1135,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 +1159,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(struct mpic_irq_save));
+	BUG_ON(mpic->save_data == NULL);
+#endif
 }
 
 void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)
@@ -1376,3 +1394,79 @@ void smp_mpic_message_pass(int target, i
 	}
 }
 #endif /* CONFIG_SMP */
+
+#ifdef CONFIG_PM
+static int mpic_suspend(struct sys_device *dev, pm_message_t state)
+{
+	struct mpic *mpic = container_of(dev, struct mpic, sysdev);
+	int i;
+
+	for (i = 0; i < mpic->num_sources; i++) {
+		mpic->save_data[i].vecprio =
+			mpic_irq_read(i, MPIC_INFO(IRQ_VECTOR_PRI));
+		mpic->save_data[i].dest =
+			mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION));
+	}
+
+	return 0;
+}
+
+static int mpic_resume(struct sys_device *dev)
+{
+	struct mpic *mpic = container_of(dev, struct mpic, sysdev);
+	int i;
+
+	for (i = 0; i < mpic->num_sources; i++) {
+		mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI),
+			       mpic->save_data[i].vecprio);
+		mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
+			       mpic->save_data[i].dest);
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+	{
+		struct mpic_irq_fixup *fixup = &mpic->fixups[i];
+
+		if (fixup->base) {
+			/* we use the lowest bit in an inverted meaning */
+			if ((mpic->save_data[i].fixup_data & 1) == 0)
+				continue;
+
+			/* Enable and configure */
+			writeb(0x10 + 2 * fixup->index, fixup->base + 2);
+
+			writel(mpic->save_data[i].fixup_data & ~1,
+			       fixup->base + 4);
+		}
+	}
+#endif
+	} /* end for loop */
+
+	return 0;
+}
+#endif
+
+static struct sysdev_class mpic_sysclass = {
+#ifdef CONFIG_PM
+	.resume = mpic_resume,
+	.suspend = mpic_suspend,
+#endif
+	set_kset_name("mpic"),
+};
+
+static int mpic_init_sys(void)
+{
+	struct mpic *mpic = mpics;
+	int error, id = 0;
+
+	error = sysdev_class_register(&mpic_sysclass);
+
+	while (mpic && !error) {
+		mpic->sysdev.cls = &mpic_sysclass;
+		mpic->sysdev.id = id++;
+		error = sysdev_register(&mpic->sysdev);
+		mpic = mpic->next;
+	}
+	return error;
+}
+
+device_initcall(mpic_init_sys);
--- linux-2.6-git.orig/include/asm-powerpc/mpic.h	2007-02-07 02:55:06.868884289 +0100
+++ linux-2.6-git/include/asm-powerpc/mpic.h	2007-02-07 04:31:41.937855996 +0100
@@ -3,6 +3,7 @@
 #ifdef __KERNEL__
 
 #include <linux/irq.h>
+#include <linux/sysdev.h>
 #include <asm/dcr.h>
 
 /*
@@ -243,6 +244,14 @@ struct mpic_reg_bank {
 #endif /* CONFIG_PPC_DCR */
 };
 
+struct mpic_irq_save {
+	u32		vecprio,
+			dest;
+#ifdef CONFIG_MPIC_BROKEN_U3
+	u32		fixup_data;
+#endif
+};
+
 /* The instance data of a given MPIC */
 struct mpic
 {
@@ -302,6 +311,12 @@ struct mpic
 
 	/* link */
 	struct mpic		*next;
+
+	struct sys_device	sysdev;
+
+#ifdef CONFIG_PM
+	struct mpic_irq_save	*save_data;
+#endif
 };
 
 /*

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 01/12] powerpc: MPIC sys_device & suspend/resume
@ 2007-02-07 12:45   ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

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.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>

---
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.

Over the previous version of this patch this changes that
it also restores the HT interrupts if necessary, making my
quad G5 actually work.

--- linux-2.6-git.orig/arch/powerpc/sysdev/mpic.c	2007-02-07 02:55:06.708884289 +0100
+++ linux-2.6-git/arch/powerpc/sysdev/mpic.c	2007-02-07 04:40:38.190855996 +0100
@@ -354,6 +354,12 @@ static void mpic_startup_ht_interrupt(st
 		tmp |= 0x22;
 	writel(tmp, fixup->base + 4);
 	spin_unlock_irqrestore(&mpic->fixup_lock, flags);
+
+#ifdef CONFIG_PM
+	/* use the lowest bit inverted to the actual HW,
+	 * set if this fixup was enabled, clear otherwise */
+	mpic->save_data[source].fixup_data = tmp | 1;
+#endif
 }
 
 static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
@@ -375,6 +381,12 @@ static void mpic_shutdown_ht_interrupt(s
 	tmp |= 1;
 	writel(tmp, fixup->base + 4);
 	spin_unlock_irqrestore(&mpic->fixup_lock, flags);
+
+#ifdef CONFIG_PM
+	/* use the lowest bit inverted to the actual HW,
+	 * set if this fixup was enabled, clear otherwise */
+	mpic->save_data[source].fixup_data = tmp & ~1;
+#endif
 }
 
 static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
@@ -1123,7 +1135,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 +1159,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(struct mpic_irq_save));
+	BUG_ON(mpic->save_data == NULL);
+#endif
 }
 
 void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)
@@ -1376,3 +1394,79 @@ void smp_mpic_message_pass(int target, i
 	}
 }
 #endif /* CONFIG_SMP */
+
+#ifdef CONFIG_PM
+static int mpic_suspend(struct sys_device *dev, pm_message_t state)
+{
+	struct mpic *mpic = container_of(dev, struct mpic, sysdev);
+	int i;
+
+	for (i = 0; i < mpic->num_sources; i++) {
+		mpic->save_data[i].vecprio =
+			mpic_irq_read(i, MPIC_INFO(IRQ_VECTOR_PRI));
+		mpic->save_data[i].dest =
+			mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION));
+	}
+
+	return 0;
+}
+
+static int mpic_resume(struct sys_device *dev)
+{
+	struct mpic *mpic = container_of(dev, struct mpic, sysdev);
+	int i;
+
+	for (i = 0; i < mpic->num_sources; i++) {
+		mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI),
+			       mpic->save_data[i].vecprio);
+		mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
+			       mpic->save_data[i].dest);
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+	{
+		struct mpic_irq_fixup *fixup = &mpic->fixups[i];
+
+		if (fixup->base) {
+			/* we use the lowest bit in an inverted meaning */
+			if ((mpic->save_data[i].fixup_data & 1) == 0)
+				continue;
+
+			/* Enable and configure */
+			writeb(0x10 + 2 * fixup->index, fixup->base + 2);
+
+			writel(mpic->save_data[i].fixup_data & ~1,
+			       fixup->base + 4);
+		}
+	}
+#endif
+	} /* end for loop */
+
+	return 0;
+}
+#endif
+
+static struct sysdev_class mpic_sysclass = {
+#ifdef CONFIG_PM
+	.resume = mpic_resume,
+	.suspend = mpic_suspend,
+#endif
+	set_kset_name("mpic"),
+};
+
+static int mpic_init_sys(void)
+{
+	struct mpic *mpic = mpics;
+	int error, id = 0;
+
+	error = sysdev_class_register(&mpic_sysclass);
+
+	while (mpic && !error) {
+		mpic->sysdev.cls = &mpic_sysclass;
+		mpic->sysdev.id = id++;
+		error = sysdev_register(&mpic->sysdev);
+		mpic = mpic->next;
+	}
+	return error;
+}
+
+device_initcall(mpic_init_sys);
--- linux-2.6-git.orig/include/asm-powerpc/mpic.h	2007-02-07 02:55:06.868884289 +0100
+++ linux-2.6-git/include/asm-powerpc/mpic.h	2007-02-07 04:31:41.937855996 +0100
@@ -3,6 +3,7 @@
 #ifdef __KERNEL__
 
 #include <linux/irq.h>
+#include <linux/sysdev.h>
 #include <asm/dcr.h>
 
 /*
@@ -243,6 +244,14 @@ struct mpic_reg_bank {
 #endif /* CONFIG_PPC_DCR */
 };
 
+struct mpic_irq_save {
+	u32		vecprio,
+			dest;
+#ifdef CONFIG_MPIC_BROKEN_U3
+	u32		fixup_data;
+#endif
+};
+
 /* The instance data of a given MPIC */
 struct mpic
 {
@@ -302,6 +311,12 @@ struct mpic
 
 	/* link */
 	struct mpic		*next;
+
+	struct sys_device	sysdev;
+
+#ifdef CONFIG_PM
+	struct mpic_irq_save	*save_data;
+#endif
 };
 
 /*

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 02/12] powermac: support G5 CPU hotplug
  2007-02-07 12:45 [PATCH 00/12] powerpc/powermac power management patches Johannes Berg
@ 2007-02-07 12:45   ` Johannes Berg
  2007-02-07 12:45   ` Johannes Berg
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

[-- Attachment #1: powermac-g5-cpu-offline.patch --]
[-- Type: text/plain, Size: 3807 bytes --]

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.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>

---
Except for the in-irq count hack I'm happy with this. I still haven't found
where the in-hard-irq count is set to 1 in the down path during suspend or
resume and other platforms do similar things so I'm inclined to leave this.

--- linux-2.6-git.orig/arch/powerpc/platforms/powermac/smp.c	2007-02-07 02:55:05.657884289 +0100
+++ linux-2.6-git/arch/powerpc/platforms/powermac/smp.c	2007-02-07 02:55:27.352884289 +0100
@@ -898,7 +898,7 @@ void smp_core99_cpu_die(unsigned int cpu
 	cpu_dead[cpu] = 0;
 }
 
-#endif
+#endif /* CONFIG_HOTPLUG_CPU && CONFIG_PP32 */
 
 /* Core99 Macs (dual G4s and G5s) */
 struct smp_ops_t core99_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,
+	 * the generic code will use kick_cpu then! */
+# endif
 #endif
 };
--- linux-2.6-git.orig/arch/powerpc/platforms/powermac/setup.c	2007-02-07 02:55:23.435884289 +0100
+++ linux-2.6-git/arch/powerpc/platforms/powermac/setup.c	2007-02-07 02:55:27.388884289 +0100
@@ -490,6 +490,9 @@ static int pmac_late_init(void)
 #ifdef CONFIG_SOFTWARE_SUSPEND
 	pm_set_ops(&pmac_pm_ops);
 #endif /* CONFIG_SOFTWARE_SUSPEND */
+	/* this is udbg (which is __init) and we can later use it during
+	 * cpu hotplug (in smp_core99_kick_cpu) */
+	ppc_md.progress = NULL;
 	return 0;
 }
 
@@ -716,6 +719,39 @@ static int pmac_pci_probe_mode(struct pc
 		return PCI_PROBE_NORMAL;
 	return PCI_PROBE_DEVTREE;
 }
+
+#ifdef CONFIG_HOTPLUG_CPU
+/* access per cpu vars from generic smp.c */
+DECLARE_PER_CPU(int, cpu_state);
+
+static void pmac_cpu_die(void)
+{
+	/* turn off as much as possible, we'll be
+	 * kicked out as this will only be invoked
+	 * on core99 platforms for now ... */
+	hard_irq_disable();
+
+	printk(KERN_INFO "CPU#%d offline\n", smp_processor_id());
+	__get_cpu_var(cpu_state) = CPU_DEAD;
+	smp_wmb();
+
+	/* during the path that leads here preemption is disabled,
+	 * reenable it now so that when coming up preempt count is
+	 * zero correctly */
+	preempt_enable();
+
+	while (1) {
+		ppc64_runlatch_off();
+		if (ppc_md.power_save) {
+			ppc_md.power_save();
+		} else {
+			HMT_low();
+			HMT_very_low();
+		}
+	}
+}
+#endif
+
 #endif
 
 static void __init pmac_init_irq(void)
@@ -769,6 +805,6 @@ define_machine(powermac) {
 	.phys_mem_access_prot	= pci_phys_mem_access_prot,
 #endif
 #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64)
-	.cpu_die		= generic_mach_cpu_die,
+	.cpu_die		= pmac_cpu_die,
 #endif
 };
--- linux-2.6-git.orig/arch/powerpc/kernel/smp.c	2007-02-07 02:55:06.111884289 +0100
+++ linux-2.6-git/arch/powerpc/kernel/smp.c	2007-02-07 02:55:27.439884289 +0100
@@ -558,6 +558,11 @@ int __devinit start_secondary(void *unus
 
 	local_irq_enable();
 
+	/* 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;
 }

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 02/12] powermac: support G5 CPU hotplug
@ 2007-02-07 12:45   ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

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.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>

---
Except for the in-irq count hack I'm happy with this. I still haven't found
where the in-hard-irq count is set to 1 in the down path during suspend or
resume and other platforms do similar things so I'm inclined to leave this.

--- linux-2.6-git.orig/arch/powerpc/platforms/powermac/smp.c	2007-02-07 02:55:05.657884289 +0100
+++ linux-2.6-git/arch/powerpc/platforms/powermac/smp.c	2007-02-07 02:55:27.352884289 +0100
@@ -898,7 +898,7 @@ void smp_core99_cpu_die(unsigned int cpu
 	cpu_dead[cpu] = 0;
 }
 
-#endif
+#endif /* CONFIG_HOTPLUG_CPU && CONFIG_PP32 */
 
 /* Core99 Macs (dual G4s and G5s) */
 struct smp_ops_t core99_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,
+	 * the generic code will use kick_cpu then! */
+# endif
 #endif
 };
--- linux-2.6-git.orig/arch/powerpc/platforms/powermac/setup.c	2007-02-07 02:55:23.435884289 +0100
+++ linux-2.6-git/arch/powerpc/platforms/powermac/setup.c	2007-02-07 02:55:27.388884289 +0100
@@ -490,6 +490,9 @@ static int pmac_late_init(void)
 #ifdef CONFIG_SOFTWARE_SUSPEND
 	pm_set_ops(&pmac_pm_ops);
 #endif /* CONFIG_SOFTWARE_SUSPEND */
+	/* this is udbg (which is __init) and we can later use it during
+	 * cpu hotplug (in smp_core99_kick_cpu) */
+	ppc_md.progress = NULL;
 	return 0;
 }
 
@@ -716,6 +719,39 @@ static int pmac_pci_probe_mode(struct pc
 		return PCI_PROBE_NORMAL;
 	return PCI_PROBE_DEVTREE;
 }
+
+#ifdef CONFIG_HOTPLUG_CPU
+/* access per cpu vars from generic smp.c */
+DECLARE_PER_CPU(int, cpu_state);
+
+static void pmac_cpu_die(void)
+{
+	/* turn off as much as possible, we'll be
+	 * kicked out as this will only be invoked
+	 * on core99 platforms for now ... */
+	hard_irq_disable();
+
+	printk(KERN_INFO "CPU#%d offline\n", smp_processor_id());
+	__get_cpu_var(cpu_state) = CPU_DEAD;
+	smp_wmb();
+
+	/* during the path that leads here preemption is disabled,
+	 * reenable it now so that when coming up preempt count is
+	 * zero correctly */
+	preempt_enable();
+
+	while (1) {
+		ppc64_runlatch_off();
+		if (ppc_md.power_save) {
+			ppc_md.power_save();
+		} else {
+			HMT_low();
+			HMT_very_low();
+		}
+	}
+}
+#endif
+
 #endif
 
 static void __init pmac_init_irq(void)
@@ -769,6 +805,6 @@ define_machine(powermac) {
 	.phys_mem_access_prot	= pci_phys_mem_access_prot,
 #endif
 #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64)
-	.cpu_die		= generic_mach_cpu_die,
+	.cpu_die		= pmac_cpu_die,
 #endif
 };
--- linux-2.6-git.orig/arch/powerpc/kernel/smp.c	2007-02-07 02:55:06.111884289 +0100
+++ linux-2.6-git/arch/powerpc/kernel/smp.c	2007-02-07 02:55:27.439884289 +0100
@@ -558,6 +558,11 @@ int __devinit start_secondary(void *unus
 
 	local_irq_enable();
 
+	/* 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;
 }

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 03/12] powerpc: dart iommu suspend
  2007-02-07 12:45 [PATCH 00/12] powerpc/powermac power management patches Johannes Berg
@ 2007-02-07 12:45   ` Johannes Berg
  2007-02-07 12:45   ` Johannes Berg
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

[-- Attachment #1: dart-suspend.patch --]
[-- Type: text/plain, Size: 3480 bytes --]

This implements save and restore hooks for IOMMUs and implements
it the dart iommu.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Paul Mackeras <paulus@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Olof Johansson <olof@lixom.net>

---
The quick patch I posted w/o testing of course didn't work. This one does.

--- linux-2.6-git.orig/arch/powerpc/sysdev/dart_iommu.c	2007-02-07 02:55:03.607884289 +0100
+++ linux-2.6-git/arch/powerpc/sysdev/dart_iommu.c	2007-02-07 02:55:29.073884289 +0100
@@ -54,6 +54,9 @@ static unsigned long dart_tablesize;
 
 /* Virtual base address of the DART table */
 static u32 *dart_vbase;
+#ifdef CONFIG_PM
+static u32 *dart_copy;
+#endif
 
 /* Mapped base address for the dart */
 static unsigned int __iomem *dart;
@@ -346,6 +349,49 @@ void iommu_init_early_dart(void)
 	pci_dma_ops = &dma_direct_ops;
 }
 
+#ifdef CONFIG_PM
+static void iommu_dart_save(void)
+{
+	memcpy(dart_copy, dart_vbase, 2*1024*1024);
+}
+
+static void iommu_dart_restore(void)
+{
+	memcpy(dart_vbase, dart_copy, 2*1024*1024);
+	dart_tlb_invalidate_all();
+}
+
+static int iommu_init_late_dart(void)
+{
+	unsigned long i, tbase = (unsigned long) dart_tablebase;
+	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*)(tbase + i)));
+
+	/* 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);
+
+	ppc_md.iommu_save = iommu_dart_save;
+	ppc_md.iommu_restore = iommu_dart_restore;
+
+	return 0;
+}
+
+late_initcall(iommu_init_late_dart);
+#endif
 
 void __init alloc_dart_table(void)
 {
--- linux-2.6-git.orig/include/asm-powerpc/iommu.h	2007-02-07 02:55:03.635884289 +0100
+++ linux-2.6-git/include/asm-powerpc/iommu.h	2007-02-07 02:55:29.099884289 +0100
@@ -26,6 +26,7 @@
 #include <linux/spinlock.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <asm/machdep.h>
 #include <asm/types.h>
 #include <asm/bitops.h>
 
@@ -108,6 +109,19 @@ static inline void pci_iommu_init(void) 
 #endif
 
 extern void alloc_dart_table(void);
+#if defined(CONFIG_PPC64) && defined(CONFIG_PM)
+static inline void iommu_save(void)
+{
+	if (ppc_md.iommu_save)
+		ppc_md.iommu_save();
+}
+
+static inline void iommu_restore(void)
+{
+	if (ppc_md.iommu_restore)
+		ppc_md.iommu_restore();
+}
+#endif
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_IOMMU_H */
--- linux-2.6-git.orig/include/asm-powerpc/machdep.h	2007-02-07 02:55:03.698884289 +0100
+++ linux-2.6-git/include/asm-powerpc/machdep.h	2007-02-07 02:55:29.108884289 +0100
@@ -91,6 +91,11 @@ struct machdep_calls {
 	void __iomem *	(*ioremap)(phys_addr_t addr, unsigned long size,
 				   unsigned long flags);
 	void		(*iounmap)(volatile void __iomem *token);
+
+#ifdef CONFIG_PM
+	void		(*iommu_save)(void);
+	void		(*iommu_restore)(void);
+#endif
 #endif /* CONFIG_PPC64 */
 
 	int		(*probe)(void);

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 03/12] powerpc: dart iommu suspend
@ 2007-02-07 12:45   ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Olof Johansson, Paul Mackeras, linux-pm

This implements save and restore hooks for IOMMUs and implements
it the dart iommu.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Paul Mackeras <paulus@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Olof Johansson <olof@lixom.net>

---
The quick patch I posted w/o testing of course didn't work. This one does.

--- linux-2.6-git.orig/arch/powerpc/sysdev/dart_iommu.c	2007-02-07 02:55:03.607884289 +0100
+++ linux-2.6-git/arch/powerpc/sysdev/dart_iommu.c	2007-02-07 02:55:29.073884289 +0100
@@ -54,6 +54,9 @@ static unsigned long dart_tablesize;
 
 /* Virtual base address of the DART table */
 static u32 *dart_vbase;
+#ifdef CONFIG_PM
+static u32 *dart_copy;
+#endif
 
 /* Mapped base address for the dart */
 static unsigned int __iomem *dart;
@@ -346,6 +349,49 @@ void iommu_init_early_dart(void)
 	pci_dma_ops = &dma_direct_ops;
 }
 
+#ifdef CONFIG_PM
+static void iommu_dart_save(void)
+{
+	memcpy(dart_copy, dart_vbase, 2*1024*1024);
+}
+
+static void iommu_dart_restore(void)
+{
+	memcpy(dart_vbase, dart_copy, 2*1024*1024);
+	dart_tlb_invalidate_all();
+}
+
+static int iommu_init_late_dart(void)
+{
+	unsigned long i, tbase = (unsigned long) dart_tablebase;
+	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*)(tbase + i)));
+
+	/* 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);
+
+	ppc_md.iommu_save = iommu_dart_save;
+	ppc_md.iommu_restore = iommu_dart_restore;
+
+	return 0;
+}
+
+late_initcall(iommu_init_late_dart);
+#endif
 
 void __init alloc_dart_table(void)
 {
--- linux-2.6-git.orig/include/asm-powerpc/iommu.h	2007-02-07 02:55:03.635884289 +0100
+++ linux-2.6-git/include/asm-powerpc/iommu.h	2007-02-07 02:55:29.099884289 +0100
@@ -26,6 +26,7 @@
 #include <linux/spinlock.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <asm/machdep.h>
 #include <asm/types.h>
 #include <asm/bitops.h>
 
@@ -108,6 +109,19 @@ static inline void pci_iommu_init(void) 
 #endif
 
 extern void alloc_dart_table(void);
+#if defined(CONFIG_PPC64) && defined(CONFIG_PM)
+static inline void iommu_save(void)
+{
+	if (ppc_md.iommu_save)
+		ppc_md.iommu_save();
+}
+
+static inline void iommu_restore(void)
+{
+	if (ppc_md.iommu_restore)
+		ppc_md.iommu_restore();
+}
+#endif
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_IOMMU_H */
--- linux-2.6-git.orig/include/asm-powerpc/machdep.h	2007-02-07 02:55:03.698884289 +0100
+++ linux-2.6-git/include/asm-powerpc/machdep.h	2007-02-07 02:55:29.108884289 +0100
@@ -91,6 +91,11 @@ struct machdep_calls {
 	void __iomem *	(*ioremap)(phys_addr_t addr, unsigned long size,
 				   unsigned long flags);
 	void		(*iounmap)(volatile void __iomem *token);
+
+#ifdef CONFIG_PM
+	void		(*iommu_save)(void);
+	void		(*iommu_restore)(void);
+#endif
 #endif /* CONFIG_PPC64 */
 
 	int		(*probe)(void);

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 04/12] powerpc: mark pages that dont exist as Nosave
  2007-02-07 12:45 [PATCH 00/12] powerpc/powermac power management patches Johannes Berg
@ 2007-02-07 12:45   ` Johannes Berg
  2007-02-07 12:45   ` Johannes Berg
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

[-- Attachment #1: powerpc-mark-nonram-nosave.patch --]
[-- Type: text/plain, Size: 1664 bytes --]

On some powerpc architectures (notably 64-bit powermac) there is a memory
hole, for example on powermacs between 2G and 4G. Since we use the flat
memory model regardless, these pages must be marked as Nosave (for suspend
to disk.)

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Rafael J. Wysocki <rjw@sisk.pl>

---
This replaces swsusp-dont-copy-pages-that-arent-ram.patch and works just as
well, except that it doesn't modify the generic code.

Tested on powerbook and powermac.

--- linux-2.6-git.orig/arch/powerpc/mm/mem.c	2007-02-07 02:55:03.319884289 +0100
+++ linux-2.6-git/arch/powerpc/mm/mem.c	2007-02-07 02:55:30.496884289 +0100
@@ -284,6 +284,27 @@ void __init do_init_bootmem(void)
 	init_bootmem_done = 1;
 }
 
+/* mark lowmem pages that don't exist as nosave, highmem
+ * pages always exist but aren't treated as RAM pages */
+static int __init mark_nonram_nosave(void)
+{
+	struct zone *zone;
+	unsigned long pfn, max_zone_pfn;
+
+	for_each_zone(zone) {
+		if (is_highmem(zone))
+			continue;
+
+		max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
+
+		for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
+			if (!page_is_ram(pfn))
+				SetPageNosave(pfn_to_page(pfn));
+	}
+
+	return 0;
+}
+
 /*
  * paging_init() sets up the page tables - in fact we've already done this.
  */
@@ -315,6 +336,8 @@ void __init paging_init(void)
 	max_zone_pfns[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
 #endif
 	free_area_init_nodes(max_zone_pfns);
+
+	mark_nonram_nosave();
 }
 #endif /* ! CONFIG_NEED_MULTIPLE_NODES */
 

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 04/12] powerpc: mark pages that dont exist as Nosave
@ 2007-02-07 12:45   ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Rafael J. Wysocki, linux-pm

On some powerpc architectures (notably 64-bit powermac) there is a memory
hole, for example on powermacs between 2G and 4G. Since we use the flat
memory model regardless, these pages must be marked as Nosave (for suspend
to disk.)

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Rafael J. Wysocki <rjw@sisk.pl>

---
This replaces swsusp-dont-copy-pages-that-arent-ram.patch and works just as
well, except that it doesn't modify the generic code.

Tested on powerbook and powermac.

--- linux-2.6-git.orig/arch/powerpc/mm/mem.c	2007-02-07 02:55:03.319884289 +0100
+++ linux-2.6-git/arch/powerpc/mm/mem.c	2007-02-07 02:55:30.496884289 +0100
@@ -284,6 +284,27 @@ void __init do_init_bootmem(void)
 	init_bootmem_done = 1;
 }
 
+/* mark lowmem pages that don't exist as nosave, highmem
+ * pages always exist but aren't treated as RAM pages */
+static int __init mark_nonram_nosave(void)
+{
+	struct zone *zone;
+	unsigned long pfn, max_zone_pfn;
+
+	for_each_zone(zone) {
+		if (is_highmem(zone))
+			continue;
+
+		max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
+
+		for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
+			if (!page_is_ram(pfn))
+				SetPageNosave(pfn_to_page(pfn));
+	}
+
+	return 0;
+}
+
 /*
  * paging_init() sets up the page tables - in fact we've already done this.
  */
@@ -315,6 +336,8 @@ void __init paging_init(void)
 	max_zone_pfns[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
 #endif
 	free_area_init_nodes(max_zone_pfns);
+
+	mark_nonram_nosave();
 }
 #endif /* ! CONFIG_NEED_MULTIPLE_NODES */
 

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 05/12] power management: no valid states w/o pm_ops + docs
  2007-02-07 12:45 [PATCH 00/12] powerpc/powermac power management patches Johannes Berg
@ 2007-02-07 12:45   ` Johannes Berg
  2007-02-07 12:45   ` Johannes Berg
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm, Pavel Macheck

[-- Attachment #1: no-pm_ops-no-valid-states.patch --]
[-- Type: text/plain, Size: 3856 bytes --]

This patch changes /sys/power/state to not advertise any valid states
(except for disk if SOFTWARE_SUSPEND is enabled) when no pm_ops have been
set so userspace can easily discover what states should be available.

Also, because the pm ops in powermac are obviously not using them as
intended, I added documentation for it in kernel-doc format.

Reordering the fields in struct pm_ops not only makes the output of
kernel-doc make more sense but also removes a hole from the structure on
64-bit platforms.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: linux-pm@lists.osdl.org
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Cc: Pavel Macheck <pavel@ucw.cz>

--- linux-2.6-git.orig/kernel/power/main.c	2007-02-07 02:55:01.676884289 +0100
+++ linux-2.6-git/kernel/power/main.c	2007-02-07 02:55:31.182884289 +0100
@@ -161,7 +161,10 @@ static inline int valid_state(suspend_st
 	if (state == PM_SUSPEND_DISK)
 		return 1;
 
-	if (pm_ops && pm_ops->valid && !pm_ops->valid(state))
+	/* all other states need lowlevel support and need to be
+	 * valid to the lowlevel implementation, no valid callback
+	 * implies that all are valid. */
+	if (!pm_ops || (pm_ops->valid && !pm_ops->valid(state)))
 		return 0;
 	return 1;
 }
--- linux-2.6-git.orig/include/linux/pm.h	2007-02-07 02:55:02.028884289 +0100
+++ linux-2.6-git/include/linux/pm.h	2007-02-07 02:55:31.208884289 +0100
@@ -120,15 +120,47 @@ typedef int __bitwise suspend_disk_metho
 #define	PM_DISK_TESTPROC	((__force suspend_disk_method_t) 6)
 #define	PM_DISK_MAX		((__force suspend_disk_method_t) 7)
 
+/**
+ * struct pm_ops
+ *
+ * Callbacks for managing platform dependent suspend states.
+ *
+ * @valid: Callback to determine whether the given state can be entered.
+ *         If %CONFIG_SOFTWARE_SUSPEND is set then %PM_SUSPEND_DISK is
+ *         always valid and never passed to this call.
+ *         If not assigned, all suspend states are advertised as valid
+ *         in /sys/power/state (but can still be rejected by prepare or enter.)
+ * @prepare: Prepare the platform for the given suspend state. Can return a
+ *           negative error code if necessary.
+ * @enter: Enter the given suspend state, must be assigned. Can return a
+ *         negative error code if necessary.
+ * @finish: Called when the system has left the given state and all devices
+ *          are resumed. The return value is ignored.
+ * @pm_disk_mode: Set to the disk method that the user should be able to
+ *                configure for suspend-to-disk. Since %PM_DISK_SHUTDOWN,
+ *                %PM_DISK_REBOOT, %PM_DISK_TEST and %PM_DISK_TESTPROC
+ *                are always allowed, currently only %PM_DISK_PLATFORM
+ *                makes sense. If the user then choses %PM_DISK_PLATFORM,
+ *                the @prepare call will be called before suspending to disk
+ *                (if present), the @enter call should be present and will
+ *                be called after all state has been saved and the machine
+ *                is ready to be shut down/suspended/..., and the @finish
+ *                callback is called after state has been restored. All
+ *                these calls are called with %PM_SUSPEND_DISK as the state.
+ */
 struct pm_ops {
-	suspend_disk_method_t pm_disk_mode;
 	int (*valid)(suspend_state_t state);
 	int (*prepare)(suspend_state_t state);
 	int (*enter)(suspend_state_t state);
 	int (*finish)(suspend_state_t state);
+	suspend_disk_method_t pm_disk_mode;
 };
 
-extern void pm_set_ops(struct pm_ops *);
+/**
+ * pm_set_ops - set platform dependent power management ops
+ * @pm_ops: The new power management operations to set.
+ */
+extern void pm_set_ops(struct pm_ops *pm_ops);
 extern struct pm_ops *pm_ops;
 extern int pm_suspend(suspend_state_t state);
 

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 05/12] power management: no valid states w/o pm_ops + docs
@ 2007-02-07 12:45   ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Rafael J. Wysocki, linux-pm, Pavel Macheck

This patch changes /sys/power/state to not advertise any valid states
(except for disk if SOFTWARE_SUSPEND is enabled) when no pm_ops have been
set so userspace can easily discover what states should be available.

Also, because the pm ops in powermac are obviously not using them as
intended, I added documentation for it in kernel-doc format.

Reordering the fields in struct pm_ops not only makes the output of
kernel-doc make more sense but also removes a hole from the structure on
64-bit platforms.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: linux-pm@lists.osdl.org
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Cc: Pavel Macheck <pavel@ucw.cz>

--- linux-2.6-git.orig/kernel/power/main.c	2007-02-07 02:55:01.676884289 +0100
+++ linux-2.6-git/kernel/power/main.c	2007-02-07 02:55:31.182884289 +0100
@@ -161,7 +161,10 @@ static inline int valid_state(suspend_st
 	if (state == PM_SUSPEND_DISK)
 		return 1;
 
-	if (pm_ops && pm_ops->valid && !pm_ops->valid(state))
+	/* all other states need lowlevel support and need to be
+	 * valid to the lowlevel implementation, no valid callback
+	 * implies that all are valid. */
+	if (!pm_ops || (pm_ops->valid && !pm_ops->valid(state)))
 		return 0;
 	return 1;
 }
--- linux-2.6-git.orig/include/linux/pm.h	2007-02-07 02:55:02.028884289 +0100
+++ linux-2.6-git/include/linux/pm.h	2007-02-07 02:55:31.208884289 +0100
@@ -120,15 +120,47 @@ typedef int __bitwise suspend_disk_metho
 #define	PM_DISK_TESTPROC	((__force suspend_disk_method_t) 6)
 #define	PM_DISK_MAX		((__force suspend_disk_method_t) 7)
 
+/**
+ * struct pm_ops
+ *
+ * Callbacks for managing platform dependent suspend states.
+ *
+ * @valid: Callback to determine whether the given state can be entered.
+ *         If %CONFIG_SOFTWARE_SUSPEND is set then %PM_SUSPEND_DISK is
+ *         always valid and never passed to this call.
+ *         If not assigned, all suspend states are advertised as valid
+ *         in /sys/power/state (but can still be rejected by prepare or enter.)
+ * @prepare: Prepare the platform for the given suspend state. Can return a
+ *           negative error code if necessary.
+ * @enter: Enter the given suspend state, must be assigned. Can return a
+ *         negative error code if necessary.
+ * @finish: Called when the system has left the given state and all devices
+ *          are resumed. The return value is ignored.
+ * @pm_disk_mode: Set to the disk method that the user should be able to
+ *                configure for suspend-to-disk. Since %PM_DISK_SHUTDOWN,
+ *                %PM_DISK_REBOOT, %PM_DISK_TEST and %PM_DISK_TESTPROC
+ *                are always allowed, currently only %PM_DISK_PLATFORM
+ *                makes sense. If the user then choses %PM_DISK_PLATFORM,
+ *                the @prepare call will be called before suspending to disk
+ *                (if present), the @enter call should be present and will
+ *                be called after all state has been saved and the machine
+ *                is ready to be shut down/suspended/..., and the @finish
+ *                callback is called after state has been restored. All
+ *                these calls are called with %PM_SUSPEND_DISK as the state.
+ */
 struct pm_ops {
-	suspend_disk_method_t pm_disk_mode;
 	int (*valid)(suspend_state_t state);
 	int (*prepare)(suspend_state_t state);
 	int (*enter)(suspend_state_t state);
 	int (*finish)(suspend_state_t state);
+	suspend_disk_method_t pm_disk_mode;
 };
 
-extern void pm_set_ops(struct pm_ops *);
+/**
+ * pm_set_ops - set platform dependent power management ops
+ * @pm_ops: The new power management operations to set.
+ */
+extern void pm_set_ops(struct pm_ops *pm_ops);
 extern struct pm_ops *pm_ops;
 extern int pm_suspend(suspend_state_t state);
 

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 06/12] powerpc: fix suspend states again
  2007-02-07 12:45 [PATCH 00/12] powerpc/powermac power management patches Johannes Berg
@ 2007-02-07 12:45   ` Johannes Berg
  2007-02-07 12:45   ` Johannes Berg
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

[-- Attachment #1: fix-powermac-suspend-again.patch --]
[-- Type: text/plain, Size: 5111 bytes --]

In commit 0fba3a1f39f8b0a50b56c8b068fa52131cbc84c2 (a very long time ago,
May 2006), I fixed a bug that caused powermacs to crash when you tried
entering standby/mem suspend states.

As I'm now getting more familiar with the suspend code I notice a few
more things:
 1. we previously misunderstood what pm_ops is for, it isn't supposed to be
    for doing platform dependent suspend/resume stuff that needs to be done
    for suspend to disk (as we currently try to use it!), it is instead for
    entering platform dependent suspend states ("standby", "mem").
 2. due to the first point, we never properly save FPU and altivec states
    when suspending to disk. It probably hasn't hurt yet because the process
    that writes the "disk" to /sys/power/state uses neither and its context
    is used.

This patch addresses these points as follows:
 1. remove all pm_ops from powermac, powermac suspend to ram isn't currently
    usable via /sys/power/state but is done via the PMU instead.
 2. move the code responsible for storing FPU/altivec state into a new
    arch_prepare_suspend function (previously, this was only present for
    32-bit platforms from asm-ppc.)

I removed
	set_context(current->active_mm->context.id, current->active_mm->pgd);
because
 1. it works without and
 2. I don't know what the point is

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>

--- linux-2.6-git.orig/arch/powerpc/platforms/powermac/setup.c	2007-02-07 02:55:27.388884289 +0100
+++ linux-2.6-git/arch/powerpc/platforms/powermac/setup.c	2007-02-07 02:55:32.107884289 +0100
@@ -420,76 +420,11 @@ static void __init find_boot_device(void
 #endif
 }
 
-/* TODO: Merge the suspend-to-ram with the common code !!!
- * currently, this is a stub implementation for suspend-to-disk
- * only
- */
-
-#ifdef CONFIG_SOFTWARE_SUSPEND
-
-static int pmac_pm_prepare(suspend_state_t state)
-{
-	printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
-
-	return 0;
-}
-
-static int pmac_pm_enter(suspend_state_t state)
-{
-	printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
-
-	/* Giveup the lazy FPU & vec so we don't have to back them
-	 * up from the low level code
-	 */
-	enable_kernel_fp();
-
-#ifdef CONFIG_ALTIVEC
-	if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
-		enable_kernel_altivec();
-#endif /* CONFIG_ALTIVEC */
-
-	return 0;
-}
-
-static int pmac_pm_finish(suspend_state_t state)
-{
-	printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
-
-	/* Restore userland MMU context */
-	set_context(current->active_mm->context.id, current->active_mm->pgd);
-
-	return 0;
-}
-
-static int pmac_pm_valid(suspend_state_t state)
-{
-	switch (state) {
-	case PM_SUSPEND_DISK:
-		return 1;
-	/* can't do any other states via generic mechanism yet */
-	default:
-		return 0;
-	}
-}
-
-static struct pm_ops pmac_pm_ops = {
-	.pm_disk_mode	= PM_DISK_SHUTDOWN,
-	.prepare	= pmac_pm_prepare,
-	.enter		= pmac_pm_enter,
-	.finish		= pmac_pm_finish,
-	.valid		= pmac_pm_valid,
-};
-
-#endif /* CONFIG_SOFTWARE_SUSPEND */
-
 static int initializing = 1;
 
 static int pmac_late_init(void)
 {
 	initializing = 0;
-#ifdef CONFIG_SOFTWARE_SUSPEND
-	pm_set_ops(&pmac_pm_ops);
-#endif /* CONFIG_SOFTWARE_SUSPEND */
 	/* this is udbg (which is __init) and we can later use it during
 	 * cpu hotplug (in smp_core99_kick_cpu) */
 	ppc_md.progress = NULL;
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-git/include/asm-powerpc/suspend.h	2007-02-07 02:55:32.124884289 +0100
@@ -0,0 +1,9 @@
+#ifndef __ASM_POWERPC_SUSPEND_H
+#define __ASM_POWERPC_SUSPEND_H
+
+static inline int arch_prepare_suspend(void) { return 0; }
+
+void save_processor_state(void);
+static inline void restore_processor_state(void) {}
+
+#endif /* __ASM_POWERPC_SUSPEND_H */
--- linux-2.6-git.orig/arch/powerpc/kernel/Makefile	2007-02-07 02:55:00.582884289 +0100
+++ linux-2.6-git/arch/powerpc/kernel/Makefile	2007-02-07 02:55:32.134884289 +0100
@@ -35,6 +35,7 @@ obj-$(CONFIG_GENERIC_TBSYNC)	+= smp-tbsy
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
 obj-$(CONFIG_6xx)		+= idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
 obj-$(CONFIG_TAU)		+= tau_6xx.o
+obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o
 obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o
 obj32-$(CONFIG_MODULES)		+= module_32.o
 
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-git/arch/powerpc/kernel/swsusp.c	2007-02-07 02:55:32.152884289 +0100
@@ -0,0 +1,26 @@
+/*
+ * Common powerpc suspend code for 32 and 64 bits
+ *
+ * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPLv2
+ */
+
+#include <asm/cputable.h>
+#include <asm/system.h>
+
+
+int save_processor_state(void)
+{
+	/* Giveup the lazy FPU & vec so we don't have to back them
+	 * up from the low level code
+	 */
+	enable_kernel_fp();
+
+#ifdef CONFIG_ALTIVEC
+	if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
+		enable_kernel_altivec();
+#endif /* CONFIG_ALTIVEC */
+
+	return 0;
+}

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 06/12] powerpc: fix suspend states again
@ 2007-02-07 12:45   ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

In commit 0fba3a1f39f8b0a50b56c8b068fa52131cbc84c2 (a very long time ago,
May 2006), I fixed a bug that caused powermacs to crash when you tried
entering standby/mem suspend states.

As I'm now getting more familiar with the suspend code I notice a few
more things:
 1. we previously misunderstood what pm_ops is for, it isn't supposed to be
    for doing platform dependent suspend/resume stuff that needs to be done
    for suspend to disk (as we currently try to use it!), it is instead for
    entering platform dependent suspend states ("standby", "mem").
 2. due to the first point, we never properly save FPU and altivec states
    when suspending to disk. It probably hasn't hurt yet because the process
    that writes the "disk" to /sys/power/state uses neither and its context
    is used.

This patch addresses these points as follows:
 1. remove all pm_ops from powermac, powermac suspend to ram isn't currently
    usable via /sys/power/state but is done via the PMU instead.
 2. move the code responsible for storing FPU/altivec state into a new
    arch_prepare_suspend function (previously, this was only present for
    32-bit platforms from asm-ppc.)

I removed
	set_context(current->active_mm->context.id, current->active_mm->pgd);
because
 1. it works without and
 2. I don't know what the point is

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>

--- linux-2.6-git.orig/arch/powerpc/platforms/powermac/setup.c	2007-02-07 02:55:27.388884289 +0100
+++ linux-2.6-git/arch/powerpc/platforms/powermac/setup.c	2007-02-07 02:55:32.107884289 +0100
@@ -420,76 +420,11 @@ static void __init find_boot_device(void
 #endif
 }
 
-/* TODO: Merge the suspend-to-ram with the common code !!!
- * currently, this is a stub implementation for suspend-to-disk
- * only
- */
-
-#ifdef CONFIG_SOFTWARE_SUSPEND
-
-static int pmac_pm_prepare(suspend_state_t state)
-{
-	printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
-
-	return 0;
-}
-
-static int pmac_pm_enter(suspend_state_t state)
-{
-	printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
-
-	/* Giveup the lazy FPU & vec so we don't have to back them
-	 * up from the low level code
-	 */
-	enable_kernel_fp();
-
-#ifdef CONFIG_ALTIVEC
-	if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
-		enable_kernel_altivec();
-#endif /* CONFIG_ALTIVEC */
-
-	return 0;
-}
-
-static int pmac_pm_finish(suspend_state_t state)
-{
-	printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
-
-	/* Restore userland MMU context */
-	set_context(current->active_mm->context.id, current->active_mm->pgd);
-
-	return 0;
-}
-
-static int pmac_pm_valid(suspend_state_t state)
-{
-	switch (state) {
-	case PM_SUSPEND_DISK:
-		return 1;
-	/* can't do any other states via generic mechanism yet */
-	default:
-		return 0;
-	}
-}
-
-static struct pm_ops pmac_pm_ops = {
-	.pm_disk_mode	= PM_DISK_SHUTDOWN,
-	.prepare	= pmac_pm_prepare,
-	.enter		= pmac_pm_enter,
-	.finish		= pmac_pm_finish,
-	.valid		= pmac_pm_valid,
-};
-
-#endif /* CONFIG_SOFTWARE_SUSPEND */
-
 static int initializing = 1;
 
 static int pmac_late_init(void)
 {
 	initializing = 0;
-#ifdef CONFIG_SOFTWARE_SUSPEND
-	pm_set_ops(&pmac_pm_ops);
-#endif /* CONFIG_SOFTWARE_SUSPEND */
 	/* this is udbg (which is __init) and we can later use it during
 	 * cpu hotplug (in smp_core99_kick_cpu) */
 	ppc_md.progress = NULL;
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-git/include/asm-powerpc/suspend.h	2007-02-07 02:55:32.124884289 +0100
@@ -0,0 +1,9 @@
+#ifndef __ASM_POWERPC_SUSPEND_H
+#define __ASM_POWERPC_SUSPEND_H
+
+static inline int arch_prepare_suspend(void) { return 0; }
+
+void save_processor_state(void);
+static inline void restore_processor_state(void) {}
+
+#endif /* __ASM_POWERPC_SUSPEND_H */
--- linux-2.6-git.orig/arch/powerpc/kernel/Makefile	2007-02-07 02:55:00.582884289 +0100
+++ linux-2.6-git/arch/powerpc/kernel/Makefile	2007-02-07 02:55:32.134884289 +0100
@@ -35,6 +35,7 @@ obj-$(CONFIG_GENERIC_TBSYNC)	+= smp-tbsy
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
 obj-$(CONFIG_6xx)		+= idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
 obj-$(CONFIG_TAU)		+= tau_6xx.o
+obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o
 obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o
 obj32-$(CONFIG_MODULES)		+= module_32.o
 
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-git/arch/powerpc/kernel/swsusp.c	2007-02-07 02:55:32.152884289 +0100
@@ -0,0 +1,26 @@
+/*
+ * Common powerpc suspend code for 32 and 64 bits
+ *
+ * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPLv2
+ */
+
+#include <asm/cputable.h>
+#include <asm/system.h>
+
+
+int save_processor_state(void)
+{
+	/* Giveup the lazy FPU & vec so we don't have to back them
+	 * up from the low level code
+	 */
+	enable_kernel_fp();
+
+#ifdef CONFIG_ALTIVEC
+	if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
+		enable_kernel_altivec();
+#endif /* CONFIG_ALTIVEC */
+
+	return 0;
+}

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 07/12] powermac: suspend to disk on G5
  2007-02-07 12:45 [PATCH 00/12] powerpc/powermac power management patches Johannes Berg
@ 2007-02-07 12:45   ` Johannes Berg
  2007-02-07 12:45   ` Johannes Berg
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

[-- Attachment #1: ppc64-swsusp.patch --]
[-- Type: text/plain, Size: 10450 bytes --]

Powermac G5 suspend to disk implementation. The code is platform
agnostic but only tested on powermac, no other 64-bit powerpc
machines.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>

---
WARNING: nvidiafb breaks suspend. I don't know why yet, but if it is
compiled and you try to suspend from X it all just freezes. The nvidiafb
suspend code looks a bit fishy but I shall have to understand first what
it's trying to achieve.

Other than that I'm really happy with this, it's good to finally be able to
hibernate the machine instead of keeping it up or shutting it down.

Tested on my powermac, this time with forced preemption enabled, of course
only together with all the other patches.

--- linux-2.6-git.orig/arch/powerpc/kernel/Makefile	2007-02-07 02:55:32.134884289 +0100
+++ linux-2.6-git/arch/powerpc/kernel/Makefile	2007-02-07 02:55:33.073884289 +0100
@@ -37,6 +37,7 @@ obj-$(CONFIG_6xx)		+= idle_6xx.o l2cr_6x
 obj-$(CONFIG_TAU)		+= tau_6xx.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o
 obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o
+obj64-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_64.o swsusp_asm64.o
 obj32-$(CONFIG_MODULES)		+= module_32.o
 
 ifeq ($(CONFIG_PPC_MERGE),y)
--- linux-2.6-git.orig/kernel/power/Kconfig	2007-02-07 02:54:59.170884289 +0100
+++ linux-2.6-git/kernel/power/Kconfig	2007-02-07 02:55:33.075884289 +0100
@@ -79,7 +79,7 @@ config PM_SYSFS_DEPRECATED
 
 config SOFTWARE_SUSPEND
 	bool "Software Suspend"
-	depends on PM && SWAP && ((X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP))
+	depends on PM && SWAP && (((X86 || PPC64) && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP))
 	---help---
 	  Enable the possibility of suspending the machine.
 	  It doesn't need ACPI or APM.
@@ -129,5 +129,5 @@ config PM_STD_PARTITION
 
 config SUSPEND_SMP
 	bool
-	depends on HOTPLUG_CPU && X86 && PM
+	depends on HOTPLUG_CPU && (X86 || PPC64) && PM
 	default y
--- linux-2.6-git.orig/include/asm-powerpc/suspend.h	2007-02-07 02:55:32.124884289 +0100
+++ linux-2.6-git/include/asm-powerpc/suspend.h	2007-02-07 02:55:33.077884289 +0100
@@ -4,6 +4,10 @@
 static inline int arch_prepare_suspend(void) { return 0; }
 
 void save_processor_state(void);
+#ifdef CONFIG_PPC32
 static inline void restore_processor_state(void) {}
+#else
+void restore_processor_state(void);
+#endif
 
 #endif /* __ASM_POWERPC_SUSPEND_H */
--- linux-2.6-git.orig/include/linux/suspend.h	2007-02-07 02:54:59.624884289 +0100
+++ linux-2.6-git/include/linux/suspend.h	2007-02-07 02:55:33.078884289 +0100
@@ -1,7 +1,7 @@
 #ifndef _LINUX_SWSUSP_H
 #define _LINUX_SWSUSP_H
 
-#if defined(CONFIG_X86) || defined(CONFIG_FRV) || defined(CONFIG_PPC32)
+#if defined(CONFIG_X86) || defined(CONFIG_FRV) || defined(CONFIG_PPC32) || defined(CONFIG_PPC64)
 #include <asm/suspend.h>
 #endif
 #include <linux/swap.h>
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-git/arch/powerpc/kernel/swsusp_64.c	2007-02-07 02:55:33.080884289 +0100
@@ -0,0 +1,29 @@
+/*
+ * PowerPC 64-bit swsusp implementation
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPLv2
+ */
+
+#include <asm/system.h>
+#include <asm/iommu.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+void restore_processor_state(void)
+{
+	hard_irq_enable();
+}
+
+void do_after_copyback(void)
+{
+	iommu_restore();
+	touch_softlockup_watchdog();
+	mb();
+}
+
+void _iommu_save(void)
+{
+	iommu_save();
+}
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-git/arch/powerpc/kernel/swsusp_asm64.S	2007-02-07 02:55:33.083884289 +0100
@@ -0,0 +1,228 @@
+/*
+ * PowerPC 64-bit swsusp implementation
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPLv2
+ */
+
+#include <linux/threads.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+
+/*
+ * Structure for storing CPU registers on the save area.
+ */
+#define SL_r1		0x00	/* stack pointer */
+#define SL_PC		0x08
+#define SL_MSR		0x10
+#define SL_SDR1		0x18
+#define SL_XER		0x20
+#define SL_TB		0x40
+#define SL_r2		0x48
+#define SL_CR		0x50
+#define SL_LR		0x58
+#define SL_r12		0x60
+#define SL_r13		0x68
+#define SL_r14		0x70
+#define SL_r15		0x78
+#define SL_r16		0x80
+#define SL_r17		0x88
+#define SL_r18		0x90
+#define SL_r19		0x98
+#define SL_r20		0xa0
+#define SL_r21		0xa8
+#define SL_r22		0xb0
+#define SL_r23		0xb8
+#define SL_r24		0xc0
+#define SL_r25		0xc8
+#define SL_r26		0xd0
+#define SL_r27		0xd8
+#define SL_r28		0xe0
+#define SL_r29		0xe8
+#define SL_r30		0xf0
+#define SL_r31		0xf8
+#define SL_SIZE		SL_r31+8
+
+/* these macros rely on the save area being
+ * pointed to by r11 */
+#define SAVE_SPECIAL(special)		\
+	mf##special	r0		;\
+	std	r0, SL_##special(r11)
+#define RESTORE_SPECIAL(special)	\
+	ld	r0, SL_##special(r11)	;\
+	mt##special	r0
+#define SAVE_REGISTER(reg)		\
+	std	reg, SL_##reg(r11)
+#define RESTORE_REGISTER(reg)		\
+	ld	reg, SL_##reg(r11)
+
+/* space for storing cpu state */
+	.section .data
+	.align  5
+swsusp_save_area:
+	.space SL_SIZE
+
+	.section ".toc","aw"
+swsusp_save_area_ptr:
+	.tc	swsusp_save_area[TC],swsusp_save_area
+restore_pblist_ptr:
+	.tc	restore_pblist[TC],restore_pblist
+
+	.section .text
+	.align  5
+_GLOBAL(swsusp_arch_suspend)
+	ld	r11,swsusp_save_area_ptr@toc(r2)
+	SAVE_SPECIAL(LR)
+	SAVE_REGISTER(r1)
+	SAVE_SPECIAL(CR)
+	SAVE_SPECIAL(TB)
+	SAVE_REGISTER(r2)
+	SAVE_REGISTER(r12)
+	SAVE_REGISTER(r13)
+	SAVE_REGISTER(r14)
+	SAVE_REGISTER(r15)
+	SAVE_REGISTER(r16)
+	SAVE_REGISTER(r17)
+	SAVE_REGISTER(r18)
+	SAVE_REGISTER(r19)
+	SAVE_REGISTER(r20)
+	SAVE_REGISTER(r21)
+	SAVE_REGISTER(r22)
+	SAVE_REGISTER(r23)
+	SAVE_REGISTER(r24)
+	SAVE_REGISTER(r25)
+	SAVE_REGISTER(r26)
+	SAVE_REGISTER(r27)
+	SAVE_REGISTER(r28)
+	SAVE_REGISTER(r29)
+	SAVE_REGISTER(r30)
+	SAVE_REGISTER(r31)
+	SAVE_SPECIAL(MSR)
+	SAVE_SPECIAL(SDR1)
+	SAVE_SPECIAL(XER)
+
+	/* we push the stack up 128 bytes but don't store the
+	 * stack pointer on the stack like a real stackframe */
+	addi	r1,r1,-128
+
+	bl _iommu_save
+	bl swsusp_save
+
+	/* restore LR */
+	ld	r11,swsusp_save_area_ptr@toc(r2)
+	RESTORE_SPECIAL(LR)
+	addi	r1,r1,128
+
+	blr
+
+/* Resume code */
+_GLOBAL(swsusp_arch_resume)
+	/* Stop pending alitvec streams and memory accesses */
+BEGIN_FTR_SECTION
+	DSSALL
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+	sync
+
+	ld	r12,restore_pblist_ptr@toc(r2)
+	ld	r12,0(r12)
+
+	cmpdi	r12,0
+	beq-	nothing_to_copy
+	li	r15,512
+copyloop:
+	ld	r13,pbe_address(r12)
+	ld	r14,pbe_orig_address(r12)
+
+	mtctr	r15
+	li	r10,0
+copy_page_loop:
+	ldx	r0,r10,r13
+	stdx	r0,r10,r14
+	addi	r10,r10,8
+	bdnz copy_page_loop
+
+	ld	r12,pbe_next(r12)
+	cmpdi	r12,0
+	bne+	copyloop
+nothing_to_copy:
+
+	/* flush caches */
+	lis	r3, 0x10
+	mtctr	r3
+	li	r3, 0
+	ori	r3, r3, CONFIG_KERNEL_START>>48
+	li	r0, 48
+	sld	r3, r3, r0
+	li	r0, 0
+1:
+	dcbf	r0,r3
+	addi	r3,r3,0x20
+	bdnz	1b
+
+	sync
+
+	tlbia
+
+	ld	r11,swsusp_save_area_ptr@toc(r2)
+
+	RESTORE_SPECIAL(CR)
+
+	/* restore timebase */
+	/* load saved tb */
+	ld	r1, SL_TB(r11)
+	/* get upper 32 bits of it */
+	srdi	r2, r1, 32
+	/* clear tb lower to avoid wrap */
+	li	r0, 0
+	mttbl	r0
+	/* set tb upper */
+	mttbu	r2
+	/* set tb lower */
+	mttbl	r1
+
+	/* restore registers */
+	RESTORE_REGISTER(r1)
+	RESTORE_REGISTER(r2)
+	RESTORE_REGISTER(r12)
+	RESTORE_REGISTER(r13)
+	RESTORE_REGISTER(r14)
+	RESTORE_REGISTER(r15)
+	RESTORE_REGISTER(r16)
+	RESTORE_REGISTER(r17)
+	RESTORE_REGISTER(r18)
+	RESTORE_REGISTER(r19)
+	RESTORE_REGISTER(r20)
+	RESTORE_REGISTER(r21)
+	RESTORE_REGISTER(r22)
+	RESTORE_REGISTER(r23)
+	RESTORE_REGISTER(r24)
+	RESTORE_REGISTER(r25)
+	RESTORE_REGISTER(r26)
+	RESTORE_REGISTER(r27)
+	RESTORE_REGISTER(r28)
+	RESTORE_REGISTER(r29)
+	RESTORE_REGISTER(r30)
+	RESTORE_REGISTER(r31)
+	/* can't use RESTORE_SPECIAL(MSR) */
+	ld	r0, SL_MSR(r11)
+	mtmsrd	r0, 0
+	RESTORE_SPECIAL(SDR1)
+	RESTORE_SPECIAL(XER)
+
+	sync
+
+	addi	r1,r1,-128
+	bl	slb_flush_and_rebolt
+	bl	do_after_copyback
+	addi	r1,r1,128
+
+	ld	r11,swsusp_save_area_ptr@toc(r2)
+	RESTORE_SPECIAL(LR)
+
+	li	r3, 0
+	blr
--- linux-2.6-git.orig/arch/powerpc/kernel/asm-offsets.c	2007-02-07 02:54:58.868884289 +0100
+++ linux-2.6-git/arch/powerpc/kernel/asm-offsets.c	2007-02-07 02:55:33.085884289 +0100
@@ -21,12 +21,12 @@
 #include <linux/types.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
+#include <linux/suspend.h>
 #ifdef CONFIG_PPC64
 #include <linux/time.h>
 #include <linux/hardirq.h>
 #else
 #include <linux/ptrace.h>
-#include <linux/suspend.h>
 #endif
 
 #include <asm/io.h>
@@ -257,11 +257,11 @@ int main(void)
 	DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
 	DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore));
 
-#ifndef CONFIG_PPC64
 	DEFINE(pbe_address, offsetof(struct pbe, address));
 	DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
 	DEFINE(pbe_next, offsetof(struct pbe, next));
 
+#ifndef CONFIG_PPC64
 	DEFINE(TASK_SIZE, TASK_SIZE);
 	DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28);
 #endif /* ! CONFIG_PPC64 */
--- linux-2.6-git.orig/arch/powerpc/kernel/idle.c	2007-02-07 02:54:58.912884289 +0100
+++ linux-2.6-git/arch/powerpc/kernel/idle.c	2007-02-07 02:55:33.086884289 +0100
@@ -33,8 +33,11 @@
 #include <asm/smp.h>
 
 #ifdef CONFIG_HOTPLUG_CPU
+/* this is used for software suspend, and that shuts down
+ * CPUs even while the system is still booting... */
 #define cpu_should_die()	(cpu_is_offline(smp_processor_id()) && \
-				 system_state == SYSTEM_RUNNING)
+				   (system_state == SYSTEM_RUNNING     \
+				 || system_state == SYSTEM_BOOTING))
 #else
 #define cpu_should_die()	0
 #endif
--- linux-2.6-git.orig/arch/powerpc/kernel/swsusp.c	2007-02-07 02:55:32.152884289 +0100
+++ linux-2.6-git/arch/powerpc/kernel/swsusp.c	2007-02-07 02:55:33.087884289 +0100
@@ -22,5 +22,9 @@ int save_processor_state(void)
 		enable_kernel_altivec();
 #endif /* CONFIG_ALTIVEC */
 
+#ifdef CONFIG_PPC64
+	hard_irq_disable();
+#endif
+
 	return 0;
 }

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 07/12] powermac: suspend to disk on G5
@ 2007-02-07 12:45   ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

Powermac G5 suspend to disk implementation. The code is platform
agnostic but only tested on powermac, no other 64-bit powerpc
machines.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>

---
WARNING: nvidiafb breaks suspend. I don't know why yet, but if it is
compiled and you try to suspend from X it all just freezes. The nvidiafb
suspend code looks a bit fishy but I shall have to understand first what
it's trying to achieve.

Other than that I'm really happy with this, it's good to finally be able to
hibernate the machine instead of keeping it up or shutting it down.

Tested on my powermac, this time with forced preemption enabled, of course
only together with all the other patches.

--- linux-2.6-git.orig/arch/powerpc/kernel/Makefile	2007-02-07 02:55:32.134884289 +0100
+++ linux-2.6-git/arch/powerpc/kernel/Makefile	2007-02-07 02:55:33.073884289 +0100
@@ -37,6 +37,7 @@ obj-$(CONFIG_6xx)		+= idle_6xx.o l2cr_6x
 obj-$(CONFIG_TAU)		+= tau_6xx.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o
 obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o
+obj64-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_64.o swsusp_asm64.o
 obj32-$(CONFIG_MODULES)		+= module_32.o
 
 ifeq ($(CONFIG_PPC_MERGE),y)
--- linux-2.6-git.orig/kernel/power/Kconfig	2007-02-07 02:54:59.170884289 +0100
+++ linux-2.6-git/kernel/power/Kconfig	2007-02-07 02:55:33.075884289 +0100
@@ -79,7 +79,7 @@ config PM_SYSFS_DEPRECATED
 
 config SOFTWARE_SUSPEND
 	bool "Software Suspend"
-	depends on PM && SWAP && ((X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP))
+	depends on PM && SWAP && (((X86 || PPC64) && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP))
 	---help---
 	  Enable the possibility of suspending the machine.
 	  It doesn't need ACPI or APM.
@@ -129,5 +129,5 @@ config PM_STD_PARTITION
 
 config SUSPEND_SMP
 	bool
-	depends on HOTPLUG_CPU && X86 && PM
+	depends on HOTPLUG_CPU && (X86 || PPC64) && PM
 	default y
--- linux-2.6-git.orig/include/asm-powerpc/suspend.h	2007-02-07 02:55:32.124884289 +0100
+++ linux-2.6-git/include/asm-powerpc/suspend.h	2007-02-07 02:55:33.077884289 +0100
@@ -4,6 +4,10 @@
 static inline int arch_prepare_suspend(void) { return 0; }
 
 void save_processor_state(void);
+#ifdef CONFIG_PPC32
 static inline void restore_processor_state(void) {}
+#else
+void restore_processor_state(void);
+#endif
 
 #endif /* __ASM_POWERPC_SUSPEND_H */
--- linux-2.6-git.orig/include/linux/suspend.h	2007-02-07 02:54:59.624884289 +0100
+++ linux-2.6-git/include/linux/suspend.h	2007-02-07 02:55:33.078884289 +0100
@@ -1,7 +1,7 @@
 #ifndef _LINUX_SWSUSP_H
 #define _LINUX_SWSUSP_H
 
-#if defined(CONFIG_X86) || defined(CONFIG_FRV) || defined(CONFIG_PPC32)
+#if defined(CONFIG_X86) || defined(CONFIG_FRV) || defined(CONFIG_PPC32) || defined(CONFIG_PPC64)
 #include <asm/suspend.h>
 #endif
 #include <linux/swap.h>
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-git/arch/powerpc/kernel/swsusp_64.c	2007-02-07 02:55:33.080884289 +0100
@@ -0,0 +1,29 @@
+/*
+ * PowerPC 64-bit swsusp implementation
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPLv2
+ */
+
+#include <asm/system.h>
+#include <asm/iommu.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+void restore_processor_state(void)
+{
+	hard_irq_enable();
+}
+
+void do_after_copyback(void)
+{
+	iommu_restore();
+	touch_softlockup_watchdog();
+	mb();
+}
+
+void _iommu_save(void)
+{
+	iommu_save();
+}
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-git/arch/powerpc/kernel/swsusp_asm64.S	2007-02-07 02:55:33.083884289 +0100
@@ -0,0 +1,228 @@
+/*
+ * PowerPC 64-bit swsusp implementation
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPLv2
+ */
+
+#include <linux/threads.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+
+/*
+ * Structure for storing CPU registers on the save area.
+ */
+#define SL_r1		0x00	/* stack pointer */
+#define SL_PC		0x08
+#define SL_MSR		0x10
+#define SL_SDR1		0x18
+#define SL_XER		0x20
+#define SL_TB		0x40
+#define SL_r2		0x48
+#define SL_CR		0x50
+#define SL_LR		0x58
+#define SL_r12		0x60
+#define SL_r13		0x68
+#define SL_r14		0x70
+#define SL_r15		0x78
+#define SL_r16		0x80
+#define SL_r17		0x88
+#define SL_r18		0x90
+#define SL_r19		0x98
+#define SL_r20		0xa0
+#define SL_r21		0xa8
+#define SL_r22		0xb0
+#define SL_r23		0xb8
+#define SL_r24		0xc0
+#define SL_r25		0xc8
+#define SL_r26		0xd0
+#define SL_r27		0xd8
+#define SL_r28		0xe0
+#define SL_r29		0xe8
+#define SL_r30		0xf0
+#define SL_r31		0xf8
+#define SL_SIZE		SL_r31+8
+
+/* these macros rely on the save area being
+ * pointed to by r11 */
+#define SAVE_SPECIAL(special)		\
+	mf##special	r0		;\
+	std	r0, SL_##special(r11)
+#define RESTORE_SPECIAL(special)	\
+	ld	r0, SL_##special(r11)	;\
+	mt##special	r0
+#define SAVE_REGISTER(reg)		\
+	std	reg, SL_##reg(r11)
+#define RESTORE_REGISTER(reg)		\
+	ld	reg, SL_##reg(r11)
+
+/* space for storing cpu state */
+	.section .data
+	.align  5
+swsusp_save_area:
+	.space SL_SIZE
+
+	.section ".toc","aw"
+swsusp_save_area_ptr:
+	.tc	swsusp_save_area[TC],swsusp_save_area
+restore_pblist_ptr:
+	.tc	restore_pblist[TC],restore_pblist
+
+	.section .text
+	.align  5
+_GLOBAL(swsusp_arch_suspend)
+	ld	r11,swsusp_save_area_ptr@toc(r2)
+	SAVE_SPECIAL(LR)
+	SAVE_REGISTER(r1)
+	SAVE_SPECIAL(CR)
+	SAVE_SPECIAL(TB)
+	SAVE_REGISTER(r2)
+	SAVE_REGISTER(r12)
+	SAVE_REGISTER(r13)
+	SAVE_REGISTER(r14)
+	SAVE_REGISTER(r15)
+	SAVE_REGISTER(r16)
+	SAVE_REGISTER(r17)
+	SAVE_REGISTER(r18)
+	SAVE_REGISTER(r19)
+	SAVE_REGISTER(r20)
+	SAVE_REGISTER(r21)
+	SAVE_REGISTER(r22)
+	SAVE_REGISTER(r23)
+	SAVE_REGISTER(r24)
+	SAVE_REGISTER(r25)
+	SAVE_REGISTER(r26)
+	SAVE_REGISTER(r27)
+	SAVE_REGISTER(r28)
+	SAVE_REGISTER(r29)
+	SAVE_REGISTER(r30)
+	SAVE_REGISTER(r31)
+	SAVE_SPECIAL(MSR)
+	SAVE_SPECIAL(SDR1)
+	SAVE_SPECIAL(XER)
+
+	/* we push the stack up 128 bytes but don't store the
+	 * stack pointer on the stack like a real stackframe */
+	addi	r1,r1,-128
+
+	bl _iommu_save
+	bl swsusp_save
+
+	/* restore LR */
+	ld	r11,swsusp_save_area_ptr@toc(r2)
+	RESTORE_SPECIAL(LR)
+	addi	r1,r1,128
+
+	blr
+
+/* Resume code */
+_GLOBAL(swsusp_arch_resume)
+	/* Stop pending alitvec streams and memory accesses */
+BEGIN_FTR_SECTION
+	DSSALL
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+	sync
+
+	ld	r12,restore_pblist_ptr@toc(r2)
+	ld	r12,0(r12)
+
+	cmpdi	r12,0
+	beq-	nothing_to_copy
+	li	r15,512
+copyloop:
+	ld	r13,pbe_address(r12)
+	ld	r14,pbe_orig_address(r12)
+
+	mtctr	r15
+	li	r10,0
+copy_page_loop:
+	ldx	r0,r10,r13
+	stdx	r0,r10,r14
+	addi	r10,r10,8
+	bdnz copy_page_loop
+
+	ld	r12,pbe_next(r12)
+	cmpdi	r12,0
+	bne+	copyloop
+nothing_to_copy:
+
+	/* flush caches */
+	lis	r3, 0x10
+	mtctr	r3
+	li	r3, 0
+	ori	r3, r3, CONFIG_KERNEL_START>>48
+	li	r0, 48
+	sld	r3, r3, r0
+	li	r0, 0
+1:
+	dcbf	r0,r3
+	addi	r3,r3,0x20
+	bdnz	1b
+
+	sync
+
+	tlbia
+
+	ld	r11,swsusp_save_area_ptr@toc(r2)
+
+	RESTORE_SPECIAL(CR)
+
+	/* restore timebase */
+	/* load saved tb */
+	ld	r1, SL_TB(r11)
+	/* get upper 32 bits of it */
+	srdi	r2, r1, 32
+	/* clear tb lower to avoid wrap */
+	li	r0, 0
+	mttbl	r0
+	/* set tb upper */
+	mttbu	r2
+	/* set tb lower */
+	mttbl	r1
+
+	/* restore registers */
+	RESTORE_REGISTER(r1)
+	RESTORE_REGISTER(r2)
+	RESTORE_REGISTER(r12)
+	RESTORE_REGISTER(r13)
+	RESTORE_REGISTER(r14)
+	RESTORE_REGISTER(r15)
+	RESTORE_REGISTER(r16)
+	RESTORE_REGISTER(r17)
+	RESTORE_REGISTER(r18)
+	RESTORE_REGISTER(r19)
+	RESTORE_REGISTER(r20)
+	RESTORE_REGISTER(r21)
+	RESTORE_REGISTER(r22)
+	RESTORE_REGISTER(r23)
+	RESTORE_REGISTER(r24)
+	RESTORE_REGISTER(r25)
+	RESTORE_REGISTER(r26)
+	RESTORE_REGISTER(r27)
+	RESTORE_REGISTER(r28)
+	RESTORE_REGISTER(r29)
+	RESTORE_REGISTER(r30)
+	RESTORE_REGISTER(r31)
+	/* can't use RESTORE_SPECIAL(MSR) */
+	ld	r0, SL_MSR(r11)
+	mtmsrd	r0, 0
+	RESTORE_SPECIAL(SDR1)
+	RESTORE_SPECIAL(XER)
+
+	sync
+
+	addi	r1,r1,-128
+	bl	slb_flush_and_rebolt
+	bl	do_after_copyback
+	addi	r1,r1,128
+
+	ld	r11,swsusp_save_area_ptr@toc(r2)
+	RESTORE_SPECIAL(LR)
+
+	li	r3, 0
+	blr
--- linux-2.6-git.orig/arch/powerpc/kernel/asm-offsets.c	2007-02-07 02:54:58.868884289 +0100
+++ linux-2.6-git/arch/powerpc/kernel/asm-offsets.c	2007-02-07 02:55:33.085884289 +0100
@@ -21,12 +21,12 @@
 #include <linux/types.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
+#include <linux/suspend.h>
 #ifdef CONFIG_PPC64
 #include <linux/time.h>
 #include <linux/hardirq.h>
 #else
 #include <linux/ptrace.h>
-#include <linux/suspend.h>
 #endif
 
 #include <asm/io.h>
@@ -257,11 +257,11 @@ int main(void)
 	DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
 	DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore));
 
-#ifndef CONFIG_PPC64
 	DEFINE(pbe_address, offsetof(struct pbe, address));
 	DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
 	DEFINE(pbe_next, offsetof(struct pbe, next));
 
+#ifndef CONFIG_PPC64
 	DEFINE(TASK_SIZE, TASK_SIZE);
 	DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28);
 #endif /* ! CONFIG_PPC64 */
--- linux-2.6-git.orig/arch/powerpc/kernel/idle.c	2007-02-07 02:54:58.912884289 +0100
+++ linux-2.6-git/arch/powerpc/kernel/idle.c	2007-02-07 02:55:33.086884289 +0100
@@ -33,8 +33,11 @@
 #include <asm/smp.h>
 
 #ifdef CONFIG_HOTPLUG_CPU
+/* this is used for software suspend, and that shuts down
+ * CPUs even while the system is still booting... */
 #define cpu_should_die()	(cpu_is_offline(smp_processor_id()) && \
-				 system_state == SYSTEM_RUNNING)
+				   (system_state == SYSTEM_RUNNING     \
+				 || system_state == SYSTEM_BOOTING))
 #else
 #define cpu_should_die()	0
 #endif
--- linux-2.6-git.orig/arch/powerpc/kernel/swsusp.c	2007-02-07 02:55:32.152884289 +0100
+++ linux-2.6-git/arch/powerpc/kernel/swsusp.c	2007-02-07 02:55:33.087884289 +0100
@@ -22,5 +22,9 @@ int save_processor_state(void)
 		enable_kernel_altivec();
 #endif /* CONFIG_ALTIVEC */
 
+#ifdef CONFIG_PPC64
+	hard_irq_disable();
+#endif
+
 	return 0;
 }

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 08/12] powermac: fix G5-cpufreq for cpu on/offline
  2007-02-07 12:45 [PATCH 00/12] powerpc/powermac power management patches Johannes Berg
@ 2007-02-07 12:45   ` Johannes Berg
  2007-02-07 12:45   ` Johannes Berg
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackeras, cpufreq, linux-pm, Benjamin Herrenschmidt

[-- Attachment #1: powermac-fix-cpufreq.patch --]
[-- Type: text/plain, Size: 1487 bytes --]

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.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Paul Mackeras <paulus@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: cpufreq@lists.linux.org.uk
Cc: Jacob Shin <jacob.shin@amd.com>

---
Tested on my powermac with suspend-to-disk.
Paul, please apply to powerpc.

--- linux-2.6-git.orig/arch/powerpc/platforms/powermac/cpufreq_64.c	2007-02-07 02:54:58.341884289 +0100
+++ linux-2.6-git/arch/powerpc/platforms/powermac/cpufreq_64.c	2007-02-07 02:55:34.023884289 +0100
@@ -357,13 +357,13 @@ static unsigned int g5_cpufreq_get_speed
 
 static int g5_cpufreq_cpu_init(struct cpufreq_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
+	 * cpufreq core if in the secondary policy we tell it that
+	 * it actually must be one policy together with all others. */
+	policy->cpus = cpu_online_map;
 	cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu);
 
 	return cpufreq_frequency_table_cpuinfo(policy,

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 08/12] powermac: fix G5-cpufreq for cpu on/offline
@ 2007-02-07 12:45   ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackeras, cpufreq, linux-pm, Jacob Shin

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.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Paul Mackeras <paulus@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: cpufreq@lists.linux.org.uk
Cc: Jacob Shin <jacob.shin@amd.com>

---
Tested on my powermac with suspend-to-disk.
Paul, please apply to powerpc.

--- linux-2.6-git.orig/arch/powerpc/platforms/powermac/cpufreq_64.c	2007-02-07 02:54:58.341884289 +0100
+++ linux-2.6-git/arch/powerpc/platforms/powermac/cpufreq_64.c	2007-02-07 02:55:34.023884289 +0100
@@ -357,13 +357,13 @@ static unsigned int g5_cpufreq_get_speed
 
 static int g5_cpufreq_cpu_init(struct cpufreq_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
+	 * cpufreq core if in the secondary policy we tell it that
+	 * it actually must be one policy together with all others. */
+	policy->cpus = cpu_online_map;
 	cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu);
 
 	return cpufreq_frequency_table_cpuinfo(policy,

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 09/12] powerpc: remove bogus comment about page_is_ram
  2007-02-07 12:45 [PATCH 00/12] powerpc/powermac power management patches Johannes Berg
@ 2007-02-07 12:45   ` Johannes Berg
  2007-02-07 12:45   ` Johannes Berg
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

[-- Attachment #1: remove-bogus-page_is_ram-comment.patch --]
[-- Type: text/plain, Size: 808 bytes --]

arch/powerpc/mm/mem.c states that page_is_ram is called by the code that
implements /dev/mem which isn't true. Remove the comment.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Paul Mackerras <paulus@samba.org>

---
Please apply to the powerpc tree.

--- linux-2.6-git.orig/arch/powerpc/mm/mem.c	2007-02-07 02:55:30.496884289 +0100
+++ linux-2.6-git/arch/powerpc/mm/mem.c	2007-02-07 02:55:34.636884289 +0100
@@ -61,10 +61,6 @@ unsigned long memory_limit;
 extern void hash_preload(struct mm_struct *mm, unsigned long ea,
 			 unsigned long access, unsigned long trap);
 
-/*
- * This is called by /dev/mem to know if a given address has to
- * be mapped non-cacheable or not
- */
 int page_is_ram(unsigned long pfn)
 {
 	unsigned long paddr = (pfn << PAGE_SHIFT);

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 09/12] powerpc: remove bogus comment about page_is_ram
@ 2007-02-07 12:45   ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras, linux-pm

arch/powerpc/mm/mem.c states that page_is_ram is called by the code that
implements /dev/mem which isn't true. Remove the comment.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Paul Mackerras <paulus@samba.org>

---
Please apply to the powerpc tree.

--- linux-2.6-git.orig/arch/powerpc/mm/mem.c	2007-02-07 02:55:30.496884289 +0100
+++ linux-2.6-git/arch/powerpc/mm/mem.c	2007-02-07 02:55:34.636884289 +0100
@@ -61,10 +61,6 @@ unsigned long memory_limit;
 extern void hash_preload(struct mm_struct *mm, unsigned long ea,
 			 unsigned long access, unsigned long trap);
 
-/*
- * This is called by /dev/mem to know if a given address has to
- * be mapped non-cacheable or not
- */
 int page_is_ram(unsigned long pfn)
 {
 	unsigned long paddr = (pfn << PAGE_SHIFT);

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 10/12] powerpc: remove unneeded exports in mem.c
  2007-02-07 12:45 [PATCH 00/12] powerpc/powermac power management patches Johannes Berg
@ 2007-02-07 12:45   ` Johannes Berg
  2007-02-07 12:45   ` Johannes Berg
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

[-- Attachment #1: remove-unneeded-exports.patch --]
[-- Type: text/plain, Size: 969 bytes --]

arch/powerpc/mm/mem.c exports page_is_ram and phys_mem_access_prot which
both are not used anywhere that could be modular.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Paul Mackerras <paulus@samba.org>

---
I don't see any possible way these could be used by external modules either,
especially since they are not portable across arches.

--- linux-2.6-git.orig/arch/powerpc/mm/mem.c	2007-02-07 02:55:34.636884289 +0100
+++ linux-2.6-git/arch/powerpc/mm/mem.c	2007-02-07 02:55:35.252884289 +0100
@@ -83,7 +83,6 @@ int page_is_ram(unsigned long pfn)
 	return 0;
 #endif
 }
-EXPORT_SYMBOL(page_is_ram);
 
 pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 			      unsigned long size, pgprot_t vma_prot)
@@ -96,7 +95,6 @@ pgprot_t phys_mem_access_prot(struct fil
 				    | _PAGE_GUARDED | _PAGE_NO_CACHE);
 	return vma_prot;
 }
-EXPORT_SYMBOL(phys_mem_access_prot);
 
 #ifdef CONFIG_MEMORY_HOTPLUG
 

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 10/12] powerpc: remove unneeded exports in mem.c
@ 2007-02-07 12:45   ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras, linux-pm

arch/powerpc/mm/mem.c exports page_is_ram and phys_mem_access_prot which
both are not used anywhere that could be modular.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Paul Mackerras <paulus@samba.org>

---
I don't see any possible way these could be used by external modules either,
especially since they are not portable across arches.

--- linux-2.6-git.orig/arch/powerpc/mm/mem.c	2007-02-07 02:55:34.636884289 +0100
+++ linux-2.6-git/arch/powerpc/mm/mem.c	2007-02-07 02:55:35.252884289 +0100
@@ -83,7 +83,6 @@ int page_is_ram(unsigned long pfn)
 	return 0;
 #endif
 }
-EXPORT_SYMBOL(page_is_ram);
 
 pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 			      unsigned long size, pgprot_t vma_prot)
@@ -96,7 +95,6 @@ pgprot_t phys_mem_access_prot(struct fil
 				    | _PAGE_GUARDED | _PAGE_NO_CACHE);
 	return vma_prot;
 }
-EXPORT_SYMBOL(phys_mem_access_prot);
 
 #ifdef CONFIG_MEMORY_HOTPLUG
 

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 11/12] powermac: disallow pmu sleep notifiers from aborting sleep
  2007-02-07 12:45 [PATCH 00/12] powerpc/powermac power management patches Johannes Berg
@ 2007-02-07 12:45   ` Johannes Berg
  2007-02-07 12:45   ` Johannes Berg
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

[-- Attachment #1: less-pmu-sleep-notifier.patch --]
[-- Type: text/plain, Size: 8814 bytes --]

Tracing through the code, no current PMU sleep notifier can abort sleep.
Since no new PMU sleep notifiers should be added, this patch simplifies the
code and removes the ability to abort sleep.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>

---
This is just something I did before I understood how to do the next patch
in this series. If you want, I can drop this one and rework the next, it's
very well possible to abort suspend from these callbacks even with the
next patch.

--- linux-2.6-git.orig/drivers/macintosh/adb.c	2007-02-07 02:54:56.301884289 +0100
+++ linux-2.6-git/drivers/macintosh/adb.c	2007-02-07 02:55:35.961884289 +0100
@@ -90,7 +90,7 @@ static int autopoll_devs;
 int __adb_probe_sync;
 
 #ifdef CONFIG_PM
-static int adb_notify_sleep(struct pmu_sleep_notifier *self, int when);
+static void adb_notify_sleep(struct pmu_sleep_notifier *self, int when);
 static struct pmu_sleep_notifier adb_sleep_notifier = {
 	adb_notify_sleep,
 	SLEEP_LEVEL_ADB,
@@ -340,11 +340,9 @@ __initcall(adb_init);
 /*
  * notify clients before sleep and reset bus afterwards
  */
-int
+void
 adb_notify_sleep(struct pmu_sleep_notifier *self, int when)
 {
-	int ret;
-	
 	switch (when) {
 	case PBOOK_SLEEP_REQUEST:
 		adb_got_sleep = 1;
@@ -353,22 +351,8 @@ adb_notify_sleep(struct pmu_sleep_notifi
 		/* Stop autopoll */
 		if (adb_controller->autopoll)
 			adb_controller->autopoll(0);
-		ret = blocking_notifier_call_chain(&adb_client_list,
-				ADB_MSG_POWERDOWN, NULL);
-		if (ret & NOTIFY_STOP_MASK) {
-			up(&adb_probe_mutex);
-			return PBOOK_SLEEP_REFUSE;
-		}
-		break;
-	case PBOOK_SLEEP_REJECT:
-		if (adb_got_sleep) {
-			adb_got_sleep = 0;
-			up(&adb_probe_mutex);
-			adb_reset_bus();
-		}
-		break;
-		
-	case PBOOK_SLEEP_NOW:
+		blocking_notifier_call_chain(&adb_client_list,
+			ADB_MSG_POWERDOWN, NULL);
 		break;
 	case PBOOK_WAKE:
 		adb_got_sleep = 0;
@@ -376,14 +360,13 @@ adb_notify_sleep(struct pmu_sleep_notifi
 		adb_reset_bus();
 		break;
 	}
-	return PBOOK_SLEEP_OK;
 }
 #endif /* CONFIG_PM */
 
 static int
 do_adb_reset_bus(void)
 {
-	int ret, nret;
+	int ret;
 	
 	if (adb_controller == NULL)
 		return -ENXIO;
@@ -391,13 +374,8 @@ do_adb_reset_bus(void)
 	if (adb_controller->autopoll)
 		adb_controller->autopoll(0);
 
-	nret = blocking_notifier_call_chain(&adb_client_list,
-			ADB_MSG_PRE_RESET, NULL);
-	if (nret & NOTIFY_STOP_MASK) {
-		if (adb_controller->autopoll)
-			adb_controller->autopoll(autopoll_devs);
-		return -EBUSY;
-	}
+	blocking_notifier_call_chain(&adb_client_list,
+		ADB_MSG_PRE_RESET, NULL);
 
 	if (sleepy_trackpad) {
 		/* Let the trackpad settle down */
@@ -427,10 +405,8 @@ do_adb_reset_bus(void)
 	}
 	up(&adb_handler_sem);
 
-	nret = blocking_notifier_call_chain(&adb_client_list,
-			ADB_MSG_POST_RESET, NULL);
-	if (nret & NOTIFY_STOP_MASK)
-		return -EBUSY;
+	blocking_notifier_call_chain(&adb_client_list,
+		ADB_MSG_POST_RESET, NULL);
 	
 	return ret;
 }
--- linux-2.6-git.orig/drivers/macintosh/via-pmu.c	2007-02-07 02:54:56.363884289 +0100
+++ linux-2.6-git/drivers/macintosh/via-pmu.c	2007-02-07 02:55:35.966884289 +0100
@@ -1770,35 +1770,21 @@ EXPORT_SYMBOL(pmu_unregister_sleep_notif
 #if defined(CONFIG_PM) && defined(CONFIG_PPC32)
 
 /* Sleep is broadcast last-to-first */
-static int
-broadcast_sleep(int when, int fallback)
+static void broadcast_sleep(int when)
 {
-	int ret = PBOOK_SLEEP_OK;
 	struct list_head *list;
 	struct pmu_sleep_notifier *notifier;
 
 	for (list = sleep_notifiers.prev; list != &sleep_notifiers;
 	     list = list->prev) {
 		notifier = list_entry(list, struct pmu_sleep_notifier, list);
-		ret = notifier->notifier_call(notifier, when);
-		if (ret != PBOOK_SLEEP_OK) {
-			printk(KERN_DEBUG "sleep %d rejected by %p (%p)\n",
-			       when, notifier, notifier->notifier_call);
-			for (; list != &sleep_notifiers; list = list->next) {
-				notifier = list_entry(list, struct pmu_sleep_notifier, list);
-				notifier->notifier_call(notifier, fallback);
-			}
-			return ret;
-		}
+		notifier->notifier_call(notifier, when);
 	}
-	return ret;
 }
 
 /* Wake is broadcast first-to-last */
-static int
-broadcast_wake(void)
+static void broadcast_wake(void)
 {
-	int ret = PBOOK_SLEEP_OK;
 	struct list_head *list;
 	struct pmu_sleep_notifier *notifier;
 
@@ -1807,7 +1793,6 @@ broadcast_wake(void)
 		notifier = list_entry(list, struct pmu_sleep_notifier, list);
 		notifier->notifier_call(notifier, PBOOK_WAKE);
 	}
-	return ret;
 }
 
 /*
@@ -2014,12 +1999,8 @@ pmac_suspend_devices(void)
 
 	pm_prepare_console();
 	
-	/* Notify old-style device drivers & userland */
-	ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT);
-	if (ret != PBOOK_SLEEP_OK) {
-		printk(KERN_ERR "Sleep rejected by drivers\n");
-		return -EBUSY;
-	}
+	/* Notify old-style device drivers */
+	broadcast_sleep(PBOOK_SLEEP_REQUEST);
 
 	/* Sync the disks. */
 	/* XXX It would be nice to have some way to ensure that
@@ -2029,12 +2010,7 @@ pmac_suspend_devices(void)
 	 */
 	sys_sync();
 
-	/* Sleep can fail now. May not be very robust but useful for debugging */
-	ret = broadcast_sleep(PBOOK_SLEEP_NOW, PBOOK_WAKE);
-	if (ret != PBOOK_SLEEP_OK) {
-		printk(KERN_ERR "Driver sleep failed\n");
-		return -EBUSY;
-	}
+	broadcast_sleep(PBOOK_SLEEP_NOW);
 
 	/* Send suspend call to devices, hold the device core's dpm_sem */
 	ret = device_suspend(PMSG_SUSPEND);
--- linux-2.6-git.orig/include/linux/pmu.h	2007-02-07 02:54:56.728884289 +0100
+++ linux-2.6-git/include/linux/pmu.h	2007-02-07 02:55:35.968884289 +0100
@@ -168,24 +168,16 @@ extern int pmu_get_model(void);
 
 struct pmu_sleep_notifier
 {
-	int (*notifier_call)(struct pmu_sleep_notifier *self, int when);
+	void (*notifier_call)(struct pmu_sleep_notifier *self, int when);
 	int priority;
 	struct list_head list;
 };
 
 /* Code values for calling sleep/wakeup handlers
- *
- * Note: If a sleep request got cancelled, all drivers will get
- * the PBOOK_SLEEP_REJECT, even those who didn't get the PBOOK_SLEEP_REQUEST.
  */
 #define PBOOK_SLEEP_REQUEST	1
 #define PBOOK_SLEEP_NOW		2
-#define PBOOK_SLEEP_REJECT	3
-#define PBOOK_WAKE		4
-
-/* Result codes returned by the notifiers */
-#define PBOOK_SLEEP_OK		0
-#define PBOOK_SLEEP_REFUSE	-1
+#define PBOOK_WAKE		3
 
 /* priority levels in notifiers */
 #define SLEEP_LEVEL_VIDEO	100	/* Video driver (first wake) */
--- linux-2.6-git.orig/drivers/macintosh/via-pmu-led.c	2007-02-07 02:54:56.425884289 +0100
+++ linux-2.6-git/drivers/macintosh/via-pmu-led.c	2007-02-07 02:55:35.969884289 +0100
@@ -81,7 +81,7 @@ static struct led_classdev pmu_led = {
 };
 
 #ifdef CONFIG_PM
-static int pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when)
+static void pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when)
 {
 	unsigned long flags;
 
@@ -99,8 +99,6 @@ static int pmu_led_sleep_call(struct pmu
 		break;
 	}
 	spin_unlock_irqrestore(&pmu_blink_lock, flags);
-
-	return PBOOK_SLEEP_OK;
 }
 
 static struct pmu_sleep_notifier via_pmu_led_sleep_notif = {
--- linux-2.6-git.orig/drivers/macintosh/apm_emu.c	2007-02-07 02:54:56.542884289 +0100
+++ linux-2.6-git/drivers/macintosh/apm_emu.c	2007-02-07 02:55:35.972884289 +0100
@@ -96,7 +96,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitq
 static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
 static struct apm_user *	user_list;
 
-static int apm_notify_sleep(struct pmu_sleep_notifier *self, int when);
+static void apm_notify_sleep(struct pmu_sleep_notifier *self, int when);
 static struct pmu_sleep_notifier apm_sleep_notifier = {
 	apm_notify_sleep,
 	SLEEP_LEVEL_USERLAND,
@@ -352,7 +352,7 @@ static int do_open(struct inode * inode,
  * doesn't provide a way to NAK, but this could be added
  * here.
  */
-static int wait_all_suspend(void)
+static void wait_all_suspend(void)
 {
 	DECLARE_WAITQUEUE(wait, current);
 
@@ -366,24 +366,19 @@ static int wait_all_suspend(void)
 	remove_wait_queue(&apm_suspend_waitqueue, &wait);
 
 	DBG("apm_emu: wait_all_suspend() - complete !\n");
-	
-	return 1;
 }
 
-static int apm_notify_sleep(struct pmu_sleep_notifier *self, int when)
+static void apm_notify_sleep(struct pmu_sleep_notifier *self, int when)
 {
 	switch(when) {
 		case PBOOK_SLEEP_REQUEST:
 			queue_event(APM_SYS_SUSPEND, NULL);
-			if (!wait_all_suspend())
-				return PBOOK_SLEEP_REFUSE;
+			wait_all_suspend();
 			break;
-		case PBOOK_SLEEP_REJECT:
 		case PBOOK_WAKE:
 			queue_event(APM_NORMAL_RESUME, NULL);
 			break;
 	}
-	return PBOOK_SLEEP_OK;
 }
 
 #define APM_CRITICAL		10

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 11/12] powermac: disallow pmu sleep notifiers from aborting sleep
@ 2007-02-07 12:45   ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

Tracing through the code, no current PMU sleep notifier can abort sleep.
Since no new PMU sleep notifiers should be added, this patch simplifies the
code and removes the ability to abort sleep.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>

---
This is just something I did before I understood how to do the next patch
in this series. If you want, I can drop this one and rework the next, it's
very well possible to abort suspend from these callbacks even with the
next patch.

--- linux-2.6-git.orig/drivers/macintosh/adb.c	2007-02-07 02:54:56.301884289 +0100
+++ linux-2.6-git/drivers/macintosh/adb.c	2007-02-07 02:55:35.961884289 +0100
@@ -90,7 +90,7 @@ static int autopoll_devs;
 int __adb_probe_sync;
 
 #ifdef CONFIG_PM
-static int adb_notify_sleep(struct pmu_sleep_notifier *self, int when);
+static void adb_notify_sleep(struct pmu_sleep_notifier *self, int when);
 static struct pmu_sleep_notifier adb_sleep_notifier = {
 	adb_notify_sleep,
 	SLEEP_LEVEL_ADB,
@@ -340,11 +340,9 @@ __initcall(adb_init);
 /*
  * notify clients before sleep and reset bus afterwards
  */
-int
+void
 adb_notify_sleep(struct pmu_sleep_notifier *self, int when)
 {
-	int ret;
-	
 	switch (when) {
 	case PBOOK_SLEEP_REQUEST:
 		adb_got_sleep = 1;
@@ -353,22 +351,8 @@ adb_notify_sleep(struct pmu_sleep_notifi
 		/* Stop autopoll */
 		if (adb_controller->autopoll)
 			adb_controller->autopoll(0);
-		ret = blocking_notifier_call_chain(&adb_client_list,
-				ADB_MSG_POWERDOWN, NULL);
-		if (ret & NOTIFY_STOP_MASK) {
-			up(&adb_probe_mutex);
-			return PBOOK_SLEEP_REFUSE;
-		}
-		break;
-	case PBOOK_SLEEP_REJECT:
-		if (adb_got_sleep) {
-			adb_got_sleep = 0;
-			up(&adb_probe_mutex);
-			adb_reset_bus();
-		}
-		break;
-		
-	case PBOOK_SLEEP_NOW:
+		blocking_notifier_call_chain(&adb_client_list,
+			ADB_MSG_POWERDOWN, NULL);
 		break;
 	case PBOOK_WAKE:
 		adb_got_sleep = 0;
@@ -376,14 +360,13 @@ adb_notify_sleep(struct pmu_sleep_notifi
 		adb_reset_bus();
 		break;
 	}
-	return PBOOK_SLEEP_OK;
 }
 #endif /* CONFIG_PM */
 
 static int
 do_adb_reset_bus(void)
 {
-	int ret, nret;
+	int ret;
 	
 	if (adb_controller == NULL)
 		return -ENXIO;
@@ -391,13 +374,8 @@ do_adb_reset_bus(void)
 	if (adb_controller->autopoll)
 		adb_controller->autopoll(0);
 
-	nret = blocking_notifier_call_chain(&adb_client_list,
-			ADB_MSG_PRE_RESET, NULL);
-	if (nret & NOTIFY_STOP_MASK) {
-		if (adb_controller->autopoll)
-			adb_controller->autopoll(autopoll_devs);
-		return -EBUSY;
-	}
+	blocking_notifier_call_chain(&adb_client_list,
+		ADB_MSG_PRE_RESET, NULL);
 
 	if (sleepy_trackpad) {
 		/* Let the trackpad settle down */
@@ -427,10 +405,8 @@ do_adb_reset_bus(void)
 	}
 	up(&adb_handler_sem);
 
-	nret = blocking_notifier_call_chain(&adb_client_list,
-			ADB_MSG_POST_RESET, NULL);
-	if (nret & NOTIFY_STOP_MASK)
-		return -EBUSY;
+	blocking_notifier_call_chain(&adb_client_list,
+		ADB_MSG_POST_RESET, NULL);
 	
 	return ret;
 }
--- linux-2.6-git.orig/drivers/macintosh/via-pmu.c	2007-02-07 02:54:56.363884289 +0100
+++ linux-2.6-git/drivers/macintosh/via-pmu.c	2007-02-07 02:55:35.966884289 +0100
@@ -1770,35 +1770,21 @@ EXPORT_SYMBOL(pmu_unregister_sleep_notif
 #if defined(CONFIG_PM) && defined(CONFIG_PPC32)
 
 /* Sleep is broadcast last-to-first */
-static int
-broadcast_sleep(int when, int fallback)
+static void broadcast_sleep(int when)
 {
-	int ret = PBOOK_SLEEP_OK;
 	struct list_head *list;
 	struct pmu_sleep_notifier *notifier;
 
 	for (list = sleep_notifiers.prev; list != &sleep_notifiers;
 	     list = list->prev) {
 		notifier = list_entry(list, struct pmu_sleep_notifier, list);
-		ret = notifier->notifier_call(notifier, when);
-		if (ret != PBOOK_SLEEP_OK) {
-			printk(KERN_DEBUG "sleep %d rejected by %p (%p)\n",
-			       when, notifier, notifier->notifier_call);
-			for (; list != &sleep_notifiers; list = list->next) {
-				notifier = list_entry(list, struct pmu_sleep_notifier, list);
-				notifier->notifier_call(notifier, fallback);
-			}
-			return ret;
-		}
+		notifier->notifier_call(notifier, when);
 	}
-	return ret;
 }
 
 /* Wake is broadcast first-to-last */
-static int
-broadcast_wake(void)
+static void broadcast_wake(void)
 {
-	int ret = PBOOK_SLEEP_OK;
 	struct list_head *list;
 	struct pmu_sleep_notifier *notifier;
 
@@ -1807,7 +1793,6 @@ broadcast_wake(void)
 		notifier = list_entry(list, struct pmu_sleep_notifier, list);
 		notifier->notifier_call(notifier, PBOOK_WAKE);
 	}
-	return ret;
 }
 
 /*
@@ -2014,12 +1999,8 @@ pmac_suspend_devices(void)
 
 	pm_prepare_console();
 	
-	/* Notify old-style device drivers & userland */
-	ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT);
-	if (ret != PBOOK_SLEEP_OK) {
-		printk(KERN_ERR "Sleep rejected by drivers\n");
-		return -EBUSY;
-	}
+	/* Notify old-style device drivers */
+	broadcast_sleep(PBOOK_SLEEP_REQUEST);
 
 	/* Sync the disks. */
 	/* XXX It would be nice to have some way to ensure that
@@ -2029,12 +2010,7 @@ pmac_suspend_devices(void)
 	 */
 	sys_sync();
 
-	/* Sleep can fail now. May not be very robust but useful for debugging */
-	ret = broadcast_sleep(PBOOK_SLEEP_NOW, PBOOK_WAKE);
-	if (ret != PBOOK_SLEEP_OK) {
-		printk(KERN_ERR "Driver sleep failed\n");
-		return -EBUSY;
-	}
+	broadcast_sleep(PBOOK_SLEEP_NOW);
 
 	/* Send suspend call to devices, hold the device core's dpm_sem */
 	ret = device_suspend(PMSG_SUSPEND);
--- linux-2.6-git.orig/include/linux/pmu.h	2007-02-07 02:54:56.728884289 +0100
+++ linux-2.6-git/include/linux/pmu.h	2007-02-07 02:55:35.968884289 +0100
@@ -168,24 +168,16 @@ extern int pmu_get_model(void);
 
 struct pmu_sleep_notifier
 {
-	int (*notifier_call)(struct pmu_sleep_notifier *self, int when);
+	void (*notifier_call)(struct pmu_sleep_notifier *self, int when);
 	int priority;
 	struct list_head list;
 };
 
 /* Code values for calling sleep/wakeup handlers
- *
- * Note: If a sleep request got cancelled, all drivers will get
- * the PBOOK_SLEEP_REJECT, even those who didn't get the PBOOK_SLEEP_REQUEST.
  */
 #define PBOOK_SLEEP_REQUEST	1
 #define PBOOK_SLEEP_NOW		2
-#define PBOOK_SLEEP_REJECT	3
-#define PBOOK_WAKE		4
-
-/* Result codes returned by the notifiers */
-#define PBOOK_SLEEP_OK		0
-#define PBOOK_SLEEP_REFUSE	-1
+#define PBOOK_WAKE		3
 
 /* priority levels in notifiers */
 #define SLEEP_LEVEL_VIDEO	100	/* Video driver (first wake) */
--- linux-2.6-git.orig/drivers/macintosh/via-pmu-led.c	2007-02-07 02:54:56.425884289 +0100
+++ linux-2.6-git/drivers/macintosh/via-pmu-led.c	2007-02-07 02:55:35.969884289 +0100
@@ -81,7 +81,7 @@ static struct led_classdev pmu_led = {
 };
 
 #ifdef CONFIG_PM
-static int pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when)
+static void pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when)
 {
 	unsigned long flags;
 
@@ -99,8 +99,6 @@ static int pmu_led_sleep_call(struct pmu
 		break;
 	}
 	spin_unlock_irqrestore(&pmu_blink_lock, flags);
-
-	return PBOOK_SLEEP_OK;
 }
 
 static struct pmu_sleep_notifier via_pmu_led_sleep_notif = {
--- linux-2.6-git.orig/drivers/macintosh/apm_emu.c	2007-02-07 02:54:56.542884289 +0100
+++ linux-2.6-git/drivers/macintosh/apm_emu.c	2007-02-07 02:55:35.972884289 +0100
@@ -96,7 +96,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitq
 static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
 static struct apm_user *	user_list;
 
-static int apm_notify_sleep(struct pmu_sleep_notifier *self, int when);
+static void apm_notify_sleep(struct pmu_sleep_notifier *self, int when);
 static struct pmu_sleep_notifier apm_sleep_notifier = {
 	apm_notify_sleep,
 	SLEEP_LEVEL_USERLAND,
@@ -352,7 +352,7 @@ static int do_open(struct inode * inode,
  * doesn't provide a way to NAK, but this could be added
  * here.
  */
-static int wait_all_suspend(void)
+static void wait_all_suspend(void)
 {
 	DECLARE_WAITQUEUE(wait, current);
 
@@ -366,24 +366,19 @@ static int wait_all_suspend(void)
 	remove_wait_queue(&apm_suspend_waitqueue, &wait);
 
 	DBG("apm_emu: wait_all_suspend() - complete !\n");
-	
-	return 1;
 }
 
-static int apm_notify_sleep(struct pmu_sleep_notifier *self, int when)
+static void apm_notify_sleep(struct pmu_sleep_notifier *self, int when)
 {
 	switch(when) {
 		case PBOOK_SLEEP_REQUEST:
 			queue_event(APM_SYS_SUSPEND, NULL);
-			if (!wait_all_suspend())
-				return PBOOK_SLEEP_REFUSE;
+			wait_all_suspend();
 			break;
-		case PBOOK_SLEEP_REJECT:
 		case PBOOK_WAKE:
 			queue_event(APM_NORMAL_RESUME, NULL);
 			break;
 	}
-	return PBOOK_SLEEP_OK;
 }
 
 #define APM_CRITICAL		10

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 12/12] powermac: proper sleep management
  2007-02-07 12:45 [PATCH 00/12] powerpc/powermac power management patches Johannes Berg
@ 2007-02-07 12:45   ` Johannes Berg
  2007-02-07 12:45   ` Johannes Berg
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

[-- Attachment #1: pmu-pm_ops.patch --]
[-- Type: text/plain, Size: 12269 bytes --]

After having removed the power management ops from powermac completely, this
patch adds them back for PMU based machines, directly in the PMU driver.
This finally allows suspending via /sys/power/state on powerbooks.

The patch also replaces the PMU ioctl with a simple call to
pm_suspend(PM_SUSPEND_MEM) and puts the PMU ioctls onto the feature-removal
schedule.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>

---
Tested on my powerbook and it works! Needs some more testing on older
powerbooks I suppose, just to see if they get problems with the slight
reordering of the suspend/resume sequence.

And before someone asks:
Yes, it is safe to remove the backlight ioctl restrictions
because the generic layer actually freezes processes before STR.

diffstat:
 Documentation/feature-removal-schedule.txt |    8 
 drivers/macintosh/via-pmu.c                |  306 +++++++++++------------------
 2 files changed, 134 insertions(+), 180 deletions(-)

--- linux-2.6-git.orig/drivers/macintosh/via-pmu.c	2007-02-07 02:55:35.966884289 +0100
+++ linux-2.6-git/drivers/macintosh/via-pmu.c	2007-02-07 02:55:36.757884289 +0100
@@ -155,9 +155,6 @@ static int drop_interrupts;
 #if defined(CONFIG_PM) && defined(CONFIG_PPC32)
 static int option_lid_wakeup = 1;
 #endif /* CONFIG_PM && CONFIG_PPC32 */
-#if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT_LEGACY)
-static int sleep_in_progress;
-#endif
 static unsigned long async_req_locks;
 static unsigned int pmu_irq_stats[11];
 
@@ -1992,132 +1989,6 @@ restore_via_state(void)
 
 extern void pmu_backlight_set_sleep(int sleep);
 
-static int
-pmac_suspend_devices(void)
-{
-	int ret;
-
-	pm_prepare_console();
-	
-	/* Notify old-style device drivers */
-	broadcast_sleep(PBOOK_SLEEP_REQUEST);
-
-	/* Sync the disks. */
-	/* XXX It would be nice to have some way to ensure that
-	 * nobody is dirtying any new buffers while we wait. That
-	 * could be achieved using the refrigerator for processes
-	 * that swsusp uses
-	 */
-	sys_sync();
-
-	broadcast_sleep(PBOOK_SLEEP_NOW);
-
-	/* Send suspend call to devices, hold the device core's dpm_sem */
-	ret = device_suspend(PMSG_SUSPEND);
-	if (ret) {
-		broadcast_wake();
-		printk(KERN_ERR "Driver sleep failed\n");
-		return -EBUSY;
-	}
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	/* Tell backlight code not to muck around with the chip anymore */
-	pmu_backlight_set_sleep(1);
-#endif
-
-	/* Call platform functions marked "on sleep" */
-	pmac_pfunc_i2c_suspend();
-	pmac_pfunc_base_suspend();
-
-	/* Stop preemption */
-	preempt_disable();
-
-	/* Make sure the decrementer won't interrupt us */
-	asm volatile("mtdec %0" : : "r" (0x7fffffff));
-	/* Make sure any pending DEC interrupt occurring while we did
-	 * the above didn't re-enable the DEC */
-	mb();
-	asm volatile("mtdec %0" : : "r" (0x7fffffff));
-
-	/* We can now disable MSR_EE. This code of course works properly only
-	 * on UP machines... For SMP, if we ever implement sleep, we'll have to
-	 * stop the "other" CPUs way before we do all that stuff.
-	 */
-	local_irq_disable();
-
-	/* Broadcast power down irq
-	 * This isn't that useful in most cases (only directly wired devices can
-	 * use this but still... This will take care of sysdev's as well, so
-	 * we exit from here with local irqs disabled and PIC off.
-	 */
-	ret = device_power_down(PMSG_SUSPEND);
-	if (ret) {
-		wakeup_decrementer();
-		local_irq_enable();
-		preempt_enable();
-		device_resume();
-		broadcast_wake();
-		printk(KERN_ERR "Driver powerdown failed\n");
-		return -EBUSY;
-	}
-
-	/* Wait for completion of async requests */
-	while (!batt_req.complete)
-		pmu_poll();
-
-	/* Giveup the lazy FPU & vec so we don't have to back them
-	 * up from the low level code
-	 */
-	enable_kernel_fp();
-
-#ifdef CONFIG_ALTIVEC
-	if (cpu_has_feature(CPU_FTR_ALTIVEC))
-		enable_kernel_altivec();
-#endif /* CONFIG_ALTIVEC */
-
-	return 0;
-}
-
-static int
-pmac_wakeup_devices(void)
-{
-	mdelay(100);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	/* Tell backlight code it can use the chip again */
-	pmu_backlight_set_sleep(0);
-#endif
-
-	/* Power back up system devices (including the PIC) */
-	device_power_up();
-
-	/* Force a poll of ADB interrupts */
-	adb_int_pending = 1;
-	via_pmu_interrupt(0, NULL);
-
-	/* Restart jiffies & scheduling */
-	wakeup_decrementer();
-
-	/* Re-enable local CPU interrupts */
-	local_irq_enable();
-	mdelay(10);
-	preempt_enable();
-
-	/* Call platform functions marked "on wake" */
-	pmac_pfunc_base_resume();
-	pmac_pfunc_i2c_resume();
-
-	/* Resume devices */
-	device_resume();
-
-	/* Notify old style drivers */
-	broadcast_wake();
-
-	pm_restore_console();
-
-	return 0;
-}
-
 #define	GRACKLE_PM	(1<<7)
 #define GRACKLE_DOZE	(1<<5)
 #define	GRACKLE_NAP	(1<<4)
@@ -2128,19 +1999,12 @@ static int powerbook_sleep_grackle(void)
 	unsigned long save_l2cr;
 	unsigned short pmcr1;
 	struct adb_request req;
-	int ret;
 	struct pci_dev *grackle;
 
 	grackle = pci_find_slot(0, 0);
 	if (!grackle)
 		return -ENODEV;
 
-	ret = pmac_suspend_devices();
-	if (ret) {
-		printk(KERN_ERR "Sleep rejected by devices\n");
-		return ret;
-	}
-	
 	/* Turn off various things. Darwin does some retry tests here... */
 	pmu_request(&req, NULL, 2, PMU_POWER_CTRL0, PMU_POW0_OFF|PMU_POW0_HARD_DRIVE);
 	pmu_wait_complete(&req);
@@ -2201,8 +2065,6 @@ static int powerbook_sleep_grackle(void)
 			PMU_POW_ON|PMU_POW_BACKLIGHT|PMU_POW_CHARGER|PMU_POW_IRLED|PMU_POW_MEDIABAY);
 	pmu_wait_complete(&req);
 
-	pmac_wakeup_devices();
-
 	return 0;
 }
 
@@ -2212,7 +2074,6 @@ powerbook_sleep_Core99(void)
 	unsigned long save_l2cr;
 	unsigned long save_l3cr;
 	struct adb_request req;
-	int ret;
 	
 	if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) {
 		printk(KERN_ERR "Sleep mode not supported on this machine\n");
@@ -2222,12 +2083,6 @@ powerbook_sleep_Core99(void)
 	if (num_online_cpus() > 1 || cpu_is_offline(0))
 		return -EAGAIN;
 
-	ret = pmac_suspend_devices();
-	if (ret) {
-		printk(KERN_ERR "Sleep rejected by devices\n");
-		return ret;
-	}
-
 	/* Stop environment and ADB interrupts */
 	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0);
 	pmu_wait_complete(&req);
@@ -2298,8 +2153,6 @@ powerbook_sleep_Core99(void)
 	/* Restore LPJ, cpufreq will adjust the cpu frequency */
 	loops_per_jiffy /= 2;
 
-	pmac_wakeup_devices();
-
 	return 0;
 }
 
@@ -2309,7 +2162,7 @@ powerbook_sleep_Core99(void)
 static int
 powerbook_sleep_3400(void)
 {
-	int ret, i, x;
+	int i, x;
 	unsigned int hid0;
 	unsigned long p;
 	struct adb_request sleep_req;
@@ -2327,13 +2180,6 @@ powerbook_sleep_3400(void)
 	/* Allocate room for PCI save */
 	pbook_alloc_pci_save();
 
-	ret = pmac_suspend_devices();
-	if (ret) {
-		pbook_free_pci_save();
-		printk(KERN_ERR "Sleep rejected by devices\n");
-		return ret;
-	}
-
 	/* Save the state of PCI config space for some slots */
 	pbook_pci_save();
 
@@ -2377,7 +2223,6 @@ powerbook_sleep_3400(void)
 	while (asleep)
 		mb();
 
-	pmac_wakeup_devices();
 	pbook_free_pci_save();
 	iounmap(mem_ctrl);
 
@@ -2559,6 +2404,126 @@ pmu_release(struct inode *inode, struct 
 	return 0;
 }
 
+#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
+static int powerbook_prepare_sleep(suspend_state_t state)
+{
+	/* Notify old-style device drivers */
+	broadcast_sleep(PBOOK_SLEEP_REQUEST);
+
+	sys_sync();
+
+	broadcast_sleep(PBOOK_SLEEP_NOW);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	/* Tell backlight code not to muck around with the chip anymore */
+	pmu_backlight_set_sleep(1);
+#endif
+
+	/* Call platform functions marked "on sleep" */
+	pmac_pfunc_i2c_suspend();
+	pmac_pfunc_base_suspend();
+
+	preempt_disable();
+
+	return 0;
+}
+
+static int powerbook_sleep(suspend_state_t state)
+{
+	int error = 0;
+
+	asm volatile("mtdec %0" : : "r" (0x7fffffff));
+	/* Make sure any pending DEC interrupt occurring while we did
+	 * the above didn't re-enable the DEC */
+	mb();
+	asm volatile("mtdec %0" : : "r" (0x7fffffff));
+
+	/* Wait for completion of async requests */
+	while (!batt_req.complete)
+		pmu_poll();
+
+	/* Giveup the lazy FPU & vec so we don't have to back them
+	 * up from the low level code
+	 */
+	enable_kernel_fp();
+
+#ifdef CONFIG_ALTIVEC
+	if (cpu_has_feature(CPU_FTR_ALTIVEC))
+		enable_kernel_altivec();
+#endif /* CONFIG_ALTIVEC */
+
+	switch (pmu_kind) {
+	case PMU_OHARE_BASED:
+		error = powerbook_sleep_3400();
+		break;
+	case PMU_HEATHROW_BASED:
+	case PMU_PADDINGTON_BASED:
+		error = powerbook_sleep_grackle();
+		break;
+	case PMU_KEYLARGO_BASED:
+		error = powerbook_sleep_Core99();
+		break;
+	default:
+		return -ENOSYS;
+	}
+
+	if (error)
+		return error;
+
+	mdelay(100);
+
+	/* Force a poll of ADB interrupts */
+	adb_int_pending = 1;
+	via_pmu_interrupt(0, NULL);
+
+	/* Restart jiffies & scheduling */
+	wakeup_decrementer();
+
+	return 0;
+}
+
+static int powerbook_finish_sleep(suspend_state_t state)
+{
+#ifdef CONFIG_PMAC_BACKLIGHT
+	/* Tell backlight code it can use the chip again */
+	pmu_backlight_set_sleep(0);
+#endif
+
+	preempt_enable();
+
+	/* Call platform functions marked "on wake" */
+	pmac_pfunc_base_resume();
+	pmac_pfunc_i2c_resume();
+
+	/* Notify old style drivers */
+	broadcast_wake();
+
+	return 0;
+}
+
+static int pmu_sleep_valid(suspend_state_t state)
+{
+	return state == PM_SUSPEND_MEM;
+}
+
+static struct pm_ops pmu_pm_ops = {
+	.pm_disk_mode = PM_DISK_PLATFORM,
+	.prepare = powerbook_prepare_sleep,
+	.finish = powerbook_finish_sleep,
+	.enter = powerbook_sleep,
+	.valid = pmu_sleep_valid,
+};
+
+static int register_pmu_pm_ops(void)
+{
+	pm_set_ops(&pmu_pm_ops);
+
+	return 0;
+}
+
+device_initcall(register_pmu_pm_ops);
+#endif
+
 static int
 pmu_ioctl(struct inode * inode, struct file *filp,
 		     u_int cmd, u_long arg)
@@ -2568,27 +2533,14 @@ pmu_ioctl(struct inode * inode, struct f
 
 	switch (cmd) {
 #if defined(CONFIG_PM) && defined(CONFIG_PPC32)
+	/* just provided for compatibility */
 	case PMU_IOC_SLEEP:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EACCES;
-		if (sleep_in_progress)
-			return -EBUSY;
-		sleep_in_progress = 1;
-		switch (pmu_kind) {
-		case PMU_OHARE_BASED:
-			error = powerbook_sleep_3400();
-			break;
-		case PMU_HEATHROW_BASED:
-		case PMU_PADDINGTON_BASED:
-			error = powerbook_sleep_grackle();
-			break;
-		case PMU_KEYLARGO_BASED:
-			error = powerbook_sleep_Core99();
-			break;
-		default:
-			error = -ENOSYS;
-		}
-		sleep_in_progress = 0;
+		printk(KERN_INFO "via-pmu: suspending via ioctl is deprecated.\n");
+		printk(KERN_INFO "via-pmu: use \"echo mem > /sys/power/state\" instead!\n");
+		printk(KERN_INFO "via-pmu: this ioctl will be removed soon.\n");
+		error = pm_suspend(PM_SUSPEND_MEM);
 		break;
 	case PMU_IOC_CAN_SLEEP:
 		if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0)
@@ -2603,9 +2555,6 @@ pmu_ioctl(struct inode * inode, struct f
 	{
 		int brightness;
 
-		if (sleep_in_progress)
-			return -EBUSY;
-
 		brightness = pmac_backlight_get_legacy_brightness();
 		if (brightness < 0)
 			return brightness;
@@ -2617,9 +2566,6 @@ pmu_ioctl(struct inode * inode, struct f
 	{
 		int brightness;
 
-		if (sleep_in_progress)
-			return -EBUSY;
-
 		error = get_user(brightness, argp);
 		if (error)
 			return error;
--- linux-2.6-git.orig/Documentation/feature-removal-schedule.txt	2007-02-07 02:54:55.727884289 +0100
+++ linux-2.6-git/Documentation/feature-removal-schedule.txt	2007-02-07 02:55:36.759884289 +0100
@@ -325,3 +325,11 @@ Why:	Unmaintained for years, superceded 
 Who:	Jeff Garzik <jeff@garzik.org>
 
 ---------------------------
+
+What:	via-pmu suspend ioctls (PMU_IOC_SLEEP, PMU_IOC_CAN_SLEEP)
+When:	February 2008
+Why:	The regular platform-independent interface in /sys/power/state
+	should be used instead.
+Who:	Johannes Berg <johannes@sipsolutions.net>
+
+---------------------------

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 12/12] powermac: proper sleep management
@ 2007-02-07 12:45   ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-07 12:45 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

After having removed the power management ops from powermac completely, this
patch adds them back for PMU based machines, directly in the PMU driver.
This finally allows suspending via /sys/power/state on powerbooks.

The patch also replaces the PMU ioctl with a simple call to
pm_suspend(PM_SUSPEND_MEM) and puts the PMU ioctls onto the feature-removal
schedule.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>

---
Tested on my powerbook and it works! Needs some more testing on older
powerbooks I suppose, just to see if they get problems with the slight
reordering of the suspend/resume sequence.

And before someone asks:
Yes, it is safe to remove the backlight ioctl restrictions
because the generic layer actually freezes processes before STR.

diffstat:
 Documentation/feature-removal-schedule.txt |    8 
 drivers/macintosh/via-pmu.c                |  306 +++++++++++------------------
 2 files changed, 134 insertions(+), 180 deletions(-)

--- linux-2.6-git.orig/drivers/macintosh/via-pmu.c	2007-02-07 02:55:35.966884289 +0100
+++ linux-2.6-git/drivers/macintosh/via-pmu.c	2007-02-07 02:55:36.757884289 +0100
@@ -155,9 +155,6 @@ static int drop_interrupts;
 #if defined(CONFIG_PM) && defined(CONFIG_PPC32)
 static int option_lid_wakeup = 1;
 #endif /* CONFIG_PM && CONFIG_PPC32 */
-#if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT_LEGACY)
-static int sleep_in_progress;
-#endif
 static unsigned long async_req_locks;
 static unsigned int pmu_irq_stats[11];
 
@@ -1992,132 +1989,6 @@ restore_via_state(void)
 
 extern void pmu_backlight_set_sleep(int sleep);
 
-static int
-pmac_suspend_devices(void)
-{
-	int ret;
-
-	pm_prepare_console();
-	
-	/* Notify old-style device drivers */
-	broadcast_sleep(PBOOK_SLEEP_REQUEST);
-
-	/* Sync the disks. */
-	/* XXX It would be nice to have some way to ensure that
-	 * nobody is dirtying any new buffers while we wait. That
-	 * could be achieved using the refrigerator for processes
-	 * that swsusp uses
-	 */
-	sys_sync();
-
-	broadcast_sleep(PBOOK_SLEEP_NOW);
-
-	/* Send suspend call to devices, hold the device core's dpm_sem */
-	ret = device_suspend(PMSG_SUSPEND);
-	if (ret) {
-		broadcast_wake();
-		printk(KERN_ERR "Driver sleep failed\n");
-		return -EBUSY;
-	}
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	/* Tell backlight code not to muck around with the chip anymore */
-	pmu_backlight_set_sleep(1);
-#endif
-
-	/* Call platform functions marked "on sleep" */
-	pmac_pfunc_i2c_suspend();
-	pmac_pfunc_base_suspend();
-
-	/* Stop preemption */
-	preempt_disable();
-
-	/* Make sure the decrementer won't interrupt us */
-	asm volatile("mtdec %0" : : "r" (0x7fffffff));
-	/* Make sure any pending DEC interrupt occurring while we did
-	 * the above didn't re-enable the DEC */
-	mb();
-	asm volatile("mtdec %0" : : "r" (0x7fffffff));
-
-	/* We can now disable MSR_EE. This code of course works properly only
-	 * on UP machines... For SMP, if we ever implement sleep, we'll have to
-	 * stop the "other" CPUs way before we do all that stuff.
-	 */
-	local_irq_disable();
-
-	/* Broadcast power down irq
-	 * This isn't that useful in most cases (only directly wired devices can
-	 * use this but still... This will take care of sysdev's as well, so
-	 * we exit from here with local irqs disabled and PIC off.
-	 */
-	ret = device_power_down(PMSG_SUSPEND);
-	if (ret) {
-		wakeup_decrementer();
-		local_irq_enable();
-		preempt_enable();
-		device_resume();
-		broadcast_wake();
-		printk(KERN_ERR "Driver powerdown failed\n");
-		return -EBUSY;
-	}
-
-	/* Wait for completion of async requests */
-	while (!batt_req.complete)
-		pmu_poll();
-
-	/* Giveup the lazy FPU & vec so we don't have to back them
-	 * up from the low level code
-	 */
-	enable_kernel_fp();
-
-#ifdef CONFIG_ALTIVEC
-	if (cpu_has_feature(CPU_FTR_ALTIVEC))
-		enable_kernel_altivec();
-#endif /* CONFIG_ALTIVEC */
-
-	return 0;
-}
-
-static int
-pmac_wakeup_devices(void)
-{
-	mdelay(100);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	/* Tell backlight code it can use the chip again */
-	pmu_backlight_set_sleep(0);
-#endif
-
-	/* Power back up system devices (including the PIC) */
-	device_power_up();
-
-	/* Force a poll of ADB interrupts */
-	adb_int_pending = 1;
-	via_pmu_interrupt(0, NULL);
-
-	/* Restart jiffies & scheduling */
-	wakeup_decrementer();
-
-	/* Re-enable local CPU interrupts */
-	local_irq_enable();
-	mdelay(10);
-	preempt_enable();
-
-	/* Call platform functions marked "on wake" */
-	pmac_pfunc_base_resume();
-	pmac_pfunc_i2c_resume();
-
-	/* Resume devices */
-	device_resume();
-
-	/* Notify old style drivers */
-	broadcast_wake();
-
-	pm_restore_console();
-
-	return 0;
-}
-
 #define	GRACKLE_PM	(1<<7)
 #define GRACKLE_DOZE	(1<<5)
 #define	GRACKLE_NAP	(1<<4)
@@ -2128,19 +1999,12 @@ static int powerbook_sleep_grackle(void)
 	unsigned long save_l2cr;
 	unsigned short pmcr1;
 	struct adb_request req;
-	int ret;
 	struct pci_dev *grackle;
 
 	grackle = pci_find_slot(0, 0);
 	if (!grackle)
 		return -ENODEV;
 
-	ret = pmac_suspend_devices();
-	if (ret) {
-		printk(KERN_ERR "Sleep rejected by devices\n");
-		return ret;
-	}
-	
 	/* Turn off various things. Darwin does some retry tests here... */
 	pmu_request(&req, NULL, 2, PMU_POWER_CTRL0, PMU_POW0_OFF|PMU_POW0_HARD_DRIVE);
 	pmu_wait_complete(&req);
@@ -2201,8 +2065,6 @@ static int powerbook_sleep_grackle(void)
 			PMU_POW_ON|PMU_POW_BACKLIGHT|PMU_POW_CHARGER|PMU_POW_IRLED|PMU_POW_MEDIABAY);
 	pmu_wait_complete(&req);
 
-	pmac_wakeup_devices();
-
 	return 0;
 }
 
@@ -2212,7 +2074,6 @@ powerbook_sleep_Core99(void)
 	unsigned long save_l2cr;
 	unsigned long save_l3cr;
 	struct adb_request req;
-	int ret;
 	
 	if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) {
 		printk(KERN_ERR "Sleep mode not supported on this machine\n");
@@ -2222,12 +2083,6 @@ powerbook_sleep_Core99(void)
 	if (num_online_cpus() > 1 || cpu_is_offline(0))
 		return -EAGAIN;
 
-	ret = pmac_suspend_devices();
-	if (ret) {
-		printk(KERN_ERR "Sleep rejected by devices\n");
-		return ret;
-	}
-
 	/* Stop environment and ADB interrupts */
 	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0);
 	pmu_wait_complete(&req);
@@ -2298,8 +2153,6 @@ powerbook_sleep_Core99(void)
 	/* Restore LPJ, cpufreq will adjust the cpu frequency */
 	loops_per_jiffy /= 2;
 
-	pmac_wakeup_devices();
-
 	return 0;
 }
 
@@ -2309,7 +2162,7 @@ powerbook_sleep_Core99(void)
 static int
 powerbook_sleep_3400(void)
 {
-	int ret, i, x;
+	int i, x;
 	unsigned int hid0;
 	unsigned long p;
 	struct adb_request sleep_req;
@@ -2327,13 +2180,6 @@ powerbook_sleep_3400(void)
 	/* Allocate room for PCI save */
 	pbook_alloc_pci_save();
 
-	ret = pmac_suspend_devices();
-	if (ret) {
-		pbook_free_pci_save();
-		printk(KERN_ERR "Sleep rejected by devices\n");
-		return ret;
-	}
-
 	/* Save the state of PCI config space for some slots */
 	pbook_pci_save();
 
@@ -2377,7 +2223,6 @@ powerbook_sleep_3400(void)
 	while (asleep)
 		mb();
 
-	pmac_wakeup_devices();
 	pbook_free_pci_save();
 	iounmap(mem_ctrl);
 
@@ -2559,6 +2404,126 @@ pmu_release(struct inode *inode, struct 
 	return 0;
 }
 
+#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
+static int powerbook_prepare_sleep(suspend_state_t state)
+{
+	/* Notify old-style device drivers */
+	broadcast_sleep(PBOOK_SLEEP_REQUEST);
+
+	sys_sync();
+
+	broadcast_sleep(PBOOK_SLEEP_NOW);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	/* Tell backlight code not to muck around with the chip anymore */
+	pmu_backlight_set_sleep(1);
+#endif
+
+	/* Call platform functions marked "on sleep" */
+	pmac_pfunc_i2c_suspend();
+	pmac_pfunc_base_suspend();
+
+	preempt_disable();
+
+	return 0;
+}
+
+static int powerbook_sleep(suspend_state_t state)
+{
+	int error = 0;
+
+	asm volatile("mtdec %0" : : "r" (0x7fffffff));
+	/* Make sure any pending DEC interrupt occurring while we did
+	 * the above didn't re-enable the DEC */
+	mb();
+	asm volatile("mtdec %0" : : "r" (0x7fffffff));
+
+	/* Wait for completion of async requests */
+	while (!batt_req.complete)
+		pmu_poll();
+
+	/* Giveup the lazy FPU & vec so we don't have to back them
+	 * up from the low level code
+	 */
+	enable_kernel_fp();
+
+#ifdef CONFIG_ALTIVEC
+	if (cpu_has_feature(CPU_FTR_ALTIVEC))
+		enable_kernel_altivec();
+#endif /* CONFIG_ALTIVEC */
+
+	switch (pmu_kind) {
+	case PMU_OHARE_BASED:
+		error = powerbook_sleep_3400();
+		break;
+	case PMU_HEATHROW_BASED:
+	case PMU_PADDINGTON_BASED:
+		error = powerbook_sleep_grackle();
+		break;
+	case PMU_KEYLARGO_BASED:
+		error = powerbook_sleep_Core99();
+		break;
+	default:
+		return -ENOSYS;
+	}
+
+	if (error)
+		return error;
+
+	mdelay(100);
+
+	/* Force a poll of ADB interrupts */
+	adb_int_pending = 1;
+	via_pmu_interrupt(0, NULL);
+
+	/* Restart jiffies & scheduling */
+	wakeup_decrementer();
+
+	return 0;
+}
+
+static int powerbook_finish_sleep(suspend_state_t state)
+{
+#ifdef CONFIG_PMAC_BACKLIGHT
+	/* Tell backlight code it can use the chip again */
+	pmu_backlight_set_sleep(0);
+#endif
+
+	preempt_enable();
+
+	/* Call platform functions marked "on wake" */
+	pmac_pfunc_base_resume();
+	pmac_pfunc_i2c_resume();
+
+	/* Notify old style drivers */
+	broadcast_wake();
+
+	return 0;
+}
+
+static int pmu_sleep_valid(suspend_state_t state)
+{
+	return state == PM_SUSPEND_MEM;
+}
+
+static struct pm_ops pmu_pm_ops = {
+	.pm_disk_mode = PM_DISK_PLATFORM,
+	.prepare = powerbook_prepare_sleep,
+	.finish = powerbook_finish_sleep,
+	.enter = powerbook_sleep,
+	.valid = pmu_sleep_valid,
+};
+
+static int register_pmu_pm_ops(void)
+{
+	pm_set_ops(&pmu_pm_ops);
+
+	return 0;
+}
+
+device_initcall(register_pmu_pm_ops);
+#endif
+
 static int
 pmu_ioctl(struct inode * inode, struct file *filp,
 		     u_int cmd, u_long arg)
@@ -2568,27 +2533,14 @@ pmu_ioctl(struct inode * inode, struct f
 
 	switch (cmd) {
 #if defined(CONFIG_PM) && defined(CONFIG_PPC32)
+	/* just provided for compatibility */
 	case PMU_IOC_SLEEP:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EACCES;
-		if (sleep_in_progress)
-			return -EBUSY;
-		sleep_in_progress = 1;
-		switch (pmu_kind) {
-		case PMU_OHARE_BASED:
-			error = powerbook_sleep_3400();
-			break;
-		case PMU_HEATHROW_BASED:
-		case PMU_PADDINGTON_BASED:
-			error = powerbook_sleep_grackle();
-			break;
-		case PMU_KEYLARGO_BASED:
-			error = powerbook_sleep_Core99();
-			break;
-		default:
-			error = -ENOSYS;
-		}
-		sleep_in_progress = 0;
+		printk(KERN_INFO "via-pmu: suspending via ioctl is deprecated.\n");
+		printk(KERN_INFO "via-pmu: use \"echo mem > /sys/power/state\" instead!\n");
+		printk(KERN_INFO "via-pmu: this ioctl will be removed soon.\n");
+		error = pm_suspend(PM_SUSPEND_MEM);
 		break;
 	case PMU_IOC_CAN_SLEEP:
 		if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0)
@@ -2603,9 +2555,6 @@ pmu_ioctl(struct inode * inode, struct f
 	{
 		int brightness;
 
-		if (sleep_in_progress)
-			return -EBUSY;
-
 		brightness = pmac_backlight_get_legacy_brightness();
 		if (brightness < 0)
 			return brightness;
@@ -2617,9 +2566,6 @@ pmu_ioctl(struct inode * inode, struct f
 	{
 		int brightness;
 
-		if (sleep_in_progress)
-			return -EBUSY;
-
 		error = get_user(brightness, argp);
 		if (error)
 			return error;
--- linux-2.6-git.orig/Documentation/feature-removal-schedule.txt	2007-02-07 02:54:55.727884289 +0100
+++ linux-2.6-git/Documentation/feature-removal-schedule.txt	2007-02-07 02:55:36.759884289 +0100
@@ -325,3 +325,11 @@ Why:	Unmaintained for years, superceded 
 Who:	Jeff Garzik <jeff@garzik.org>
 
 ---------------------------
+
+What:	via-pmu suspend ioctls (PMU_IOC_SLEEP, PMU_IOC_CAN_SLEEP)
+When:	February 2008
+Why:	The regular platform-independent interface in /sys/power/state
+	should be used instead.
+Who:	Johannes Berg <johannes@sipsolutions.net>
+
+---------------------------

--

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 11/12] powermac: disallow pmu sleep notifiers from aborting sleep
  2007-02-07 12:45   ` Johannes Berg
  (?)
@ 2007-02-07 22:52   ` Andreas Schwab
  2007-02-08 13:08       ` Johannes Berg
  -1 siblings, 1 reply; 71+ messages in thread
From: Andreas Schwab @ 2007-02-07 22:52 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, linux-pm

Johannes Berg <johannes@sipsolutions.net> writes:

> Tracing through the code, no current PMU sleep notifier can abort sleep.
> Since no new PMU sleep notifiers should be added, this patch simplifies the
> code and removes the ability to abort sleep.

There is a use of PBOOK_SLEEP_OK left in
arch/powerpc/platforms/powermac/time.c.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 10/12] powerpc: remove unneeded exports in mem.c
  2007-02-07 12:45   ` Johannes Berg
  (?)
@ 2007-02-08  4:25   ` Paul Mackerras
  2007-02-08 13:10       ` Johannes Berg
  -1 siblings, 1 reply; 71+ messages in thread
From: Paul Mackerras @ 2007-02-08  4:25 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, linux-pm

Johannes Berg writes:

> arch/powerpc/mm/mem.c exports page_is_ram and phys_mem_access_prot which
> both are not used anywhere that could be modular.

phys_mem_access_prot is used in drivers/video/fbmem.c, and the fb
stuff can be a module.

Paul.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 11/12] powermac: disallow pmu sleep notifiers from aborting sleep
  2007-02-07 22:52   ` Andreas Schwab
@ 2007-02-08 13:08       ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-08 13:08 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: linuxppc-dev, linux-pm


[-- Attachment #1.1: Type: text/plain, Size: 547 bytes --]

On Wed, 2007-02-07 at 23:52 +0100, Andreas Schwab wrote:
> Johannes Berg <johannes@sipsolutions.net> writes:
> 
> > Tracing through the code, no current PMU sleep notifier can abort sleep.
> > Since no new PMU sleep notifiers should be added, this patch simplifies the
> > code and removes the ability to abort sleep.
> 
> There is a use of PBOOK_SLEEP_OK left in
> arch/powerpc/platforms/powermac/time.c.

Ouch. Yeah, the patch was done assuming my time resume patch is applied.

I found another one though, in dmasound.

johannes

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

[-- Attachment #2: Type: text/plain, Size: 146 bytes --]

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 11/12] powermac: disallow pmu sleep notifiers from aborting sleep
@ 2007-02-08 13:08       ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-08 13:08 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: linuxppc-dev, linux-pm

[-- Attachment #1: Type: text/plain, Size: 547 bytes --]

On Wed, 2007-02-07 at 23:52 +0100, Andreas Schwab wrote:
> Johannes Berg <johannes@sipsolutions.net> writes:
> 
> > Tracing through the code, no current PMU sleep notifier can abort sleep.
> > Since no new PMU sleep notifiers should be added, this patch simplifies the
> > code and removes the ability to abort sleep.
> 
> There is a use of PBOOK_SLEEP_OK left in
> arch/powerpc/platforms/powermac/time.c.

Ouch. Yeah, the patch was done assuming my time resume patch is applied.

I found another one though, in dmasound.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 10/12] powerpc: remove unneeded exports in mem.c
  2007-02-08  4:25   ` Paul Mackerras
@ 2007-02-08 13:10       ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-08 13:10 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, linux-pm


[-- Attachment #1.1: Type: text/plain, Size: 498 bytes --]

On Thu, 2007-02-08 at 15:25 +1100, Paul Mackerras wrote:
> Johannes Berg writes:
> 
> > arch/powerpc/mm/mem.c exports page_is_ram and phys_mem_access_prot which
> > both are not used anywhere that could be modular.
> 
> phys_mem_access_prot is used in drivers/video/fbmem.c, and the fb
> stuff can be a module.

Ouch, sorry, the Makefile there with fb-y confused me. Seems all these
patches have one problem or another :(

I'll repost just the removal of page_is_ram then.

johannes

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

[-- Attachment #2: Type: text/plain, Size: 146 bytes --]

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 10/12] powerpc: remove unneeded exports in mem.c
@ 2007-02-08 13:10       ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-08 13:10 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, linux-pm

[-- Attachment #1: Type: text/plain, Size: 498 bytes --]

On Thu, 2007-02-08 at 15:25 +1100, Paul Mackerras wrote:
> Johannes Berg writes:
> 
> > arch/powerpc/mm/mem.c exports page_is_ram and phys_mem_access_prot which
> > both are not used anywhere that could be modular.
> 
> phys_mem_access_prot is used in drivers/video/fbmem.c, and the fb
> stuff can be a module.

Ouch, sorry, the Makefile there with fb-y confused me. Seems all these
patches have one problem or another :(

I'll repost just the removal of page_is_ram then.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
  2007-02-07 12:45   ` Johannes Berg
@ 2007-02-08 13:14     ` Johannes Berg
  -1 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-08 13:14 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm


[-- Attachment #1.1: Type: text/plain, Size: 964 bytes --]

On Wed, 2007-02-07 at 13:45 +0100, Johannes Berg wrote:

> Except for the in-irq count hack I'm happy with this. I still haven't found
> where the in-hard-irq count is set to 1 in the down path during suspend or
> resume and other platforms do similar things so I'm inclined to leave this.

Um, ok, so the hack breaks platforms that don't have paca, e.g. chrp32.

Also, I finally figured out how the in-hard-irq count happens. The thing
is that when I try to turn off the CPU it actually doesn't really turn
off of course, so it ends up doing NAP and taking timer interrupts...
which goes irq_enter() and we happen to kill it afterwards.

I have two ways of fixing this:
 - just ignore it as we do now
 - insert a "if (cpu_dead) return" into the timer interrupt function

I prefer the latter because then we're guaranteed that whatever the
timer interrupt does we don't modify any state for/by the CPU that isn't
supposed to exist.

johannes

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
@ 2007-02-08 13:14     ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-08 13:14 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

[-- Attachment #1: Type: text/plain, Size: 964 bytes --]

On Wed, 2007-02-07 at 13:45 +0100, Johannes Berg wrote:

> Except for the in-irq count hack I'm happy with this. I still haven't found
> where the in-hard-irq count is set to 1 in the down path during suspend or
> resume and other platforms do similar things so I'm inclined to leave this.

Um, ok, so the hack breaks platforms that don't have paca, e.g. chrp32.

Also, I finally figured out how the in-hard-irq count happens. The thing
is that when I try to turn off the CPU it actually doesn't really turn
off of course, so it ends up doing NAP and taking timer interrupts...
which goes irq_enter() and we happen to kill it afterwards.

I have two ways of fixing this:
 - just ignore it as we do now
 - insert a "if (cpu_dead) return" into the timer interrupt function

I prefer the latter because then we're guaranteed that whatever the
timer interrupt does we don't modify any state for/by the CPU that isn't
supposed to exist.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 11/12] powermac: disallow pmu sleep notifiers from aborting sleep
  2007-02-07 12:45   ` Johannes Berg
@ 2007-02-08 13:16     ` Johannes Berg
  -1 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-08 13:16 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

Tracing through the code, no current PMU sleep notifier can abort sleep.
Since no new PMU sleep notifiers should be added, this patch simplifies the
code and removes the ability to abort sleep.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>

---
This is just something I did before I understood how to do the next patch
in this series. If you want, I can drop this one and rework the next, it's
very well possible to abort suspend from these callbacks even with the
next patch.

Previous version missed dmasound. I'd completely forgotten that still
exists. Maybe we should just remove it?

As Andreas pointed out, it doesn't change the one in
arch/powerpc/kernel/time.c, but that has been removed by the previous
time suspend patch so this patch depends on that.

--- linux-2.6-git.orig/drivers/macintosh/adb.c	2007-02-07 22:33:32.676922690 +0100
+++ linux-2.6-git/drivers/macintosh/adb.c	2007-02-07 22:34:39.678922690 +0100
@@ -90,7 +90,7 @@ static int autopoll_devs;
 int __adb_probe_sync;
 
 #ifdef CONFIG_PM
-static int adb_notify_sleep(struct pmu_sleep_notifier *self, int when);
+static void adb_notify_sleep(struct pmu_sleep_notifier *self, int when);
 static struct pmu_sleep_notifier adb_sleep_notifier = {
 	adb_notify_sleep,
 	SLEEP_LEVEL_ADB,
@@ -340,11 +340,9 @@ __initcall(adb_init);
 /*
  * notify clients before sleep and reset bus afterwards
  */
-int
+void
 adb_notify_sleep(struct pmu_sleep_notifier *self, int when)
 {
-	int ret;
-	
 	switch (when) {
 	case PBOOK_SLEEP_REQUEST:
 		adb_got_sleep = 1;
@@ -353,22 +351,8 @@ adb_notify_sleep(struct pmu_sleep_notifi
 		/* Stop autopoll */
 		if (adb_controller->autopoll)
 			adb_controller->autopoll(0);
-		ret = blocking_notifier_call_chain(&adb_client_list,
-				ADB_MSG_POWERDOWN, NULL);
-		if (ret & NOTIFY_STOP_MASK) {
-			up(&adb_probe_mutex);
-			return PBOOK_SLEEP_REFUSE;
-		}
-		break;
-	case PBOOK_SLEEP_REJECT:
-		if (adb_got_sleep) {
-			adb_got_sleep = 0;
-			up(&adb_probe_mutex);
-			adb_reset_bus();
-		}
-		break;
-		
-	case PBOOK_SLEEP_NOW:
+		blocking_notifier_call_chain(&adb_client_list,
+			ADB_MSG_POWERDOWN, NULL);
 		break;
 	case PBOOK_WAKE:
 		adb_got_sleep = 0;
@@ -376,14 +360,13 @@ adb_notify_sleep(struct pmu_sleep_notifi
 		adb_reset_bus();
 		break;
 	}
-	return PBOOK_SLEEP_OK;
 }
 #endif /* CONFIG_PM */
 
 static int
 do_adb_reset_bus(void)
 {
-	int ret, nret;
+	int ret;
 	
 	if (adb_controller == NULL)
 		return -ENXIO;
@@ -391,13 +374,8 @@ do_adb_reset_bus(void)
 	if (adb_controller->autopoll)
 		adb_controller->autopoll(0);
 
-	nret = blocking_notifier_call_chain(&adb_client_list,
-			ADB_MSG_PRE_RESET, NULL);
-	if (nret & NOTIFY_STOP_MASK) {
-		if (adb_controller->autopoll)
-			adb_controller->autopoll(autopoll_devs);
-		return -EBUSY;
-	}
+	blocking_notifier_call_chain(&adb_client_list,
+		ADB_MSG_PRE_RESET, NULL);
 
 	if (sleepy_trackpad) {
 		/* Let the trackpad settle down */
@@ -427,10 +405,8 @@ do_adb_reset_bus(void)
 	}
 	up(&adb_handler_sem);
 
-	nret = blocking_notifier_call_chain(&adb_client_list,
-			ADB_MSG_POST_RESET, NULL);
-	if (nret & NOTIFY_STOP_MASK)
-		return -EBUSY;
+	blocking_notifier_call_chain(&adb_client_list,
+		ADB_MSG_POST_RESET, NULL);
 	
 	return ret;
 }
--- linux-2.6-git.orig/drivers/macintosh/via-pmu.c	2007-02-07 22:33:32.705922690 +0100
+++ linux-2.6-git/drivers/macintosh/via-pmu.c	2007-02-07 22:38:03.023922690 +0100
@@ -1770,35 +1770,21 @@ EXPORT_SYMBOL(pmu_unregister_sleep_notif
 #if defined(CONFIG_PM) && defined(CONFIG_PPC32)
 
 /* Sleep is broadcast last-to-first */
-static int
-broadcast_sleep(int when, int fallback)
+static void broadcast_sleep(int when)
 {
-	int ret = PBOOK_SLEEP_OK;
 	struct list_head *list;
 	struct pmu_sleep_notifier *notifier;
 
 	for (list = sleep_notifiers.prev; list != &sleep_notifiers;
 	     list = list->prev) {
 		notifier = list_entry(list, struct pmu_sleep_notifier, list);
-		ret = notifier->notifier_call(notifier, when);
-		if (ret != PBOOK_SLEEP_OK) {
-			printk(KERN_DEBUG "sleep %d rejected by %p (%p)\n",
-			       when, notifier, notifier->notifier_call);
-			for (; list != &sleep_notifiers; list = list->next) {
-				notifier = list_entry(list, struct pmu_sleep_notifier, list);
-				notifier->notifier_call(notifier, fallback);
-			}
-			return ret;
-		}
+		notifier->notifier_call(notifier, when);
 	}
-	return ret;
 }
 
 /* Wake is broadcast first-to-last */
-static int
-broadcast_wake(void)
+static void broadcast_wake(void)
 {
-	int ret = PBOOK_SLEEP_OK;
 	struct list_head *list;
 	struct pmu_sleep_notifier *notifier;
 
@@ -1807,7 +1793,6 @@ broadcast_wake(void)
 		notifier = list_entry(list, struct pmu_sleep_notifier, list);
 		notifier->notifier_call(notifier, PBOOK_WAKE);
 	}
-	return ret;
 }
 
 /*
@@ -2014,12 +1999,8 @@ pmac_suspend_devices(void)
 
 	pm_prepare_console();
 	
-	/* Notify old-style device drivers & userland */
-	ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT);
-	if (ret != PBOOK_SLEEP_OK) {
-		printk(KERN_ERR "Sleep rejected by drivers\n");
-		return -EBUSY;
-	}
+	/* Notify old-style device drivers */
+	broadcast_sleep(PBOOK_SLEEP_REQUEST);
 
 	/* Sync the disks. */
 	/* XXX It would be nice to have some way to ensure that
@@ -2029,12 +2010,7 @@ pmac_suspend_devices(void)
 	 */
 	sys_sync();
 
-	/* Sleep can fail now. May not be very robust but useful for debugging */
-	ret = broadcast_sleep(PBOOK_SLEEP_NOW, PBOOK_WAKE);
-	if (ret != PBOOK_SLEEP_OK) {
-		printk(KERN_ERR "Driver sleep failed\n");
-		return -EBUSY;
-	}
+	broadcast_sleep(PBOOK_SLEEP_NOW);
 
 	/* Send suspend call to devices, hold the device core's dpm_sem */
 	ret = device_suspend(PMSG_SUSPEND);
--- linux-2.6-git.orig/include/linux/pmu.h	2007-02-07 22:33:32.817922690 +0100
+++ linux-2.6-git/include/linux/pmu.h	2007-02-07 22:34:39.685922690 +0100
@@ -168,24 +168,16 @@ extern int pmu_get_model(void);
 
 struct pmu_sleep_notifier
 {
-	int (*notifier_call)(struct pmu_sleep_notifier *self, int when);
+	void (*notifier_call)(struct pmu_sleep_notifier *self, int when);
 	int priority;
 	struct list_head list;
 };
 
 /* Code values for calling sleep/wakeup handlers
- *
- * Note: If a sleep request got cancelled, all drivers will get
- * the PBOOK_SLEEP_REJECT, even those who didn't get the PBOOK_SLEEP_REQUEST.
  */
 #define PBOOK_SLEEP_REQUEST	1
 #define PBOOK_SLEEP_NOW		2
-#define PBOOK_SLEEP_REJECT	3
-#define PBOOK_WAKE		4
-
-/* Result codes returned by the notifiers */
-#define PBOOK_SLEEP_OK		0
-#define PBOOK_SLEEP_REFUSE	-1
+#define PBOOK_WAKE		3
 
 /* priority levels in notifiers */
 #define SLEEP_LEVEL_VIDEO	100	/* Video driver (first wake) */
--- linux-2.6-git.orig/drivers/macintosh/via-pmu-led.c	2007-02-07 22:33:32.737922690 +0100
+++ linux-2.6-git/drivers/macintosh/via-pmu-led.c	2007-02-07 22:34:39.687922690 +0100
@@ -81,7 +81,7 @@ static struct led_classdev pmu_led = {
 };
 
 #ifdef CONFIG_PM
-static int pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when)
+static void pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when)
 {
 	unsigned long flags;
 
@@ -99,8 +99,6 @@ static int pmu_led_sleep_call(struct pmu
 		break;
 	}
 	spin_unlock_irqrestore(&pmu_blink_lock, flags);
-
-	return PBOOK_SLEEP_OK;
 }
 
 static struct pmu_sleep_notifier via_pmu_led_sleep_notif = {
--- linux-2.6-git.orig/drivers/macintosh/apm_emu.c	2007-02-07 22:33:32.775922690 +0100
+++ linux-2.6-git/drivers/macintosh/apm_emu.c	2007-02-07 22:34:39.689922690 +0100
@@ -96,7 +96,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitq
 static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
 static struct apm_user *	user_list;
 
-static int apm_notify_sleep(struct pmu_sleep_notifier *self, int when);
+static void apm_notify_sleep(struct pmu_sleep_notifier *self, int when);
 static struct pmu_sleep_notifier apm_sleep_notifier = {
 	apm_notify_sleep,
 	SLEEP_LEVEL_USERLAND,
@@ -352,7 +352,7 @@ static int do_open(struct inode * inode,
  * doesn't provide a way to NAK, but this could be added
  * here.
  */
-static int wait_all_suspend(void)
+static void wait_all_suspend(void)
 {
 	DECLARE_WAITQUEUE(wait, current);
 
@@ -366,24 +366,19 @@ static int wait_all_suspend(void)
 	remove_wait_queue(&apm_suspend_waitqueue, &wait);
 
 	DBG("apm_emu: wait_all_suspend() - complete !\n");
-	
-	return 1;
 }
 
-static int apm_notify_sleep(struct pmu_sleep_notifier *self, int when)
+static void apm_notify_sleep(struct pmu_sleep_notifier *self, int when)
 {
 	switch(when) {
 		case PBOOK_SLEEP_REQUEST:
 			queue_event(APM_SYS_SUSPEND, NULL);
-			if (!wait_all_suspend())
-				return PBOOK_SLEEP_REFUSE;
+			wait_all_suspend();
 			break;
-		case PBOOK_SLEEP_REJECT:
 		case PBOOK_WAKE:
 			queue_event(APM_NORMAL_RESUME, NULL);
 			break;
 	}
-	return PBOOK_SLEEP_OK;
 }
 
 #define APM_CRITICAL		10
--- linux-2.6-git.orig/sound/oss/dmasound/dmasound_awacs.c	2007-02-07 22:37:25.300922690 +0100
+++ linux-2.6-git/sound/oss/dmasound/dmasound_awacs.c	2007-02-07 22:38:20.407922690 +0100
@@ -257,7 +257,7 @@ static volatile struct dbdma_cmd *emerge
 /*
  * Stuff for restoring after a sleep.
  */
-static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when);
+static void awacs_sleep_notify(struct pmu_sleep_notifier *self, int when);
 struct pmu_sleep_notifier awacs_sleep_notifier = {
 	awacs_sleep_notify, SLEEP_LEVEL_SOUND,
 };
@@ -1419,7 +1419,7 @@ load_awacs(void)
  * Save state when going to sleep, restore it afterwards.
  */
 /* FIXME: sort out disabling/re-enabling of read stuff as well */
-static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when)
+static void awacs_sleep_notify(struct pmu_sleep_notifier *self, int when)
 {
 	unsigned long flags;
 
@@ -1548,7 +1548,6 @@ static int awacs_sleep_notify(struct pmu
 		spin_unlock_irqrestore(&dmasound.lock, flags);
 		UNLOCK();
 	}
-	return PBOOK_SLEEP_OK;
 }
 #endif /* CONFIG_PM */
 

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 11/12] powermac: disallow pmu sleep notifiers from aborting sleep
@ 2007-02-08 13:16     ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-08 13:16 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

Tracing through the code, no current PMU sleep notifier can abort sleep.
Since no new PMU sleep notifiers should be added, this patch simplifies the
code and removes the ability to abort sleep.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>

---
This is just something I did before I understood how to do the next patch
in this series. If you want, I can drop this one and rework the next, it's
very well possible to abort suspend from these callbacks even with the
next patch.

Previous version missed dmasound. I'd completely forgotten that still
exists. Maybe we should just remove it?

As Andreas pointed out, it doesn't change the one in
arch/powerpc/kernel/time.c, but that has been removed by the previous
time suspend patch so this patch depends on that.

--- linux-2.6-git.orig/drivers/macintosh/adb.c	2007-02-07 22:33:32.676922690 +0100
+++ linux-2.6-git/drivers/macintosh/adb.c	2007-02-07 22:34:39.678922690 +0100
@@ -90,7 +90,7 @@ static int autopoll_devs;
 int __adb_probe_sync;
 
 #ifdef CONFIG_PM
-static int adb_notify_sleep(struct pmu_sleep_notifier *self, int when);
+static void adb_notify_sleep(struct pmu_sleep_notifier *self, int when);
 static struct pmu_sleep_notifier adb_sleep_notifier = {
 	adb_notify_sleep,
 	SLEEP_LEVEL_ADB,
@@ -340,11 +340,9 @@ __initcall(adb_init);
 /*
  * notify clients before sleep and reset bus afterwards
  */
-int
+void
 adb_notify_sleep(struct pmu_sleep_notifier *self, int when)
 {
-	int ret;
-	
 	switch (when) {
 	case PBOOK_SLEEP_REQUEST:
 		adb_got_sleep = 1;
@@ -353,22 +351,8 @@ adb_notify_sleep(struct pmu_sleep_notifi
 		/* Stop autopoll */
 		if (adb_controller->autopoll)
 			adb_controller->autopoll(0);
-		ret = blocking_notifier_call_chain(&adb_client_list,
-				ADB_MSG_POWERDOWN, NULL);
-		if (ret & NOTIFY_STOP_MASK) {
-			up(&adb_probe_mutex);
-			return PBOOK_SLEEP_REFUSE;
-		}
-		break;
-	case PBOOK_SLEEP_REJECT:
-		if (adb_got_sleep) {
-			adb_got_sleep = 0;
-			up(&adb_probe_mutex);
-			adb_reset_bus();
-		}
-		break;
-		
-	case PBOOK_SLEEP_NOW:
+		blocking_notifier_call_chain(&adb_client_list,
+			ADB_MSG_POWERDOWN, NULL);
 		break;
 	case PBOOK_WAKE:
 		adb_got_sleep = 0;
@@ -376,14 +360,13 @@ adb_notify_sleep(struct pmu_sleep_notifi
 		adb_reset_bus();
 		break;
 	}
-	return PBOOK_SLEEP_OK;
 }
 #endif /* CONFIG_PM */
 
 static int
 do_adb_reset_bus(void)
 {
-	int ret, nret;
+	int ret;
 	
 	if (adb_controller == NULL)
 		return -ENXIO;
@@ -391,13 +374,8 @@ do_adb_reset_bus(void)
 	if (adb_controller->autopoll)
 		adb_controller->autopoll(0);
 
-	nret = blocking_notifier_call_chain(&adb_client_list,
-			ADB_MSG_PRE_RESET, NULL);
-	if (nret & NOTIFY_STOP_MASK) {
-		if (adb_controller->autopoll)
-			adb_controller->autopoll(autopoll_devs);
-		return -EBUSY;
-	}
+	blocking_notifier_call_chain(&adb_client_list,
+		ADB_MSG_PRE_RESET, NULL);
 
 	if (sleepy_trackpad) {
 		/* Let the trackpad settle down */
@@ -427,10 +405,8 @@ do_adb_reset_bus(void)
 	}
 	up(&adb_handler_sem);
 
-	nret = blocking_notifier_call_chain(&adb_client_list,
-			ADB_MSG_POST_RESET, NULL);
-	if (nret & NOTIFY_STOP_MASK)
-		return -EBUSY;
+	blocking_notifier_call_chain(&adb_client_list,
+		ADB_MSG_POST_RESET, NULL);
 	
 	return ret;
 }
--- linux-2.6-git.orig/drivers/macintosh/via-pmu.c	2007-02-07 22:33:32.705922690 +0100
+++ linux-2.6-git/drivers/macintosh/via-pmu.c	2007-02-07 22:38:03.023922690 +0100
@@ -1770,35 +1770,21 @@ EXPORT_SYMBOL(pmu_unregister_sleep_notif
 #if defined(CONFIG_PM) && defined(CONFIG_PPC32)
 
 /* Sleep is broadcast last-to-first */
-static int
-broadcast_sleep(int when, int fallback)
+static void broadcast_sleep(int when)
 {
-	int ret = PBOOK_SLEEP_OK;
 	struct list_head *list;
 	struct pmu_sleep_notifier *notifier;
 
 	for (list = sleep_notifiers.prev; list != &sleep_notifiers;
 	     list = list->prev) {
 		notifier = list_entry(list, struct pmu_sleep_notifier, list);
-		ret = notifier->notifier_call(notifier, when);
-		if (ret != PBOOK_SLEEP_OK) {
-			printk(KERN_DEBUG "sleep %d rejected by %p (%p)\n",
-			       when, notifier, notifier->notifier_call);
-			for (; list != &sleep_notifiers; list = list->next) {
-				notifier = list_entry(list, struct pmu_sleep_notifier, list);
-				notifier->notifier_call(notifier, fallback);
-			}
-			return ret;
-		}
+		notifier->notifier_call(notifier, when);
 	}
-	return ret;
 }
 
 /* Wake is broadcast first-to-last */
-static int
-broadcast_wake(void)
+static void broadcast_wake(void)
 {
-	int ret = PBOOK_SLEEP_OK;
 	struct list_head *list;
 	struct pmu_sleep_notifier *notifier;
 
@@ -1807,7 +1793,6 @@ broadcast_wake(void)
 		notifier = list_entry(list, struct pmu_sleep_notifier, list);
 		notifier->notifier_call(notifier, PBOOK_WAKE);
 	}
-	return ret;
 }
 
 /*
@@ -2014,12 +1999,8 @@ pmac_suspend_devices(void)
 
 	pm_prepare_console();
 	
-	/* Notify old-style device drivers & userland */
-	ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT);
-	if (ret != PBOOK_SLEEP_OK) {
-		printk(KERN_ERR "Sleep rejected by drivers\n");
-		return -EBUSY;
-	}
+	/* Notify old-style device drivers */
+	broadcast_sleep(PBOOK_SLEEP_REQUEST);
 
 	/* Sync the disks. */
 	/* XXX It would be nice to have some way to ensure that
@@ -2029,12 +2010,7 @@ pmac_suspend_devices(void)
 	 */
 	sys_sync();
 
-	/* Sleep can fail now. May not be very robust but useful for debugging */
-	ret = broadcast_sleep(PBOOK_SLEEP_NOW, PBOOK_WAKE);
-	if (ret != PBOOK_SLEEP_OK) {
-		printk(KERN_ERR "Driver sleep failed\n");
-		return -EBUSY;
-	}
+	broadcast_sleep(PBOOK_SLEEP_NOW);
 
 	/* Send suspend call to devices, hold the device core's dpm_sem */
 	ret = device_suspend(PMSG_SUSPEND);
--- linux-2.6-git.orig/include/linux/pmu.h	2007-02-07 22:33:32.817922690 +0100
+++ linux-2.6-git/include/linux/pmu.h	2007-02-07 22:34:39.685922690 +0100
@@ -168,24 +168,16 @@ extern int pmu_get_model(void);
 
 struct pmu_sleep_notifier
 {
-	int (*notifier_call)(struct pmu_sleep_notifier *self, int when);
+	void (*notifier_call)(struct pmu_sleep_notifier *self, int when);
 	int priority;
 	struct list_head list;
 };
 
 /* Code values for calling sleep/wakeup handlers
- *
- * Note: If a sleep request got cancelled, all drivers will get
- * the PBOOK_SLEEP_REJECT, even those who didn't get the PBOOK_SLEEP_REQUEST.
  */
 #define PBOOK_SLEEP_REQUEST	1
 #define PBOOK_SLEEP_NOW		2
-#define PBOOK_SLEEP_REJECT	3
-#define PBOOK_WAKE		4
-
-/* Result codes returned by the notifiers */
-#define PBOOK_SLEEP_OK		0
-#define PBOOK_SLEEP_REFUSE	-1
+#define PBOOK_WAKE		3
 
 /* priority levels in notifiers */
 #define SLEEP_LEVEL_VIDEO	100	/* Video driver (first wake) */
--- linux-2.6-git.orig/drivers/macintosh/via-pmu-led.c	2007-02-07 22:33:32.737922690 +0100
+++ linux-2.6-git/drivers/macintosh/via-pmu-led.c	2007-02-07 22:34:39.687922690 +0100
@@ -81,7 +81,7 @@ static struct led_classdev pmu_led = {
 };
 
 #ifdef CONFIG_PM
-static int pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when)
+static void pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when)
 {
 	unsigned long flags;
 
@@ -99,8 +99,6 @@ static int pmu_led_sleep_call(struct pmu
 		break;
 	}
 	spin_unlock_irqrestore(&pmu_blink_lock, flags);
-
-	return PBOOK_SLEEP_OK;
 }
 
 static struct pmu_sleep_notifier via_pmu_led_sleep_notif = {
--- linux-2.6-git.orig/drivers/macintosh/apm_emu.c	2007-02-07 22:33:32.775922690 +0100
+++ linux-2.6-git/drivers/macintosh/apm_emu.c	2007-02-07 22:34:39.689922690 +0100
@@ -96,7 +96,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitq
 static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
 static struct apm_user *	user_list;
 
-static int apm_notify_sleep(struct pmu_sleep_notifier *self, int when);
+static void apm_notify_sleep(struct pmu_sleep_notifier *self, int when);
 static struct pmu_sleep_notifier apm_sleep_notifier = {
 	apm_notify_sleep,
 	SLEEP_LEVEL_USERLAND,
@@ -352,7 +352,7 @@ static int do_open(struct inode * inode,
  * doesn't provide a way to NAK, but this could be added
  * here.
  */
-static int wait_all_suspend(void)
+static void wait_all_suspend(void)
 {
 	DECLARE_WAITQUEUE(wait, current);
 
@@ -366,24 +366,19 @@ static int wait_all_suspend(void)
 	remove_wait_queue(&apm_suspend_waitqueue, &wait);
 
 	DBG("apm_emu: wait_all_suspend() - complete !\n");
-	
-	return 1;
 }
 
-static int apm_notify_sleep(struct pmu_sleep_notifier *self, int when)
+static void apm_notify_sleep(struct pmu_sleep_notifier *self, int when)
 {
 	switch(when) {
 		case PBOOK_SLEEP_REQUEST:
 			queue_event(APM_SYS_SUSPEND, NULL);
-			if (!wait_all_suspend())
-				return PBOOK_SLEEP_REFUSE;
+			wait_all_suspend();
 			break;
-		case PBOOK_SLEEP_REJECT:
 		case PBOOK_WAKE:
 			queue_event(APM_NORMAL_RESUME, NULL);
 			break;
 	}
-	return PBOOK_SLEEP_OK;
 }
 
 #define APM_CRITICAL		10
--- linux-2.6-git.orig/sound/oss/dmasound/dmasound_awacs.c	2007-02-07 22:37:25.300922690 +0100
+++ linux-2.6-git/sound/oss/dmasound/dmasound_awacs.c	2007-02-07 22:38:20.407922690 +0100
@@ -257,7 +257,7 @@ static volatile struct dbdma_cmd *emerge
 /*
  * Stuff for restoring after a sleep.
  */
-static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when);
+static void awacs_sleep_notify(struct pmu_sleep_notifier *self, int when);
 struct pmu_sleep_notifier awacs_sleep_notifier = {
 	awacs_sleep_notify, SLEEP_LEVEL_SOUND,
 };
@@ -1419,7 +1419,7 @@ load_awacs(void)
  * Save state when going to sleep, restore it afterwards.
  */
 /* FIXME: sort out disabling/re-enabling of read stuff as well */
-static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when)
+static void awacs_sleep_notify(struct pmu_sleep_notifier *self, int when)
 {
 	unsigned long flags;
 
@@ -1548,7 +1548,6 @@ static int awacs_sleep_notify(struct pmu
 		spin_unlock_irqrestore(&dmasound.lock, flags);
 		UNLOCK();
 	}
-	return PBOOK_SLEEP_OK;
 }
 #endif /* CONFIG_PM */
 

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 13/12] mpic: add affinity callback for IPI "chip"
  2007-02-07 12:45 [PATCH 00/12] powerpc/powermac power management patches Johannes Berg
                   ` (11 preceding siblings ...)
  2007-02-07 12:45   ` Johannes Berg
@ 2007-02-08 13:16 ` Johannes Berg
  2007-02-08 21:14   ` Benjamin Herrenschmidt
  12 siblings, 1 reply; 71+ messages in thread
From: Johannes Berg @ 2007-02-08 13:16 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

This patch adds a dummy affinity callback for the IPI "chip" to avoid
getting a warning ("Cannot set affinity for irq 251") when taking a
CPU offline via sysfs or during suspend.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>

--- linux-2.6-git.orig/arch/powerpc/sysdev/mpic.c	2007-02-08 00:19:46.105926568 +0100
+++ linux-2.6-git/arch/powerpc/sysdev/mpic.c	2007-02-08 00:22:31.810926568 +0100
@@ -700,6 +700,12 @@ static void mpic_end_ipi(unsigned int ir
 	mpic_eoi(mpic);
 }
 
+static void mpic_set_ipi_affinity(unsigned int irq, cpumask_t cpumask)
+{
+	/* we can't set affinity but also don't need to since we only
+	 * send IPIs to online CPUs */
+}
+
 #endif /* CONFIG_SMP */
 
 static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
@@ -788,6 +794,7 @@ static struct irq_chip mpic_ipi_chip = {
 	.mask		= mpic_mask_ipi,
 	.unmask		= mpic_unmask_ipi,
 	.eoi		= mpic_end_ipi,
+	.set_affinity	= mpic_set_ipi_affinity,
 };
 #endif /* CONFIG_SMP */
 

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 10/12] powerpc: remove unneeded page_is_ram export
  2007-02-08 13:10       ` Johannes Berg
  (?)
@ 2007-02-08 13:27       ` Johannes Berg
  -1 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-08 13:27 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, linux-pm

arch/powerpc/mm/mem.c exports page_is_ram which is not used anywhere
that could be modular.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>

--- linux-2.6.orig/arch/powerpc/mm/mem.c	2007-02-08 14:07:05.446944128 +0100
+++ linux-2.6/arch/powerpc/mm/mem.c	2007-02-08 14:26:24.016944128 +0100
@@ -83,7 +83,6 @@ int page_is_ram(unsigned long pfn)
 	return 0;
 #endif
 }
-EXPORT_SYMBOL(page_is_ram);
 
 pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 			      unsigned long size, pgprot_t vma_prot)

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
  2007-02-08 13:14     ` Johannes Berg
  (?)
@ 2007-02-08 13:28     ` Johannes Berg
  2007-02-08 15:38         ` Johannes Berg
  2007-02-08 21:59         ` [linux-pm] " Paul Mackerras
  -1 siblings, 2 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-08 13:28 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

This patch allows "hotplugging" of CPUs on G5 machines. CPUs that are
disabled are put into an idle loop with the decrementer frequency set
to minimum. To wake them up again we kick them just like when bringing
them up. To stop those CPUs from messing with any global state we stop
them from entering the timer interrupt.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>

--- linux-2.6-git.orig/arch/powerpc/platforms/powermac/smp.c	2007-02-08 12:52:47.694172211 +0100
+++ linux-2.6-git/arch/powerpc/platforms/powermac/smp.c	2007-02-08 12:52:56.835172211 +0100
@@ -898,7 +898,7 @@ void smp_core99_cpu_die(unsigned int cpu
 	cpu_dead[cpu] = 0;
 }
 
-#endif
+#endif /* CONFIG_HOTPLUG_CPU && CONFIG_PP32 */
 
 /* Core99 Macs (dual G4s and G5s) */
 struct smp_ops_t core99_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,
+	 * the generic code will use kick_cpu then! */
+# endif
 #endif
 };
--- linux-2.6-git.orig/arch/powerpc/platforms/powermac/setup.c	2007-02-08 12:52:47.722172211 +0100
+++ linux-2.6-git/arch/powerpc/platforms/powermac/setup.c	2007-02-08 13:17:06.436651035 +0100
@@ -490,6 +490,9 @@ static int pmac_late_init(void)
 #ifdef CONFIG_SOFTWARE_SUSPEND
 	pm_set_ops(&pmac_pm_ops);
 #endif /* CONFIG_SOFTWARE_SUSPEND */
+	/* this is udbg (which is __init) and we can later use it during
+	 * cpu hotplug (in smp_core99_kick_cpu) */
+	ppc_md.progress = NULL;
 	return 0;
 }
 
@@ -716,6 +719,44 @@ static int pmac_pci_probe_mode(struct pc
 		return PCI_PROBE_NORMAL;
 	return PCI_PROBE_DEVTREE;
 }
+
+#ifdef CONFIG_HOTPLUG_CPU
+/* access per cpu vars from generic smp.c */
+DECLARE_PER_CPU(int, cpu_state);
+
+static void pmac_cpu_die(void)
+{
+	/* turn off as much as possible, we'll be
+	 * kicked out as this will only be invoked
+	 * on core99 platforms for now ... */
+
+	hard_irq_disable();
+
+	printk(KERN_INFO "CPU#%d offline\n", smp_processor_id());
+	__get_cpu_var(cpu_state) = CPU_DEAD;
+	smp_wmb();
+
+	/* during the path that leads here preemption is disabled,
+	 * reenable it now so that when coming up preempt count is
+	 * zero correctly */
+	preempt_enable();
+
+	while (1) {
+		ppc64_runlatch_off();
+
+		/* let's not take timer interrupts too often ... */
+		set_dec(0x7fffffff);
+
+		if (ppc_md.power_save) {
+			ppc_md.power_save();
+		} else {
+			HMT_low();
+			HMT_very_low();
+		}
+	}
+}
+#endif
+
 #endif
 
 static void __init pmac_init_irq(void)
@@ -769,6 +810,6 @@ define_machine(powermac) {
 	.phys_mem_access_prot	= pci_phys_mem_access_prot,
 #endif
 #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64)
-	.cpu_die		= generic_mach_cpu_die,
+	.cpu_die		= pmac_cpu_die,
 #endif
 };
--- linux-2.6-git.orig/arch/powerpc/kernel/time.c	2007-02-08 12:54:22.776172211 +0100
+++ linux-2.6-git/arch/powerpc/kernel/time.c	2007-02-08 13:17:41.666651035 +0100
@@ -597,6 +597,11 @@ static void iSeries_tb_recal(void)
 }
 #endif
 
+#ifdef CONFIG_CPU_HOTPLUG
+/* from smp.c, see below in timer_interrupt() */
+DECLARE_PER_CPU(int, cpu_state);
+#endif
+
 /*
  * For iSeries shared processors, we have to let the hypervisor
  * set the hardware decrementer.  We set a virtual decrementer
@@ -619,6 +624,15 @@ void timer_interrupt(struct pt_regs * re
 	unsigned long ticks;
 	u64 tb_next_jiffy;
 
+#ifdef CONFIG_CPU_HOTPLUG
+	/* if we have fake CPU hotplug just to support suspend to disk
+	 * and can't really turn off a CPU, it may be taking timer interrupts
+	 * even when it is dead. Avoid doing anything in that case so global
+	 * state is not modified for and by a CPU that doesn't really exist. */
+	if (__get_cpu_var(cpu_state) == CPU_DEAD)
+		return;
+#endif
+
 #ifdef CONFIG_PPC32
 	if (atomic_read(&ppc_n_lost_interrupts) != 0)
 		do_IRQ(regs);

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
  2007-02-08 13:28     ` Johannes Berg
@ 2007-02-08 15:38         ` Johannes Berg
  2007-02-08 21:59         ` [linux-pm] " Paul Mackerras
  1 sibling, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-08 15:38 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm


[-- Attachment #1.1: Type: text/plain, Size: 602 bytes --]

On Thu, 2007-02-08 at 14:28 +0100, Johannes Berg wrote:
> 
> +#ifdef CONFIG_CPU_HOTPLUG
> +       /* if we have fake CPU hotplug just to support suspend to disk
> +        * and can't really turn off a CPU, it may be taking timer interrupts
> +        * even when it is dead. Avoid doing anything in that case so global
> +        * state is not modified for and by a CPU that doesn't really exist. */
> +       if (__get_cpu_var(cpu_state) == CPU_DEAD)
> +               return;
> +#endif

Michael Buesch suggested to add an unlikely() there which I'll do for
the next round.

johannes

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
@ 2007-02-08 15:38         ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-08 15:38 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pm

[-- Attachment #1: Type: text/plain, Size: 602 bytes --]

On Thu, 2007-02-08 at 14:28 +0100, Johannes Berg wrote:
> 
> +#ifdef CONFIG_CPU_HOTPLUG
> +       /* if we have fake CPU hotplug just to support suspend to disk
> +        * and can't really turn off a CPU, it may be taking timer interrupts
> +        * even when it is dead. Avoid doing anything in that case so global
> +        * state is not modified for and by a CPU that doesn't really exist. */
> +       if (__get_cpu_var(cpu_state) == CPU_DEAD)
> +               return;
> +#endif

Michael Buesch suggested to add an unlikely() there which I'll do for
the next round.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 13/12] mpic: add affinity callback for IPI "chip"
  2007-02-08 13:16 ` [PATCH 13/12] mpic: add affinity callback for IPI "chip" Johannes Berg
@ 2007-02-08 21:14   ` Benjamin Herrenschmidt
  2007-02-09 15:41       ` Johannes Berg
  2007-02-12 15:20     ` [PATCH 13/12] mpic: set IPIs to be per-CPU Johannes Berg
  0 siblings, 2 replies; 71+ messages in thread
From: Benjamin Herrenschmidt @ 2007-02-08 21:14 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, linux-pm

On Thu, 2007-02-08 at 14:16 +0100, Johannes Berg wrote:
> This patch adds a dummy affinity callback for the IPI "chip" to avoid
> getting a warning ("Cannot set affinity for irq 251") when taking a
> CPU offline via sysfs or during suspend.

Wouldn't be a better option to make sure they have IRQF_PERCPU set and
that we don't do the affinity thing on interrupts with that flag when 
offlining a CPU ?

Ben.

> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
> 
> --- linux-2.6-git.orig/arch/powerpc/sysdev/mpic.c	2007-02-08 00:19:46.105926568 +0100
> +++ linux-2.6-git/arch/powerpc/sysdev/mpic.c	2007-02-08 00:22:31.810926568 +0100
> @@ -700,6 +700,12 @@ static void mpic_end_ipi(unsigned int ir
>  	mpic_eoi(mpic);
>  }
>  
> +static void mpic_set_ipi_affinity(unsigned int irq, cpumask_t cpumask)
> +{
> +	/* we can't set affinity but also don't need to since we only
> +	 * send IPIs to online CPUs */
> +}
> +
>  #endif /* CONFIG_SMP */
>  
>  static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
> @@ -788,6 +794,7 @@ static struct irq_chip mpic_ipi_chip = {
>  	.mask		= mpic_mask_ipi,
>  	.unmask		= mpic_unmask_ipi,
>  	.eoi		= mpic_end_ipi,
> +	.set_affinity	= mpic_set_ipi_affinity,
>  };
>  #endif /* CONFIG_SMP */
>  

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
  2007-02-08 13:28     ` Johannes Berg
@ 2007-02-08 21:59         ` Paul Mackerras
  2007-02-08 21:59         ` [linux-pm] " Paul Mackerras
  1 sibling, 0 replies; 71+ messages in thread
From: Paul Mackerras @ 2007-02-08 21:59 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, linux-pm

Johannes Berg writes:

> +#ifdef CONFIG_CPU_HOTPLUG
> +	/* if we have fake CPU hotplug just to support suspend to disk
> +	 * and can't really turn off a CPU, it may be taking timer interrupts
> +	 * even when it is dead. Avoid doing anything in that case so global
> +	 * state is not modified for and by a CPU that doesn't really exist. */
> +	if (__get_cpu_var(cpu_state) == CPU_DEAD)
> +		return;
> +#endif

Are you sure this is necessary?  IIRC, the if (!cpu_is_offline(cpu)) a
little bit further down is there to cope with this exact situation.
And cpu hotplug already works on G4 SMP powermacs, where we can't
physically remove the cpu either - we just put it into sleep mode with
interrupts disabled, which is what we would be doing on a G5 powermac
also.

Paul.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [linux-pm] [PATCH 02/12] powermac: support G5 CPU hotplug
@ 2007-02-08 21:59         ` Paul Mackerras
  0 siblings, 0 replies; 71+ messages in thread
From: Paul Mackerras @ 2007-02-08 21:59 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, linux-pm

Johannes Berg writes:

> +#ifdef CONFIG_CPU_HOTPLUG
> +	/* if we have fake CPU hotplug just to support suspend to disk
> +	 * and can't really turn off a CPU, it may be taking timer interrupts
> +	 * even when it is dead. Avoid doing anything in that case so global
> +	 * state is not modified for and by a CPU that doesn't really exist. */
> +	if (__get_cpu_var(cpu_state) == CPU_DEAD)
> +		return;
> +#endif

Are you sure this is necessary?  IIRC, the if (!cpu_is_offline(cpu)) a
little bit further down is there to cope with this exact situation.
And cpu hotplug already works on G4 SMP powermacs, where we can't
physically remove the cpu either - we just put it into sleep mode with
interrupts disabled, which is what we would be doing on a G5 powermac
also.

Paul.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
  2007-02-08 13:14     ` Johannes Berg
  (?)
  (?)
@ 2007-02-08 22:24     ` Benjamin Herrenschmidt
  -1 siblings, 0 replies; 71+ messages in thread
From: Benjamin Herrenschmidt @ 2007-02-08 22:24 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, linux-pm

On Thu, 2007-02-08 at 14:14 +0100, Johannes Berg wrote:
> On Wed, 2007-02-07 at 13:45 +0100, Johannes Berg wrote:
> 
> > Except for the in-irq count hack I'm happy with this. I still haven't found
> > where the in-hard-irq count is set to 1 in the down path during suspend or
> > resume and other platforms do similar things so I'm inclined to leave this.
> 
> Um, ok, so the hack breaks platforms that don't have paca, e.g. chrp32.
> 
> Also, I finally figured out how the in-hard-irq count happens. The thing
> is that when I try to turn off the CPU it actually doesn't really turn
> off of course, so it ends up doing NAP and taking timer interrupts...
> which goes irq_enter() and we happen to kill it afterwards.
> 
> I have two ways of fixing this:
>  - just ignore it as we do now
>  - insert a "if (cpu_dead) return" into the timer interrupt function
> 
> I prefer the latter because then we're guaranteed that whatever the
> timer interrupt does we don't modify any state for/by the CPU that isn't
> supposed to exist.

Agreed.

Ben.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
  2007-02-08 13:14     ` Johannes Berg
                       ` (2 preceding siblings ...)
  (?)
@ 2007-02-08 22:24     ` Benjamin Herrenschmidt
  2007-02-09 15:36         ` Johannes Berg
  -1 siblings, 1 reply; 71+ messages in thread
From: Benjamin Herrenschmidt @ 2007-02-08 22:24 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, linux-pm

On Thu, 2007-02-08 at 14:14 +0100, Johannes Berg wrote:
> On Wed, 2007-02-07 at 13:45 +0100, Johannes Berg wrote:
> 
> > Except for the in-irq count hack I'm happy with this. I still haven't found
> > where the in-hard-irq count is set to 1 in the down path during suspend or
> > resume and other platforms do similar things so I'm inclined to leave this.
> 
> Um, ok, so the hack breaks platforms that don't have paca, e.g. chrp32.
> 
> Also, I finally figured out how the in-hard-irq count happens. The thing
> is that when I try to turn off the CPU it actually doesn't really turn
> off of course, so it ends up doing NAP and taking timer interrupts...
> which goes irq_enter() and we happen to kill it afterwards.
> 
> I have two ways of fixing this:
>  - just ignore it as we do now
>  - insert a "if (cpu_dead) return" into the timer interrupt function
> 
> I prefer the latter because then we're guaranteed that whatever the
> timer interrupt does we don't modify any state for/by the CPU that isn't
> supposed to exist.

Or we can just mark interrupts as soft-disabled ?

Ben.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
  2007-02-08 21:59         ` [linux-pm] " Paul Mackerras
@ 2007-02-08 22:33           ` Benjamin Herrenschmidt
  -1 siblings, 0 replies; 71+ messages in thread
From: Benjamin Herrenschmidt @ 2007-02-08 22:33 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, Johannes Berg, linux-pm


> Are you sure this is necessary?  IIRC, the if (!cpu_is_offline(cpu)) a
> little bit further down is there to cope with this exact situation.
> And cpu hotplug already works on G4 SMP powermacs, where we can't
> physically remove the cpu either - we just put it into sleep mode with
> interrupts disabled, which is what we would be doing on a G5 powermac
> also.

I've always had doubts about wether SLEEP with EE off was legal and
wouldn't actually still go out of sleep when getting an interrupt... In
that case, at least on CPUs where the DEC acts "level" triggered, we
need to at least reset the DEC to some sane value.

Ben.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [linux-pm] [PATCH 02/12] powermac: support G5 CPU hotplug
@ 2007-02-08 22:33           ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 71+ messages in thread
From: Benjamin Herrenschmidt @ 2007-02-08 22:33 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, Johannes Berg, linux-pm


> Are you sure this is necessary?  IIRC, the if (!cpu_is_offline(cpu)) a
> little bit further down is there to cope with this exact situation.
> And cpu hotplug already works on G4 SMP powermacs, where we can't
> physically remove the cpu either - we just put it into sleep mode with
> interrupts disabled, which is what we would be doing on a G5 powermac
> also.

I've always had doubts about wether SLEEP with EE off was legal and
wouldn't actually still go out of sleep when getting an interrupt... In
that case, at least on CPUs where the DEC acts "level" triggered, we
need to at least reset the DEC to some sane value.

Ben.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
  2007-02-08 22:24     ` Benjamin Herrenschmidt
@ 2007-02-09 15:36         ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-09 15:36 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linux-pm


[-- Attachment #1.1: Type: text/plain, Size: 254 bytes --]

On Fri, 2007-02-09 at 09:24 +1100, Benjamin Herrenschmidt wrote:

> Or we can just mark interrupts as soft-disabled ?

The power4 nap function enables both so we'd have to change some things
around there. Probably a better idea though.

johannes

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
@ 2007-02-09 15:36         ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-09 15:36 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linux-pm

[-- Attachment #1: Type: text/plain, Size: 254 bytes --]

On Fri, 2007-02-09 at 09:24 +1100, Benjamin Herrenschmidt wrote:

> Or we can just mark interrupts as soft-disabled ?

The power4 nap function enables both so we'd have to change some things
around there. Probably a better idea though.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
  2007-02-08 21:59         ` [linux-pm] " Paul Mackerras
@ 2007-02-09 15:39           ` Johannes Berg
  -1 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-09 15:39 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, linux-pm


[-- Attachment #1.1: Type: text/plain, Size: 1552 bytes --]

On Fri, 2007-02-09 at 08:59 +1100, Paul Mackerras wrote:
> Johannes Berg writes:
> 
> > +#ifdef CONFIG_CPU_HOTPLUG
> > +	/* if we have fake CPU hotplug just to support suspend to disk
> > +	 * and can't really turn off a CPU, it may be taking timer interrupts
> > +	 * even when it is dead. Avoid doing anything in that case so global
> > +	 * state is not modified for and by a CPU that doesn't really exist. */
> > +	if (__get_cpu_var(cpu_state) == CPU_DEAD)
> > +		return;
> > +#endif
> 
> Are you sure this is necessary?  IIRC, the if (!cpu_is_offline(cpu)) a
> little bit further down is there to cope with this exact situation.

Yes, but we still do irq_enter() and as it happens with HZ=1000 we
almost always kick the CPU out while it's inbetween irq_enter() and
irq_exit().

You said:

> And cpu hotplug already works on G4 SMP powermacs, where we can't
> physically remove the cpu either - we just put it into sleep mode with
> interrupts disabled, which is what we would be doing on a G5 powermac
> also.

and then Benh said:

> I've always had doubts about wether SLEEP with EE off was legal and
> wouldn't actually still go out of sleep when getting an interrupt... In
> that case, at least on CPUs where the DEC acts "level" triggered, we
> need to at least reset the DEC to some sane value.

I probably should've mentioned that. I tried going into NAP with EE off
and that seemed to get me a busy loop where the CPU wasn't even napping
at all. I could have done something wrong, of course.

johannes

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [linux-pm] [PATCH 02/12] powermac: support G5 CPU hotplug
@ 2007-02-09 15:39           ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-09 15:39 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, linux-pm

[-- Attachment #1: Type: text/plain, Size: 1552 bytes --]

On Fri, 2007-02-09 at 08:59 +1100, Paul Mackerras wrote:
> Johannes Berg writes:
> 
> > +#ifdef CONFIG_CPU_HOTPLUG
> > +	/* if we have fake CPU hotplug just to support suspend to disk
> > +	 * and can't really turn off a CPU, it may be taking timer interrupts
> > +	 * even when it is dead. Avoid doing anything in that case so global
> > +	 * state is not modified for and by a CPU that doesn't really exist. */
> > +	if (__get_cpu_var(cpu_state) == CPU_DEAD)
> > +		return;
> > +#endif
> 
> Are you sure this is necessary?  IIRC, the if (!cpu_is_offline(cpu)) a
> little bit further down is there to cope with this exact situation.

Yes, but we still do irq_enter() and as it happens with HZ=1000 we
almost always kick the CPU out while it's inbetween irq_enter() and
irq_exit().

You said:

> And cpu hotplug already works on G4 SMP powermacs, where we can't
> physically remove the cpu either - we just put it into sleep mode with
> interrupts disabled, which is what we would be doing on a G5 powermac
> also.

and then Benh said:

> I've always had doubts about wether SLEEP with EE off was legal and
> wouldn't actually still go out of sleep when getting an interrupt... In
> that case, at least on CPUs where the DEC acts "level" triggered, we
> need to at least reset the DEC to some sane value.

I probably should've mentioned that. I tried going into NAP with EE off
and that seemed to get me a busy loop where the CPU wasn't even napping
at all. I could have done something wrong, of course.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 13/12] mpic: add affinity callback for IPI "chip"
  2007-02-08 21:14   ` Benjamin Herrenschmidt
@ 2007-02-09 15:41       ` Johannes Berg
  2007-02-12 15:20     ` [PATCH 13/12] mpic: set IPIs to be per-CPU Johannes Berg
  1 sibling, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-09 15:41 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linux-pm


[-- Attachment #1.1: Type: text/plain, Size: 683 bytes --]

On Fri, 2007-02-09 at 08:14 +1100, Benjamin Herrenschmidt wrote:
> 
> > This patch adds a dummy affinity callback for the IPI "chip" to avoid
> > getting a warning ("Cannot set affinity for irq 251") when taking a
> > CPU offline via sysfs or during suspend.
> 
> Wouldn't be a better option to make sure they have IRQF_PERCPU set and
> that we don't do the affinity thing on interrupts with that flag when 
> offlining a CPU ?

Hmm. Yeah, something like that could be possible. Looking at
fixup_irqs() there is a test:

                if (irq_desc[irq].status & IRQ_PER_CPU)
                        continue;

but I'd have to dig what else this means.

johannes

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 13/12] mpic: add affinity callback for IPI "chip"
@ 2007-02-09 15:41       ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-09 15:41 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linux-pm

[-- Attachment #1: Type: text/plain, Size: 683 bytes --]

On Fri, 2007-02-09 at 08:14 +1100, Benjamin Herrenschmidt wrote:
> 
> > This patch adds a dummy affinity callback for the IPI "chip" to avoid
> > getting a warning ("Cannot set affinity for irq 251") when taking a
> > CPU offline via sysfs or during suspend.
> 
> Wouldn't be a better option to make sure they have IRQF_PERCPU set and
> that we don't do the affinity thing on interrupts with that flag when 
> offlining a CPU ?

Hmm. Yeah, something like that could be possible. Looking at
fixup_irqs() there is a test:

                if (irq_desc[irq].status & IRQ_PER_CPU)
                        continue;

but I'd have to dig what else this means.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 02/12] powermac: support G5 CPU hotplug
  2007-02-09 15:36         ` Johannes Berg
  (?)
@ 2007-02-12 15:15         ` Johannes Berg
  2007-02-15  3:44           ` Paul Mackerras
  -1 siblings, 1 reply; 71+ messages in thread
From: Johannes Berg @ 2007-02-12 15:15 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linux-pm

This patch allows "hotplugging" of CPUs on G5 machines. CPUs that are
disabled are put into an idle loop with the decrementer frequency set
to minimum. To wake them up again we kick them just like when bringing
them up.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>

---
This one seems better. I just soft-disable interrupts from the idle
function and exit it to reset the decrementer.

 arch/powerpc/kernel/idle_power4.S       |   14 +++++++++----
 arch/powerpc/platforms/powermac/setup.c |   34 +++++++++++++++++++++++++++++++-
 arch/powerpc/platforms/powermac/smp.c   |   12 +++++++++--
 include/asm-powerpc/machdep.h           |    2 +
 4 files changed, 55 insertions(+), 7 deletions(-)

--- linux-2.6-git.orig/arch/powerpc/platforms/powermac/smp.c	2007-02-12 15:35:52.380522210 +0100
+++ linux-2.6-git/arch/powerpc/platforms/powermac/smp.c	2007-02-12 15:36:12.990522210 +0100
@@ -897,7 +897,7 @@ void smp_core99_cpu_die(unsigned int cpu
 	cpu_dead[cpu] = 0;
 }
 
-#endif
+#endif /* CONFIG_HOTPLUG_CPU && CONFIG_PP32 */
 
 /* Core99 Macs (dual G4s and G5s) */
 struct smp_ops_t core99_smp_ops = {
@@ -907,8 +907,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,
+	 * the generic code will use kick_cpu then! */
+# endif
 #endif
 };
--- linux-2.6-git.orig/arch/powerpc/platforms/powermac/setup.c	2007-02-12 15:35:52.418522210 +0100
+++ linux-2.6-git/arch/powerpc/platforms/powermac/setup.c	2007-02-12 15:39:42.512522210 +0100
@@ -425,6 +425,9 @@ static int initializing = 1;
 static int pmac_late_init(void)
 {
 	initializing = 0;
+	/* this is udbg (which is __init) and we can later use it during
+	 * cpu hotplug (in smp_core99_kick_cpu) */
+	ppc_md.progress = NULL;
 	return 0;
 }
 
@@ -651,6 +654,35 @@ static int pmac_pci_probe_mode(struct pc
 		return PCI_PROBE_NORMAL;
 	return PCI_PROBE_DEVTREE;
 }
+
+#ifdef CONFIG_HOTPLUG_CPU
+/* access per cpu vars from generic smp.c */
+DECLARE_PER_CPU(int, cpu_state);
+
+static void pmac_cpu_die(void)
+{
+	/* turn off as much as possible, we'll be
+	 * kicked out as this will only be invoked
+	 * on core99 platforms for now ... */
+
+	printk(KERN_INFO "CPU#%d offline\n", smp_processor_id());
+	__get_cpu_var(cpu_state) = CPU_DEAD;
+	smp_wmb();
+
+	/* during the path that leads here preemption is disabled,
+	 * reenable it now so that when coming up preempt count is
+	 * zero correctly */
+	preempt_enable();
+
+	while (1) {
+		/* let's not take timer interrupts too often ... */
+		set_dec(0x7fffffff);
+
+		power4_idle_irqs_softdisabled();
+	}
+}
+#endif
+
 #endif
 
 define_machine(powermac) {
@@ -689,6 +721,6 @@ define_machine(powermac) {
 	.phys_mem_access_prot	= pci_phys_mem_access_prot,
 #endif
 #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64)
-	.cpu_die		= generic_mach_cpu_die,
+	.cpu_die		= pmac_cpu_die,
 #endif
 };
--- linux-2.6-git.orig/arch/powerpc/kernel/idle_power4.S	2007-02-12 15:35:52.493522210 +0100
+++ linux-2.6-git/arch/powerpc/kernel/idle_power4.S	2007-02-12 15:39:20.382522210 +0100
@@ -19,7 +19,12 @@
 
 	.text
 
+_GLOBAL(power4_idle_irqs_softdisabled)
+	li	r6,1
+	b	0f
 _GLOBAL(power4_idle)
+	li	r6,0
+0:
 BEGIN_FTR_SECTION
 	blr
 END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
@@ -35,8 +40,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
 	rotldi	r0,r0,16
 	mtmsrd	r0,1			/* hard-disable interrupts */
 	li	r0,1
-	stb	r0,PACASOFTIRQEN(r13)	/* we'll hard-enable shortly */
-	stb	r0,PACAHARDIRQEN(r13)
+	stb	r0,PACAHARDIRQEN(r13)	/* we'll hard-enable shortly */
+	stb	r6,PACASOFTIRQEN(r13)	/* set softirqs enabled bit */
 BEGIN_FTR_SECTION
 	DSSALL
 	sync
@@ -51,5 +56,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	isync
 	mtmsrd	r7
 	isync
-	b	1b
-
+	beq-	1b			/* cr0 is still set, exit if this
+					   is power4_idle_irqs_softdisabled */
+	blr
--- linux-2.6-git.orig/include/asm-powerpc/machdep.h	2007-02-12 15:35:52.551522210 +0100
+++ linux-2.6-git/include/asm-powerpc/machdep.h	2007-02-12 15:36:13.006522210 +0100
@@ -252,6 +252,8 @@ struct machdep_calls {
 
 extern void power4_idle(void);
 extern void ppc6xx_idle(void);
+/* this one is for CPU hotplug (e.g. powermac) */
+extern void power4_idle_irqs_softdisabled(void);
 
 /*
  * ppc_md contains a copy of the machine description structure for the

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 13/12] mpic: set IPIs to be per-CPU
  2007-02-08 21:14   ` Benjamin Herrenschmidt
  2007-02-09 15:41       ` Johannes Berg
@ 2007-02-12 15:20     ` Johannes Berg
  1 sibling, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-12 15:20 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linux-pm

This patch changes the MPIC IPIs to be per-CPU to avoid getting a
warning ("Cannot set affinity for irq 251") when taking a CPU
offline via sysfs or during suspend.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>

---
Yup, that's a lot better, thanks.

 arch/powerpc/sysdev/mpic.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- linux-2.6-git.orig/arch/powerpc/sysdev/mpic.c	2007-02-12 15:12:36.079524117 +0100
+++ linux-2.6-git/arch/powerpc/sysdev/mpic.c	2007-02-12 15:23:18.812465943 +0100
@@ -1388,7 +1388,7 @@ void mpic_request_ipis(void)
 			printk(KERN_ERR "Failed to map IPI %d\n", i);
 			break;
 		}
-		request_irq(vipi, mpic_ipi_action, IRQF_DISABLED,
+		request_irq(vipi, mpic_ipi_action, IRQF_DISABLED|IRQF_PERCPU,
 			    ipi_names[i], mpic);
 	}
 }

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 05/12] power management: no valid states w/o pm_ops + docs
  2007-02-07 12:45   ` Johannes Berg
@ 2007-02-13 12:12     ` Pavel Machek
  -1 siblings, 0 replies; 71+ messages in thread
From: Pavel Machek @ 2007-02-13 12:12 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, linux-pm

Hi!

> This patch changes /sys/power/state to not advertise any valid states
> (except for disk if SOFTWARE_SUSPEND is enabled) when no pm_ops have been
> set so userspace can easily discover what states should be available.
> 
> Also, because the pm ops in powermac are obviously not using them as
> intended, I added documentation for it in kernel-doc format.
> 
> Reordering the fields in struct pm_ops not only makes the output of
> kernel-doc make more sense but also removes a hole from the structure on
> 64-bit platforms.
> 
> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
> Cc: linux-pm@lists.osdl.org
> Cc: Rafael J. Wysocki <rjw@sisk.pl>
> Cc: Pavel Macheck <pavel@ucw.cz>

Looks okay to me.
										Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 05/12] power management: no valid states w/o pm_ops + docs
@ 2007-02-13 12:12     ` Pavel Machek
  0 siblings, 0 replies; 71+ messages in thread
From: Pavel Machek @ 2007-02-13 12:12 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Rafael J. Wysocki, linuxppc-dev, linux-pm

Hi!

> This patch changes /sys/power/state to not advertise any valid states
> (except for disk if SOFTWARE_SUSPEND is enabled) when no pm_ops have been
> set so userspace can easily discover what states should be available.
> 
> Also, because the pm ops in powermac are obviously not using them as
> intended, I added documentation for it in kernel-doc format.
> 
> Reordering the fields in struct pm_ops not only makes the output of
> kernel-doc make more sense but also removes a hole from the structure on
> 64-bit platforms.
> 
> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
> Cc: linux-pm@lists.osdl.org
> Cc: Rafael J. Wysocki <rjw@sisk.pl>
> Cc: Pavel Macheck <pavel@ucw.cz>

Looks okay to me.
										Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 05/12] power management: no valid states w/o pm_ops + docs
  2007-02-13 12:12     ` Pavel Machek
@ 2007-02-13 16:08       ` Johannes Berg
  -1 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-13 16:08 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linuxppc-dev, linux-pm


[-- Attachment #1.1: Type: text/plain, Size: 907 bytes --]

On Tue, 2007-02-13 at 13:12 +0100, Pavel Machek wrote:
> Hi!
> 
> > This patch changes /sys/power/state to not advertise any valid states
> > (except for disk if SOFTWARE_SUSPEND is enabled) when no pm_ops have been
> > set so userspace can easily discover what states should be available.
> > 
> > Also, because the pm ops in powermac are obviously not using them as
> > intended, I added documentation for it in kernel-doc format.
> > 
> > Reordering the fields in struct pm_ops not only makes the output of
> > kernel-doc make more sense but also removes a hole from the structure on
> > 64-bit platforms.
> > 
> > Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
> > Cc: linux-pm@lists.osdl.org
> > Cc: Rafael J. Wysocki <rjw@sisk.pl>
> > Cc: Pavel Macheck <pavel@ucw.cz>
> 
> Looks okay to me.

Are you going to pick it up or should I send it to someone else?

johannes

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 05/12] power management: no valid states w/o pm_ops + docs
@ 2007-02-13 16:08       ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-13 16:08 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Rafael J. Wysocki, linuxppc-dev, linux-pm

[-- Attachment #1: Type: text/plain, Size: 907 bytes --]

On Tue, 2007-02-13 at 13:12 +0100, Pavel Machek wrote:
> Hi!
> 
> > This patch changes /sys/power/state to not advertise any valid states
> > (except for disk if SOFTWARE_SUSPEND is enabled) when no pm_ops have been
> > set so userspace can easily discover what states should be available.
> > 
> > Also, because the pm ops in powermac are obviously not using them as
> > intended, I added documentation for it in kernel-doc format.
> > 
> > Reordering the fields in struct pm_ops not only makes the output of
> > kernel-doc make more sense but also removes a hole from the structure on
> > 64-bit platforms.
> > 
> > Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
> > Cc: linux-pm@lists.osdl.org
> > Cc: Rafael J. Wysocki <rjw@sisk.pl>
> > Cc: Pavel Macheck <pavel@ucw.cz>
> 
> Looks okay to me.

Are you going to pick it up or should I send it to someone else?

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 05/12] power management: no valid states w/o pm_ops + docs
  2007-02-13 16:08       ` Johannes Berg
@ 2007-02-13 16:14         ` Pavel Machek
  -1 siblings, 0 replies; 71+ messages in thread
From: Pavel Machek @ 2007-02-13 16:14 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, linux-pm

Hi!

> > > This patch changes /sys/power/state to not advertise any valid states
> > > (except for disk if SOFTWARE_SUSPEND is enabled) when no pm_ops have been
> > > set so userspace can easily discover what states should be available.
> > > 
> > > Also, because the pm ops in powermac are obviously not using them as
> > > intended, I added documentation for it in kernel-doc format.
> > > 
> > > Reordering the fields in struct pm_ops not only makes the output of
> > > kernel-doc make more sense but also removes a hole from the structure on
> > > 64-bit platforms.
> > > 
> > > Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
> > > Cc: linux-pm@lists.osdl.org
> > > Cc: Rafael J. Wysocki <rjw@sisk.pl>
> > > Cc: Pavel Macheck <pavel@ucw.cz>
> > 
> > Looks okay to me.
> 
> Are you going to pick it up or should I send it to someone else?

Add my Acked-by and send it to akpm. I do not actually maintain a
tree.

								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 05/12] power management: no valid states w/o pm_ops + docs
@ 2007-02-13 16:14         ` Pavel Machek
  0 siblings, 0 replies; 71+ messages in thread
From: Pavel Machek @ 2007-02-13 16:14 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Rafael J. Wysocki, linuxppc-dev, linux-pm

Hi!

> > > This patch changes /sys/power/state to not advertise any valid states
> > > (except for disk if SOFTWARE_SUSPEND is enabled) when no pm_ops have been
> > > set so userspace can easily discover what states should be available.
> > > 
> > > Also, because the pm ops in powermac are obviously not using them as
> > > intended, I added documentation for it in kernel-doc format.
> > > 
> > > Reordering the fields in struct pm_ops not only makes the output of
> > > kernel-doc make more sense but also removes a hole from the structure on
> > > 64-bit platforms.
> > > 
> > > Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
> > > Cc: linux-pm@lists.osdl.org
> > > Cc: Rafael J. Wysocki <rjw@sisk.pl>
> > > Cc: Pavel Macheck <pavel@ucw.cz>
> > 
> > Looks okay to me.
> 
> Are you going to pick it up or should I send it to someone else?

Add my Acked-by and send it to akpm. I do not actually maintain a
tree.

								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
  2007-02-08 13:14     ` Johannes Berg
@ 2007-02-14 14:45       ` Pavel Machek
  -1 siblings, 0 replies; 71+ messages in thread
From: Pavel Machek @ 2007-02-14 14:45 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, linux-pm

Hi!

> > Except for the in-irq count hack I'm happy with this. I still haven't found
> > where the in-hard-irq count is set to 1 in the down path during suspend or
> > resume and other platforms do similar things so I'm inclined to leave this.
> 
> Um, ok, so the hack breaks platforms that don't have paca, e.g. chrp32.
> 
> Also, I finally figured out how the in-hard-irq count happens. The thing
> is that when I try to turn off the CPU it actually doesn't really turn
> off of course, so it ends up doing NAP and taking timer interrupts...
> which goes irq_enter() and we happen to kill it afterwards.
> 
> I have two ways of fixing this:
>  - just ignore it as we do now
>  - insert a "if (cpu_dead) return" into the timer interrupt function
> 
> I prefer the latter because then we're guaranteed that whatever the
> timer interrupt does we don't modify any state for/by the CPU that isn't
> supposed to exist.

Can you disable timer interrupt on the interrupt controller, instead?
Provides same functionality, and needs no runtime overhead...
									Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [linux-pm] [PATCH 02/12] powermac: support G5 CPU hotplug
@ 2007-02-14 14:45       ` Pavel Machek
  0 siblings, 0 replies; 71+ messages in thread
From: Pavel Machek @ 2007-02-14 14:45 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, linux-pm

Hi!

> > Except for the in-irq count hack I'm happy with this. I still haven't found
> > where the in-hard-irq count is set to 1 in the down path during suspend or
> > resume and other platforms do similar things so I'm inclined to leave this.
> 
> Um, ok, so the hack breaks platforms that don't have paca, e.g. chrp32.
> 
> Also, I finally figured out how the in-hard-irq count happens. The thing
> is that when I try to turn off the CPU it actually doesn't really turn
> off of course, so it ends up doing NAP and taking timer interrupts...
> which goes irq_enter() and we happen to kill it afterwards.
> 
> I have two ways of fixing this:
>  - just ignore it as we do now
>  - insert a "if (cpu_dead) return" into the timer interrupt function
> 
> I prefer the latter because then we're guaranteed that whatever the
> timer interrupt does we don't modify any state for/by the CPU that isn't
> supposed to exist.

Can you disable timer interrupt on the interrupt controller, instead?
Provides same functionality, and needs no runtime overhead...
									Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
  2007-02-14 14:45       ` [linux-pm] " Pavel Machek
@ 2007-02-14 19:11         ` Johannes Berg
  -1 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-14 19:11 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linuxppc-dev, linux-pm


[-- Attachment #1.1: Type: text/plain, Size: 426 bytes --]

On Wed, 2007-02-14 at 15:45 +0100, Pavel Machek wrote:

> Can you disable timer interrupt on the interrupt controller, instead?

No, it's not actually an external interrupt, the "timer interrupt" on
powerpc is the decrementer exception which is built into the CPU.

In any case, the soft-irq disable stuff I already posted a bit later
provides the same with no more runtime overhead than we already have.

johannes

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [linux-pm] [PATCH 02/12] powermac: support G5 CPU hotplug
@ 2007-02-14 19:11         ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-14 19:11 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linuxppc-dev, linux-pm

[-- Attachment #1: Type: text/plain, Size: 426 bytes --]

On Wed, 2007-02-14 at 15:45 +0100, Pavel Machek wrote:

> Can you disable timer interrupt on the interrupt controller, instead?

No, it's not actually an external interrupt, the "timer interrupt" on
powerpc is the decrementer exception which is built into the CPU.

In any case, the soft-irq disable stuff I already posted a bit later
provides the same with no more runtime overhead than we already have.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
  2007-02-14 14:45       ` [linux-pm] " Pavel Machek
@ 2007-02-14 21:27         ` Benjamin Herrenschmidt
  -1 siblings, 0 replies; 71+ messages in thread
From: Benjamin Herrenschmidt @ 2007-02-14 21:27 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linuxppc-dev, Johannes Berg, linux-pm


> Can you disable timer interrupt on the interrupt controller, instead?
> Provides same functionality, and needs no runtime overhead...

On most PowerPCs, timer interrupt aren't an interrupt comimg from the
interrupt controller, but their own processor exception triggered by the
decrementer defined by the ppc architecture. 

Ben.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [linux-pm] [PATCH 02/12] powermac: support G5 CPU hotplug
@ 2007-02-14 21:27         ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 71+ messages in thread
From: Benjamin Herrenschmidt @ 2007-02-14 21:27 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linuxppc-dev, Johannes Berg, linux-pm


> Can you disable timer interrupt on the interrupt controller, instead?
> Provides same functionality, and needs no runtime overhead...

On most PowerPCs, timer interrupt aren't an interrupt comimg from the
interrupt controller, but their own processor exception triggered by the
decrementer defined by the ppc architecture. 

Ben.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
  2007-02-12 15:15         ` Johannes Berg
@ 2007-02-15  3:44           ` Paul Mackerras
  2007-02-15 15:08               ` Johannes Berg
  2007-02-15 19:43             ` Johannes Berg
  0 siblings, 2 replies; 71+ messages in thread
From: Paul Mackerras @ 2007-02-15  3:44 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-pm, linuxppc-dev

Johannes Berg writes:

> +_GLOBAL(power4_idle_irqs_softdisabled)
> +	li	r6,1
> +	b	0f
>  _GLOBAL(power4_idle)
> +	li	r6,0
> +0:
>  BEGIN_FTR_SECTION
>  	blr
>  END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
> @@ -35,8 +40,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
>  	rotldi	r0,r0,16
>  	mtmsrd	r0,1			/* hard-disable interrupts */
>  	li	r0,1
> -	stb	r0,PACASOFTIRQEN(r13)	/* we'll hard-enable shortly */
> -	stb	r0,PACAHARDIRQEN(r13)
> +	stb	r0,PACAHARDIRQEN(r13)	/* we'll hard-enable shortly */
> +	stb	r6,PACASOFTIRQEN(r13)	/* set softirqs enabled bit */

Don't you have something backwards here?  If we come in through
power4_idle_irqs_softdisabled, the name would indicate to me that we
want to end up with paca->soft_enabled set to 0, not 1.

Paul.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
  2007-02-15  3:44           ` Paul Mackerras
@ 2007-02-15 15:08               ` Johannes Berg
  2007-02-15 19:43             ` Johannes Berg
  1 sibling, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-15 15:08 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linux-pm, linuxppc-dev


[-- Attachment #1.1: Type: text/plain, Size: 1003 bytes --]

On Thu, 2007-02-15 at 14:44 +1100, Paul Mackerras wrote:

> > +_GLOBAL(power4_idle_irqs_softdisabled)
> > +	li	r6,1
> > +	b	0f
> >  _GLOBAL(power4_idle)
> > +	li	r6,0
> > +0:
> >  BEGIN_FTR_SECTION
> >  	blr
> >  END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
> > @@ -35,8 +40,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
> >  	rotldi	r0,r0,16
> >  	mtmsrd	r0,1			/* hard-disable interrupts */
> >  	li	r0,1
> > -	stb	r0,PACASOFTIRQEN(r13)	/* we'll hard-enable shortly */
> > -	stb	r0,PACAHARDIRQEN(r13)
> > +	stb	r0,PACAHARDIRQEN(r13)	/* we'll hard-enable shortly */
> > +	stb	r6,PACASOFTIRQEN(r13)	/* set softirqs enabled bit */
> 
> Don't you have something backwards here?  If we come in through
> power4_idle_irqs_softdisabled, the name would indicate to me that we
> want to end up with paca->soft_enabled set to 0, not 1.

Umm, yes, looks like. I'll rewrite it. Interesting that it worked as I
had expected though (I actually put a printk into the timer interrupt!).

johannes

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

[-- Attachment #2: Type: text/plain, Size: 146 bytes --]

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
@ 2007-02-15 15:08               ` Johannes Berg
  0 siblings, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-15 15:08 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linux-pm, linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 1003 bytes --]

On Thu, 2007-02-15 at 14:44 +1100, Paul Mackerras wrote:

> > +_GLOBAL(power4_idle_irqs_softdisabled)
> > +	li	r6,1
> > +	b	0f
> >  _GLOBAL(power4_idle)
> > +	li	r6,0
> > +0:
> >  BEGIN_FTR_SECTION
> >  	blr
> >  END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
> > @@ -35,8 +40,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
> >  	rotldi	r0,r0,16
> >  	mtmsrd	r0,1			/* hard-disable interrupts */
> >  	li	r0,1
> > -	stb	r0,PACASOFTIRQEN(r13)	/* we'll hard-enable shortly */
> > -	stb	r0,PACAHARDIRQEN(r13)
> > +	stb	r0,PACAHARDIRQEN(r13)	/* we'll hard-enable shortly */
> > +	stb	r6,PACASOFTIRQEN(r13)	/* set softirqs enabled bit */
> 
> Don't you have something backwards here?  If we come in through
> power4_idle_irqs_softdisabled, the name would indicate to me that we
> want to end up with paca->soft_enabled set to 0, not 1.

Umm, yes, looks like. I'll rewrite it. Interesting that it worked as I
had expected though (I actually put a printk into the timer interrupt!).

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/12] powermac: support G5 CPU hotplug
  2007-02-15  3:44           ` Paul Mackerras
  2007-02-15 15:08               ` Johannes Berg
@ 2007-02-15 19:43             ` Johannes Berg
  1 sibling, 0 replies; 71+ messages in thread
From: Johannes Berg @ 2007-02-15 19:43 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linux-pm, linuxppc-dev

This patch allows "hotplugging" of CPUs on G5 machines. CPUs that are
disabled are put into an idle loop with the decrementer frequency set
to minimum. To wake them up again we kick them just like when bringing
them up. To stop those CPUs from messing with any global state we stop
them from entering the timer interrupt.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>

---
This makes more sense... Thanks for pointing that out. I wonder why it
actually worked.

 arch/powerpc/kernel/idle_power4.S       |   15 ++++++++++----
 arch/powerpc/platforms/powermac/setup.c |   34 +++++++++++++++++++++++++++++++-
 arch/powerpc/platforms/powermac/smp.c   |   12 +++++++++--
 include/asm-powerpc/machdep.h           |    2 +
 4 files changed, 56 insertions(+), 7 deletions(-)

--- linux-2.6-git.orig/arch/powerpc/platforms/powermac/smp.c	2007-02-12 19:14:13.584037567 +0100
+++ linux-2.6-git/arch/powerpc/platforms/powermac/smp.c	2007-02-12 19:14:32.345037567 +0100
@@ -897,7 +897,7 @@ void smp_core99_cpu_die(unsigned int cpu
 	cpu_dead[cpu] = 0;
 }
 
-#endif
+#endif /* CONFIG_HOTPLUG_CPU && CONFIG_PP32 */
 
 /* Core99 Macs (dual G4s and G5s) */
 struct smp_ops_t core99_smp_ops = {
@@ -907,8 +907,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,
+	 * the generic code will use kick_cpu then! */
+# endif
 #endif
 };
--- linux-2.6-git.orig/arch/powerpc/platforms/powermac/setup.c	2007-02-12 19:14:32.182037567 +0100
+++ linux-2.6-git/arch/powerpc/platforms/powermac/setup.c	2007-02-12 19:14:32.347037567 +0100
@@ -425,6 +425,9 @@ static int initializing = 1;
 static int pmac_late_init(void)
 {
 	initializing = 0;
+	/* this is udbg (which is __init) and we can later use it during
+	 * cpu hotplug (in smp_core99_kick_cpu) */
+	ppc_md.progress = NULL;
 	return 0;
 }
 
@@ -651,6 +654,35 @@ static int pmac_pci_probe_mode(struct pc
 		return PCI_PROBE_NORMAL;
 	return PCI_PROBE_DEVTREE;
 }
+
+#ifdef CONFIG_HOTPLUG_CPU
+/* access per cpu vars from generic smp.c */
+DECLARE_PER_CPU(int, cpu_state);
+
+static void pmac_cpu_die(void)
+{
+	/* turn off as much as possible, we'll be
+	 * kicked out as this will only be invoked
+	 * on core99 platforms for now ... */
+
+	printk(KERN_INFO "CPU#%d offline\n", smp_processor_id());
+	__get_cpu_var(cpu_state) = CPU_DEAD;
+	smp_wmb();
+
+	/* during the path that leads here preemption is disabled,
+	 * reenable it now so that when coming up preempt count is
+	 * zero correctly */
+	preempt_enable();
+
+	while (1) {
+		/* let's not take timer interrupts too often ... */
+		set_dec(0x7fffffff);
+
+		power4_idle_irqs_softdisabled();
+	}
+}
+#endif
+
 #endif
 
 define_machine(powermac) {
@@ -689,6 +721,6 @@ define_machine(powermac) {
 	.phys_mem_access_prot	= pci_phys_mem_access_prot,
 #endif
 #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64)
-	.cpu_die		= generic_mach_cpu_die,
+	.cpu_die		= pmac_cpu_die,
 #endif
 };
--- linux-2.6-git.orig/arch/powerpc/kernel/idle_power4.S	2007-02-12 19:14:13.624037567 +0100
+++ linux-2.6-git/arch/powerpc/kernel/idle_power4.S	2007-02-15 20:16:06.906249905 +0100
@@ -19,7 +19,12 @@
 
 	.text
 
+_GLOBAL(power4_idle_irqs_softdisabled)
+	li	r6,0
+	b	0f
 _GLOBAL(power4_idle)
+	li	r6,1
+0:
 BEGIN_FTR_SECTION
 	blr
 END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
@@ -35,8 +40,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
 	rotldi	r0,r0,16
 	mtmsrd	r0,1			/* hard-disable interrupts */
 	li	r0,1
-	stb	r0,PACASOFTIRQEN(r13)	/* we'll hard-enable shortly */
-	stb	r0,PACAHARDIRQEN(r13)
+	stb	r0,PACAHARDIRQEN(r13)	/* we'll hard-enable shortly */
+	stb	r6,PACASOFTIRQEN(r13)	/* set softirqs enabled bit */
 BEGIN_FTR_SECTION
 	DSSALL
 	sync
@@ -51,5 +56,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	isync
 	mtmsrd	r7
 	isync
-	b	1b
-
+	cmpdi	0,r6,0
+	bne+	1b
+	blr
--- linux-2.6-git.orig/include/asm-powerpc/machdep.h	2007-02-12 19:14:13.645037567 +0100
+++ linux-2.6-git/include/asm-powerpc/machdep.h	2007-02-15 20:15:27.287249905 +0100
@@ -252,6 +252,8 @@ struct machdep_calls {
 
 extern void power4_idle(void);
 extern void ppc6xx_idle(void);
+/* this one is for CPU hotplug (e.g. powermac) */
+extern void power4_idle_irqs_softdisabled(void);
 
 /*
  * ppc_md contains a copy of the machine description structure for the

^ permalink raw reply	[flat|nested] 71+ messages in thread

end of thread, other threads:[~2007-02-15 19:43 UTC | newest]

Thread overview: 71+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-07 12:45 [PATCH 00/12] powerpc/powermac power management patches Johannes Berg
2007-02-07 12:45 ` [PATCH 01/12] powerpc: MPIC sys_device & suspend/resume Johannes Berg
2007-02-07 12:45   ` Johannes Berg
2007-02-07 12:45 ` [PATCH 02/12] powermac: support G5 CPU hotplug Johannes Berg
2007-02-07 12:45   ` Johannes Berg
2007-02-08 13:14   ` Johannes Berg
2007-02-08 13:14     ` Johannes Berg
2007-02-08 13:28     ` Johannes Berg
2007-02-08 15:38       ` Johannes Berg
2007-02-08 15:38         ` Johannes Berg
2007-02-08 21:59       ` Paul Mackerras
2007-02-08 21:59         ` [linux-pm] " Paul Mackerras
2007-02-08 22:33         ` Benjamin Herrenschmidt
2007-02-08 22:33           ` [linux-pm] " Benjamin Herrenschmidt
2007-02-09 15:39         ` Johannes Berg
2007-02-09 15:39           ` [linux-pm] " Johannes Berg
2007-02-08 22:24     ` Benjamin Herrenschmidt
2007-02-08 22:24     ` Benjamin Herrenschmidt
2007-02-09 15:36       ` Johannes Berg
2007-02-09 15:36         ` Johannes Berg
2007-02-12 15:15         ` Johannes Berg
2007-02-15  3:44           ` Paul Mackerras
2007-02-15 15:08             ` Johannes Berg
2007-02-15 15:08               ` Johannes Berg
2007-02-15 19:43             ` Johannes Berg
2007-02-14 14:45     ` Pavel Machek
2007-02-14 14:45       ` [linux-pm] " Pavel Machek
2007-02-14 19:11       ` Johannes Berg
2007-02-14 19:11         ` [linux-pm] " Johannes Berg
2007-02-14 21:27       ` Benjamin Herrenschmidt
2007-02-14 21:27         ` [linux-pm] " Benjamin Herrenschmidt
2007-02-07 12:45 ` [PATCH 03/12] powerpc: dart iommu suspend Johannes Berg
2007-02-07 12:45   ` Johannes Berg
2007-02-07 12:45 ` [PATCH 04/12] powerpc: mark pages that dont exist as Nosave Johannes Berg
2007-02-07 12:45   ` Johannes Berg
2007-02-07 12:45 ` [PATCH 05/12] power management: no valid states w/o pm_ops + docs Johannes Berg
2007-02-07 12:45   ` Johannes Berg
2007-02-13 12:12   ` Pavel Machek
2007-02-13 12:12     ` Pavel Machek
2007-02-13 16:08     ` Johannes Berg
2007-02-13 16:08       ` Johannes Berg
2007-02-13 16:14       ` Pavel Machek
2007-02-13 16:14         ` Pavel Machek
2007-02-07 12:45 ` [PATCH 06/12] powerpc: fix suspend states again Johannes Berg
2007-02-07 12:45   ` Johannes Berg
2007-02-07 12:45 ` [PATCH 07/12] powermac: suspend to disk on G5 Johannes Berg
2007-02-07 12:45   ` Johannes Berg
2007-02-07 12:45 ` [PATCH 08/12] powermac: fix G5-cpufreq for cpu on/offline Johannes Berg
2007-02-07 12:45   ` Johannes Berg
2007-02-07 12:45 ` [PATCH 09/12] powerpc: remove bogus comment about page_is_ram Johannes Berg
2007-02-07 12:45   ` Johannes Berg
2007-02-07 12:45 ` [PATCH 10/12] powerpc: remove unneeded exports in mem.c Johannes Berg
2007-02-07 12:45   ` Johannes Berg
2007-02-08  4:25   ` Paul Mackerras
2007-02-08 13:10     ` Johannes Berg
2007-02-08 13:10       ` Johannes Berg
2007-02-08 13:27       ` [PATCH 10/12] powerpc: remove unneeded page_is_ram export Johannes Berg
2007-02-07 12:45 ` [PATCH 11/12] powermac: disallow pmu sleep notifiers from aborting sleep Johannes Berg
2007-02-07 12:45   ` Johannes Berg
2007-02-07 22:52   ` Andreas Schwab
2007-02-08 13:08     ` Johannes Berg
2007-02-08 13:08       ` Johannes Berg
2007-02-08 13:16   ` Johannes Berg
2007-02-08 13:16     ` Johannes Berg
2007-02-07 12:45 ` [PATCH 12/12] powermac: proper sleep management Johannes Berg
2007-02-07 12:45   ` Johannes Berg
2007-02-08 13:16 ` [PATCH 13/12] mpic: add affinity callback for IPI "chip" Johannes Berg
2007-02-08 21:14   ` Benjamin Herrenschmidt
2007-02-09 15:41     ` Johannes Berg
2007-02-09 15:41       ` Johannes Berg
2007-02-12 15:20     ` [PATCH 13/12] mpic: set IPIs to be per-CPU Johannes Berg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.