Re: [PATCH 2/3] powermac: proper time of day after resume
From: Johannes Berg <johannes@sipsolutions.net>
Date: 2007-01-26 14:36:06
On Wed, 2007-01-24 at 17:34 +1100, Benjamin Herrenschmidt wrote:
On Wed, 2006-12-13 at 13:38 +0100, Johannes Berg wrote:quoted
plain text document attachment (time-resume.patch) This patch converts the time restore code from a PMU notifier to a regular sys device so I can profit from it even when I don't suspend through the PMU, i.e. suspend to disk. Also another step towards dropping pmu_sleep_notifier completely.I'd rather do it differently: On suspend, read the RTC and save the value. On resume, read it again, diff the values, and add that to the current time.
Alright, how about something like this? I still need to fill in the actual calculations of course :)
--- mb-wireless.orig/arch/powerpc/platforms/powermac/time.c 2007-01-25 14:09:12.288927117 +0100
+++ mb-wireless/arch/powerpc/platforms/powermac/time.c 2007-01-26 14:16:18.598954773 +0100@@ -297,49 +297,11 @@ int __init via_calibrate_decr(void) } #endif -#ifdef CONFIG_PM -/* - * Reset the time after a sleep. - */ -static int -time_sleep_notify(struct pmu_sleep_notifier *self, int when) -{ - static unsigned long time_diff; - unsigned long flags; - unsigned long seq; - struct timespec tv; - - switch (when) { - case PBOOK_SLEEP_NOW: - do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - time_diff = xtime.tv_sec - pmac_get_boot_time(); - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - break; - case PBOOK_WAKE: - tv.tv_sec = pmac_get_boot_time() + time_diff; - tv.tv_nsec = 0; - do_settimeofday(&tv); - break; - } - return PBOOK_SLEEP_OK; -} - -static struct pmu_sleep_notifier time_sleep_notifier = { - time_sleep_notify, SLEEP_LEVEL_MISC, -}; -#endif /* CONFIG_PM */ - /* * Query the OF and get the decr frequency. */ void __init pmac_calibrate_decr(void) { -#if defined(CONFIG_PM) && defined(CONFIG_ADB_PMU) - /* XXX why here? */ - pmu_register_sleep_notifier(&time_sleep_notifier); -#endif - generic_calibrate_decr(); #ifdef CONFIG_PPC32 --- mb-wireless.orig/arch/powerpc/kernel/Makefile 2007-01-26 14:16:35.838954773 +0100 +++ mb-wireless/arch/powerpc/kernel/Makefile 2007-01-26 14:16:47.918954773 +0100
@@ -50,6 +50,7 @@ extra-y += vmlinux.lds obj-y += time.o prom.o traps.o setup-common.o \ udbg.o misc.o io.o +obj-$(CONFIG_PM) += time_suspend.o obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ mb-wireless/arch/powerpc/kernel/time_suspend.c 2007-01-26 15:33:55.879025345 +0100
@@ -0,0 +1,62 @@ +/* + * Common code to keep time when machine suspends. + * + * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> + * + * GPLv2 + */ + +#include <linux/time.h> +#include <asm/rtc.h> + +static struct rtc_time suspend_rtc_time; + +/* + * Reset the time after a sleep. + */ +static int timer_resume(struct sys_device *dev) +{ + struct timespec tv; + struct rtc_time cur_rtc_time; + + + get_rtc_time(&suspend_rtc_time); + + do_gettimeofday(&tv); + + /* FIXME: do something with tv here */ + + do_settimeofday(&tv); + + return 0; +} + +static int timer_suspend(struct sys_device *dev, pm_message_t state) +{ + WARN_ON(!ppc_md.get_rtc_time); + + get_rtc_time(&suspend_rtc_time); + + return 0; +} + +static struct sysdev_class timer_sysclass = { + .resume = timer_resume, + .suspend = timer_suspend, + set_kset_name("timer"), +}; + +static struct sys_device device_timer = { + .id = 0, + .cls = &timer_sysclass, +}; + +static int time_init_device(void) +{ + int error = sysdev_class_register(&timer_sysclass); + if (!error) + error = sysdev_register(&device_timer); + return error; +} + +device_initcall(time_init_device);
Attachments
- signature.asc [application/pgp-signature] 190 bytes