On Tue, Apr 27, 2004 at 02:25:11PM +1000, Benjamin Herrenschmidt wrote: > That should be fixed in recent fbdev code, I haven't updated my tree > yet though. I'll check that. Great. > > BTW. Can somebody send me back the latest pmdisk patch ? :) The one I'm using (including the USB fix) is attached. Cheers, -- Guido
Index: kernel/sys.c
===================================================================
--- kernel/sys.c (revision 26)
+++ kernel/sys.c (working copy)
@@ -84,7 +84,7 @@
* and the like.
*/
-static struct notifier_block *reboot_notifier_list;
+struct notifier_block *reboot_notifier_list;
rwlock_t notifier_lock = RW_LOCK_UNLOCKED;
/**
Index: kernel/power/main.c
===================================================================
--- kernel/power/main.c (revision 26)
+++ kernel/power/main.c (working copy)
@@ -120,6 +120,7 @@
char * pm_states[] = {
[PM_SUSPEND_STANDBY] = "standby",
+ [2] = "",
[PM_SUSPEND_MEM] = "mem",
[PM_SUSPEND_DISK] = "disk",
NULL,
Index: kernel/power/pmdisk.c
===================================================================
--- kernel/power/pmdisk.c (revision 26)
+++ kernel/power/pmdisk.c (working copy)
@@ -18,7 +18,7 @@
*
*/
-#undef DEBUG
+#define DEBUG
#include <linux/mm.h>
#include <linux/bio.h>
@@ -569,7 +572,7 @@
/**
- * enough_free_mem - Make sure we enough free memory to snapshot.
+ * enough_free_mem - Make sure we have enough free memory to snapshot.
*
* Returns TRUE or FALSE after checking the number of available
* free pages.
@@ -625,8 +628,10 @@
{
int error = 0;
- if ((error = read_swapfiles()))
+ if ((error = read_swapfiles())) {
+ printk("Can't read swapfiles\n");
return error;
+ }
drain_local_pages();
@@ -703,6 +709,7 @@
* Magic happens here
*/
+#if 0
int pmdisk_resume(void)
{
BUG_ON (nr_copy_pages_check != pmdisk_pages);
@@ -712,6 +719,7 @@
__flush_tlb_global();
return 0;
}
+#endif
/* pmdisk_arch_suspend() is implemented in arch/?/power/pmdisk.S,
and basically does:
@@ -1083,9 +1091,11 @@
if ((error = arch_prepare_suspend()))
return error;
local_irq_disable();
+ device_power_down(PM_SUSPEND_DISK);
save_processor_state();
error = pmdisk_arch_suspend(0);
restore_processor_state();
+ device_power_up();
local_irq_enable();
return error;
}
@@ -1144,10 +1154,13 @@
int __init pmdisk_restore(void)
{
int error;
+
local_irq_disable();
+ device_power_down(PM_SUSPEND_DISK);
save_processor_state();
error = pmdisk_arch_suspend(1);
restore_processor_state();
+ device_power_up();
local_irq_enable();
return error;
}
Index: kernel/power/disk.c
===================================================================
--- kernel/power/disk.c (revision 26)
+++ kernel/power/disk.c (working copy)
@@ -17,6 +17,7 @@
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/fs.h>
+#include <linux/reboot.h>
#include "power.h"
@@ -45,23 +46,26 @@
unsigned long flags;
int error = 0;
- local_irq_save(flags);
- device_power_down(PM_SUSPEND_DISK);
switch(mode) {
case PM_DISK_PLATFORM:
+ local_irq_save(flags);
error = pm_ops->enter(PM_SUSPEND_DISK);
+ local_irq_restore(flags);
break;
case PM_DISK_SHUTDOWN:
printk("Powering off system\n");
+ notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
+ device_shutdown();
machine_power_off();
break;
case PM_DISK_REBOOT:
+ printk("Rebooting system\n");
+ notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
+ device_shutdown();
machine_restart(NULL);
break;
}
machine_halt();
- device_power_up();
- local_irq_restore(flags);
return 0;
}
@@ -162,8 +166,10 @@
pr_debug("PM: snapshotting memory.\n");
in_suspend = 1;
- if ((error = pmdisk_save()))
+ if ((error = pmdisk_save())) {
+ pr_debug("PM: snapshot memory failed !\n");
goto Done;
+ }
if (in_suspend) {
pr_debug("PM: writing image.\n");
@@ -224,9 +230,6 @@
* Do it with disabled interrupts for best effect. That way, if some
* driver scheduled DMA, we have good chance for DMA to finish ;-).
*/
- pr_debug("PM: Waiting for DMAs to settle down.\n");
- mdelay(1000);
-
pr_debug("PM: Restoring saved image.\n");
pmdisk_restore();
pr_debug("PM: Restore failed, recovering.n");
Index: include/linux/pm.h
===================================================================
--- include/linux/pm.h (revision 26)
+++ include/linux/pm.h (working copy)
@@ -195,10 +195,10 @@
extern void (*pm_power_off)(void);
enum {
- PM_SUSPEND_ON,
- PM_SUSPEND_STANDBY,
- PM_SUSPEND_MEM,
- PM_SUSPEND_DISK,
+ PM_SUSPEND_ON = 0,
+ PM_SUSPEND_STANDBY = 1,
+ PM_SUSPEND_MEM = 3,
+ PM_SUSPEND_DISK = 4,
PM_SUSPEND_MAX,
};
Index: include/linux/suspend.h
===================================================================
--- include/linux/suspend.h (revision 26)
+++ include/linux/suspend.h (working copy)
@@ -1,9 +1,9 @@
#ifndef _LINUX_SWSUSP_H
#define _LINUX_SWSUSP_H
-#ifdef CONFIG_X86
+//#ifdef CONFIG_X86
#include <asm/suspend.h>
-#endif
+//#endif
#include <linux/swap.h>
#include <linux/notifier.h>
#include <linux/config.h>
Index: include/linux/reboot.h
===================================================================
--- include/linux/reboot.h (revision 26)
+++ include/linux/reboot.h (working copy)
@@ -40,6 +40,8 @@
extern int register_reboot_notifier(struct notifier_block *);
extern int unregister_reboot_notifier(struct notifier_block *);
+/* For use by swsusp only */
+extern struct notifier_block *reboot_notifier_list;
/*
* Architecture-specific implementations of sys_reboot commands.
Index: arch/ppc/kernel/Makefile
===================================================================
--- arch/ppc/kernel/Makefile (revision 26)
+++ arch/ppc/kernel/Makefile (working copy)
@@ -15,6 +15,7 @@
extra-$(CONFIG_8xx) := head_8xx.o
extra-$(CONFIG_6xx) += idle_6xx.o
extra-$(CONFIG_POWER4) += idle_power4.o
+
extra-y += vmlinux.lds.s
obj-y := entry.o traps.o irq.o idle.o time.o misc.o \
@@ -22,6 +23,7 @@
semaphore.o syscalls.o setup.o \
cputable.o ppc_htab.o
obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o
+obj-$(CONFIG_PM_DISK) += pmdisk.o
obj-$(CONFIG_POWER4) += cpu_setup_power4.o
obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o
obj-$(CONFIG_PCI) += pci.o
Index: arch/ppc/kernel/vmlinux.lds.S
===================================================================
--- arch/ppc/kernel/vmlinux.lds.S (revision 26)
+++ arch/ppc/kernel/vmlinux.lds.S (working copy)
@@ -72,6 +72,12 @@
CONSTRUCTORS
}
+ . = ALIGN(4096);
+ __nosave_begin = .;
+ .data_nosave : { *(.data.nosave) }
+ . = ALIGN(4096);
+ __nosave_end = .;
+
. = ALIGN(32);
.data.cacheline_aligned : { *(.data.cacheline_aligned) }
Index: arch/ppc/kernel/signal.c
===================================================================
--- arch/ppc/kernel/signal.c (revision 26)
+++ arch/ppc/kernel/signal.c (working copy)
@@ -28,6 +28,7 @@
#include <linux/elf.h>
#include <linux/tty.h>
#include <linux/binfmts.h>
+#include <linux/suspend.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -569,6 +570,11 @@
unsigned long frame, newsp;
int signr, ret;
+ if (current->flags & PF_FREEZE) {
+ refrigerator(0);
+ return 0;
+ }
+
if (!oldset)
oldset = ¤t->blocked;
Index: arch/ppc/Kconfig
===================================================================
--- arch/ppc/Kconfig (revision 26)
+++ arch/ppc/Kconfig (working copy)
@@ -914,6 +914,8 @@
source "drivers/zorro/Kconfig"
+source kernel/power/Kconfig
+
endmenu
menu "Bus options"
Index: arch/ppc/platforms/pmac_setup.c
===================================================================
--- arch/ppc/platforms/pmac_setup.c (revision 26)
+++ arch/ppc/platforms/pmac_setup.c (working copy)
@@ -51,6 +51,7 @@
#include <linux/irq.h>
#include <linux/seq_file.h>
#include <linux/root_dev.h>
+#include <linux/suspend.h>
#include <asm/reg.h>
#include <asm/sections.h>
@@ -70,6 +71,8 @@
#include <asm/pmac_feature.h>
#include <asm/time.h>
#include <asm/of_device.h>
+#include <asm/mmu_context.h>
+
#include "pmac_pic.h"
#include "mem_pieces.h"
@@ -425,11 +428,65 @@
#endif
}
+/* TODO: Merge the suspend-to-ram with the common code !!!
+ * currently, this is a stub implementation for suspend-to-disk
+ * only
+ */
+
+#ifdef CONFIG_PM_DISK
+
+static int pmac_pm_prepare(u32 state)
+{
+ printk(KERN_DEBUG "pmac_pm_prepare(%d)\n", state);
+
+ return 0;
+}
+
+static int pmac_pm_enter(u32 state)
+{
+ printk(KERN_DEBUG "pmac_pm_enter(%d)\n", 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[0]->cpu_features & CPU_FTR_ALTIVEC)
+ enable_kernel_altivec();
+#endif /* CONFIG_ALTIVEC */
+
+ return 0;
+}
+
+static int pmac_pm_finish(u32 state)
+{
+ printk(KERN_DEBUG "pmac_pm_finish(%d)\n", state);
+
+ /* Restore userland MMU context */
+ set_context(current->active_mm->context, current->active_mm->pgd);
+
+ 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,
+};
+
+#endif /* CONFIG_PM_DISK */
+
static int initializing = 1;
static int pmac_late_init(void)
{
initializing = 0;
+
+#ifdef CONFIG_PM_DISK
+ pm_set_ops(&pmac_pm_ops);
+#endif /* CONFIG_PM_DISK */
return 0;
}
Index: arch/ppc/platforms/pmac_feature.c
===================================================================
--- arch/ppc/platforms/pmac_feature.c (revision 26)
+++ arch/ppc/platforms/pmac_feature.c (working copy)
@@ -1156,7 +1156,7 @@
(void)MACIO_IN32(KEYLARGO_FCR1);
mdelay(1);
LOCK(flags);
- MACIO_BIS(KEYLARGO_FCR0, KL1_USB2_CELL_ENABLE);
+ MACIO_BIS(KEYLARGO_FCR1, KL1_USB2_CELL_ENABLE);
}
if (number < 4) {
reg = MACIO_IN32(KEYLARGO_FCR4);
Index: drivers/video/aty/radeon_pm.c
===================================================================
--- drivers/video/aty/radeon_pm.c (revision 26)
+++ drivers/video/aty/radeon_pm.c (working copy)
@@ -846,6 +846,8 @@
*/
printk(KERN_DEBUG "radeonfb: suspending to state: %d...\n", state);
+ if (state != 2 && state != 3)
+ return 0;
if (pdev->dev.power_state >= state)
return 0;
Index: drivers/macintosh/Kconfig
===================================================================
--- drivers/macintosh/Kconfig (revision 26)
+++ drivers/macintosh/Kconfig (working copy)
@@ -80,7 +80,7 @@
config PMAC_PBOOK
bool "Power management support for PowerBooks"
- depends on ADB_PMU
+ depends on PM && ADB_PMU
---help---
This provides support for putting a PowerBook to sleep; it also
enables media bay support. Power management works on the
@@ -97,10 +97,10 @@
have it autoloaded. The act of removing the module shuts down the
sound hardware for more power savings.
-config PM
- bool
- depends on PPC_PMAC && ADB_PMU && PMAC_PBOOK
- default y
+#config PM
+# bool
+# depends on PPC_PMAC && ADB_PMU && PMAC_PBOOK
+# default y
config PMAC_APM_EMU
tristate "APM emulation"
Index: drivers/macintosh/mediabay.c
===================================================================
--- drivers/macintosh/mediabay.c (revision 26)
+++ drivers/macintosh/mediabay.c (working copy)
@@ -715,7 +715,7 @@
{
struct media_bay_info *bay = macio_get_drvdata(mdev);
- if (state != mdev->ofdev.dev.power_state && state >= 2) {
+ if (state != mdev->ofdev.dev.power_state && state >= 2 && state != 4) {
down(&bay->lock);
bay->sleeping = 1;
set_mb_power(bay, 0);
Index: drivers/macintosh/via-pmu.c
===================================================================
--- drivers/macintosh/via-pmu.c (revision 26)
+++ drivers/macintosh/via-pmu.c (working copy)
@@ -43,6 +43,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/device.h>
+#include <linux/sysdev.h>
#include <linux/suspend.h>
#include <linux/syscalls.h>
#include <asm/prom.h>
@@ -2324,7 +2325,7 @@
/* 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 acheived using the refrigerator for processes
+ * could be achieved using the refrigerator for processes
* that swsusp uses
*/
sys_sync();
@@ -2377,7 +2378,6 @@
/* Wait for completion of async backlight requests */
while (!bright_req_1.complete || !bright_req_2.complete ||
-
!batt_req.complete)
pmu_poll();
@@ -3045,6 +3045,88 @@
}
#endif /* DEBUG_SLEEP */
+
+/* FIXME: This is a temporary set of callbacks to enable us
+ * to do suspend-to-disk.
+ */
+
+#ifdef CONFIG_PM
+
+static int pmu_sys_suspended = 0;
+
+static int pmu_sys_suspend(struct sys_device *sysdev, u32 state)
+{
+ if (state != PM_SUSPEND_DISK || pmu_sys_suspended)
+ return 0;
+
+ /* Suspend PMU event interrupts */
+ pmu_suspend();
+
+ pmu_sys_suspended = 1;
+ return 0;
+}
+
+static int pmu_sys_resume(struct sys_device *sysdev)
+{
+ struct adb_request req;
+
+ if (!pmu_sys_suspended)
+ return 0;
+
+ /* Tell PMU we are ready */
+ pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
+ pmu_wait_complete(&req);
+
+ /* Resume PMU event interrupts */
+ pmu_resume();
+
+ pmu_sys_suspended = 0;
+
+ return 0;
+}
+
+#endif /* CONFIG_PM */
+
+static struct sysdev_class pmu_sysclass = {
+ set_kset_name("pmu"),
+};
+
+static struct sys_device device_pmu = {
+ .id = 0,
+ .cls = &pmu_sysclass,
+};
+
+static struct sysdev_driver driver_pmu = {
+#ifdef CONFIG_PM
+ .suspend = &pmu_sys_suspend,
+ .resume = &pmu_sys_resume,
+#endif /* CONFIG_PM */
+};
+
+static int __init init_pmu_sysfs(void)
+{
+ int rc;
+
+ rc = sysdev_class_register(&pmu_sysclass);
+ if (rc) {
+ printk(KERN_ERR "Failed registering PMU sys class\n");
+ return -ENODEV;
+ }
+ rc = sysdev_register(&device_pmu);
+ if (rc) {
+ printk(KERN_ERR "Failed registering PMU sys device\n");
+ return -ENODEV;
+ }
+ rc = sysdev_driver_register(&pmu_sysclass, &driver_pmu);
+ if (rc) {
+ printk(KERN_ERR "Failed registering PMU sys driver\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+subsys_initcall(init_pmu_sysfs);
+
EXPORT_SYMBOL(pmu_request);
EXPORT_SYMBOL(pmu_poll);
EXPORT_SYMBOL(pmu_poll_adb);
Index: drivers/ide/ppc/pmac.c
===================================================================
--- drivers/ide/ppc/pmac.c (revision 26)
+++ drivers/ide/ppc/pmac.c (working copy)
@@ -1372,7 +1372,7 @@
ide_hwif_t *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
int rc = 0;
- if (state != mdev->ofdev.dev.power_state && state >= 2) {
+ if (state != mdev->ofdev.dev.power_state && state >= 2 && state != 4) {
rc = pmac_ide_do_suspend(hwif);
if (rc == 0)
mdev->ofdev.dev.power_state = state;
@@ -1480,7 +1480,7 @@
ide_hwif_t *hwif = (ide_hwif_t *)pci_get_drvdata(pdev);
int rc = 0;
- if (state != pdev->dev.power_state && state >= 2) {
+ if (state != pdev->dev.power_state && state >= 2 && state != 4) {
rc = pmac_ide_do_suspend(hwif);
if (rc == 0)
pdev->dev.power_state = state;
Attachment:
signature.asc
Description: Digital signature