* [RFC][PATCH -mm 0/2] Suspend notifiers @ 2007-04-21 22:02 Rafael J. Wysocki 2007-04-21 22:05 ` [RFC][PATCH -mm 1/2] swsusp: Free more memory Rafael J. Wysocki 2007-04-21 22:07 ` [RFC][PATCH -mm 2/2] PM: Introduce suspend notifiers Rafael J. Wysocki 0 siblings, 2 replies; 10+ messages in thread From: Rafael J. Wysocki @ 2007-04-21 22:02 UTC (permalink / raw) To: Pavel Machek; +Cc: pm list, Nigel Cunningham Hi, The following two patches are intended to address the problem that some drivers allocate a lot of memory in their .suspend() routines causing swsusp to fail (and generally may want to do some things that shouldn't be done in .suspend()/.resume()). Greetings, Rafael -- If you don't have the time to read, you don't have the time or the tools to write. - Stephen King ^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC][PATCH -mm 1/2] swsusp: Free more memory 2007-04-21 22:02 [RFC][PATCH -mm 0/2] Suspend notifiers Rafael J. Wysocki @ 2007-04-21 22:05 ` Rafael J. Wysocki 2007-04-21 23:31 ` Nigel Cunningham 2007-04-22 12:55 ` Pavel Machek 2007-04-21 22:07 ` [RFC][PATCH -mm 2/2] PM: Introduce suspend notifiers Rafael J. Wysocki 1 sibling, 2 replies; 10+ messages in thread From: Rafael J. Wysocki @ 2007-04-21 22:05 UTC (permalink / raw) To: Pavel Machek; +Cc: pm list, Nigel Cunningham From: Rafael J. Wysocki <rjw@sisk.pl> Move the definition of PAGES_FOR_IO to kernel/power/power.h and introduce SPARE_PAGES representing the number of pages that should be freed by the swsusp's memory shrinker in addition to PAGES_FOR_IO so that device drivers can allocate some memory (up to 1 MB total) in their .suspend() routines without causing the suspend to fail. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> --- include/linux/suspend.h | 6 ------ kernel/power/power.h | 12 +++++++++++- kernel/power/swsusp.c | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) Index: linux-2.6.21-rc6-mm1/include/linux/suspend.h =================================================================== --- linux-2.6.21-rc6-mm1.orig/include/linux/suspend.h 2007-04-21 23:24:28.000000000 +0200 +++ linux-2.6.21-rc6-mm1/include/linux/suspend.h 2007-04-21 23:24:44.000000000 +0200 @@ -60,10 +60,4 @@ struct saved_context; void __save_processor_state(struct saved_context *ctxt); void __restore_processor_state(struct saved_context *ctxt); -/* - * XXX: We try to keep some more pages free so that I/O operations succeed - * without paging. Might this be more? - */ -#define PAGES_FOR_IO 1024 - #endif /* _LINUX_SWSUSP_H */ Index: linux-2.6.21-rc6-mm1/kernel/power/power.h =================================================================== --- linux-2.6.21-rc6-mm1.orig/kernel/power/power.h 2007-04-21 23:24:28.000000000 +0200 +++ linux-2.6.21-rc6-mm1/kernel/power/power.h 2007-04-21 23:24:44.000000000 +0200 @@ -14,8 +14,18 @@ struct swsusp_info { #ifdef CONFIG_SOFTWARE_SUSPEND -extern int pm_suspend_disk(void); +/* + * Keep some memory free so that I/O operations can succeed without paging + * [Might this be more than 4 MB?] + */ +#define PAGES_FOR_IO ((4096 * 1024) >> PAGE_SHIFT) +/* + * Keep 1 MB of memory free so that device drivers can allocate some pages in + * their .suspend() routines without breaking the suspend to disk. + */ +#define SPARE_PAGES ((1024 * 1024) >> PAGE_SHIFT) +extern int pm_suspend_disk(void); #else static inline int pm_suspend_disk(void) { Index: linux-2.6.21-rc6-mm1/kernel/power/swsusp.c =================================================================== --- linux-2.6.21-rc6-mm1.orig/kernel/power/swsusp.c 2007-04-21 22:37:50.000000000 +0200 +++ linux-2.6.21-rc6-mm1/kernel/power/swsusp.c 2007-04-21 23:24:44.000000000 +0200 @@ -233,7 +233,7 @@ int swsusp_shrink_memory(void) long size, highmem_size; highmem_size = count_highmem_pages(); - size = count_data_pages() + PAGES_FOR_IO; + size = count_data_pages() + PAGES_FOR_IO + SPARE_PAGES; tmp = size; size += highmem_size; for_each_zone (zone) ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC][PATCH -mm 1/2] swsusp: Free more memory 2007-04-21 22:05 ` [RFC][PATCH -mm 1/2] swsusp: Free more memory Rafael J. Wysocki @ 2007-04-21 23:31 ` Nigel Cunningham 2007-04-22 9:37 ` Rafael J. Wysocki 2007-04-22 12:55 ` Pavel Machek 1 sibling, 1 reply; 10+ messages in thread From: Nigel Cunningham @ 2007-04-21 23:31 UTC (permalink / raw) To: Rafael J. Wysocki; +Cc: pm list, Pavel Machek [-- Attachment #1.1: Type: text/plain, Size: 674 bytes --] Hi. On Sun, 2007-04-22 at 00:05 +0200, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki <rjw@sisk.pl> > > Move the definition of PAGES_FOR_IO to kernel/power/power.h and introduce > SPARE_PAGES representing the number of pages that should be freed by the > swsusp's memory shrinker in addition to PAGES_FOR_IO so that device drivers can > allocate some memory (up to 1 MB total) in their .suspend() routines without > causing the suspend to fail. 1MB is not going to be enough for people with DRI. I have a cycle on my machine recording 3510 extra pages (13 meg) allocated during the atomic copy, and I know there are others with larger numbers. Nigel [-- Attachment #1.2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 189 bytes --] [-- Attachment #2: Type: text/plain, Size: 0 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC][PATCH -mm 1/2] swsusp: Free more memory 2007-04-21 23:31 ` Nigel Cunningham @ 2007-04-22 9:37 ` Rafael J. Wysocki 2007-04-22 22:22 ` Nigel Cunningham 0 siblings, 1 reply; 10+ messages in thread From: Rafael J. Wysocki @ 2007-04-22 9:37 UTC (permalink / raw) To: nigel; +Cc: pm list, Pavel Machek On Sunday, 22 April 2007 01:31, Nigel Cunningham wrote: > Hi. > > On Sun, 2007-04-22 at 00:05 +0200, Rafael J. Wysocki wrote: > > From: Rafael J. Wysocki <rjw@sisk.pl> > > > > Move the definition of PAGES_FOR_IO to kernel/power/power.h and introduce > > SPARE_PAGES representing the number of pages that should be freed by the > > swsusp's memory shrinker in addition to PAGES_FOR_IO so that device drivers can > > allocate some memory (up to 1 MB total) in their .suspend() routines without > > causing the suspend to fail. > > 1MB is not going to be enough for people with DRI. I have a cycle on my > machine recording 3510 extra pages (13 meg) allocated during the atomic > copy, and I know there are others with larger numbers. I know. The other mechanism (ie. notifiers) is for them. The idea of this patch is to make it possible to _avoid_ using the notifiers if you need only a limited amount of memory. Greetings, Rafael ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC][PATCH -mm 1/2] swsusp: Free more memory 2007-04-22 9:37 ` Rafael J. Wysocki @ 2007-04-22 22:22 ` Nigel Cunningham 2007-04-23 19:59 ` Rafael J. Wysocki 0 siblings, 1 reply; 10+ messages in thread From: Nigel Cunningham @ 2007-04-22 22:22 UTC (permalink / raw) To: Rafael J. Wysocki; +Cc: pm list, Pavel Machek [-- Attachment #1.1: Type: text/plain, Size: 1142 bytes --] Hi. On Sun, 2007-04-22 at 11:37 +0200, Rafael J. Wysocki wrote: > On Sunday, 22 April 2007 01:31, Nigel Cunningham wrote: > > Hi. > > > > On Sun, 2007-04-22 at 00:05 +0200, Rafael J. Wysocki wrote: > > > From: Rafael J. Wysocki <rjw@sisk.pl> > > > > > > Move the definition of PAGES_FOR_IO to kernel/power/power.h and introduce > > > SPARE_PAGES representing the number of pages that should be freed by the > > > swsusp's memory shrinker in addition to PAGES_FOR_IO so that device drivers can > > > allocate some memory (up to 1 MB total) in their .suspend() routines without > > > causing the suspend to fail. > > > > 1MB is not going to be enough for people with DRI. I have a cycle on my > > machine recording 3510 extra pages (13 meg) allocated during the atomic > > copy, and I know there are others with larger numbers. > > I know. The other mechanism (ie. notifiers) is for them. > > The idea of this patch is to make it possible to _avoid_ using the notifiers > if you need only a limited amount of memory. That's fine when the notifiers are actually used, but for the moment.... Regards, Nigel [-- Attachment #1.2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 189 bytes --] [-- Attachment #2: Type: text/plain, Size: 0 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC][PATCH -mm 1/2] swsusp: Free more memory 2007-04-22 22:22 ` Nigel Cunningham @ 2007-04-23 19:59 ` Rafael J. Wysocki 0 siblings, 0 replies; 10+ messages in thread From: Rafael J. Wysocki @ 2007-04-23 19:59 UTC (permalink / raw) To: nigel; +Cc: pm list, Pavel Machek On Monday, 23 April 2007 00:22, Nigel Cunningham wrote: > Hi. > > On Sun, 2007-04-22 at 11:37 +0200, Rafael J. Wysocki wrote: > > On Sunday, 22 April 2007 01:31, Nigel Cunningham wrote: > > > Hi. > > > > > > On Sun, 2007-04-22 at 00:05 +0200, Rafael J. Wysocki wrote: > > > > From: Rafael J. Wysocki <rjw@sisk.pl> > > > > > > > > Move the definition of PAGES_FOR_IO to kernel/power/power.h and introduce > > > > SPARE_PAGES representing the number of pages that should be freed by the > > > > swsusp's memory shrinker in addition to PAGES_FOR_IO so that device drivers can > > > > allocate some memory (up to 1 MB total) in their .suspend() routines without > > > > causing the suspend to fail. > > > > > > 1MB is not going to be enough for people with DRI. I have a cycle on my > > > machine recording 3510 extra pages (13 meg) allocated during the atomic > > > copy, and I know there are others with larger numbers. > > > > I know. The other mechanism (ie. notifiers) is for them. > > > > The idea of this patch is to make it possible to _avoid_ using the notifiers > > if you need only a limited amount of memory. > > That's fine when the notifiers are actually used, but for the moment.... I know, but if I make SPARE_PAGES large enough for everyone, then no one will have any reason to use the notifiers. :-) Greetings, Rafael ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC][PATCH -mm 1/2] swsusp: Free more memory 2007-04-21 22:05 ` [RFC][PATCH -mm 1/2] swsusp: Free more memory Rafael J. Wysocki 2007-04-21 23:31 ` Nigel Cunningham @ 2007-04-22 12:55 ` Pavel Machek 1 sibling, 0 replies; 10+ messages in thread From: Pavel Machek @ 2007-04-22 12:55 UTC (permalink / raw) To: Rafael J. Wysocki; +Cc: pm list, Nigel Cunningham Hi! > Move the definition of PAGES_FOR_IO to kernel/power/power.h and introduce > SPARE_PAGES representing the number of pages that should be freed by the > swsusp's memory shrinker in addition to PAGES_FOR_IO so that device drivers can > allocate some memory (up to 1 MB total) in their .suspend() routines without > causing the suspend to fail. > > Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> ACK. 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] 10+ messages in thread
* [RFC][PATCH -mm 2/2] PM: Introduce suspend notifiers 2007-04-21 22:02 [RFC][PATCH -mm 0/2] Suspend notifiers Rafael J. Wysocki 2007-04-21 22:05 ` [RFC][PATCH -mm 1/2] swsusp: Free more memory Rafael J. Wysocki @ 2007-04-21 22:07 ` Rafael J. Wysocki 2007-04-22 13:00 ` Pavel Machek 1 sibling, 1 reply; 10+ messages in thread From: Rafael J. Wysocki @ 2007-04-21 22:07 UTC (permalink / raw) To: Pavel Machek; +Cc: pm list, Nigel Cunningham From: Rafael J. Wysocki <rjw@sisk.pl> Make it possible to register suspend notifiers so that subsystems can perform suspend-related operations which should not be carried out by device drivers' .suspend() and .resume() routines. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> --- Documentation/power/suspend-notifiers.txt | 41 ++++++++++++++++++++++++ include/linux/notifier.h | 6 +++ include/linux/suspend.h | 27 +++++++++++++-- kernel/power/Makefile | 2 - kernel/power/disk.c | 21 ++++++++++++ kernel/power/main.c | 13 +++++++ kernel/power/notify.c | 51 ++++++++++++++++++++++++++++++ kernel/power/power.h | 3 + kernel/power/user.c | 19 +++++++++++ 9 files changed, 178 insertions(+), 5 deletions(-) Index: linux-2.6.21-rc6-mm1/kernel/power/notify.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.21-rc6-mm1/kernel/power/notify.c 2007-04-21 23:24:50.000000000 +0200 @@ -0,0 +1,51 @@ +/* + * linux/kernel/power/notify.c + * + * This file contains functions used for registering and calling suspend + * notifiers that can be used by subsystems for carrying out some special + * suspend-related operations. + * + * Copyright (C) 2007 Rafael J. Wysocki <rjw@sisk.pl> + * + * This file is released under the GPLv2. + * + */ + +#include <linux/smp.h> +#include <linux/notifier.h> +#include <linux/module.h> +#include <linux/suspend.h> + +static DEFINE_MUTEX(suspend_notifier_lock); + +static RAW_NOTIFIER_HEAD(suspend_chain); + +int register_suspend_notifier(struct notifier_block *nb) +{ + int ret; + mutex_lock(&suspend_notifier_lock); + ret = raw_notifier_chain_register(&suspend_chain, nb); + mutex_unlock(&suspend_notifier_lock); + return ret; +} +EXPORT_SYMBOL(register_suspend_notifier); + +void unregister_suspend_notifier(struct notifier_block *nb) +{ + mutex_lock(&suspend_notifier_lock); + raw_notifier_chain_unregister(&suspend_chain, nb); + mutex_unlock(&suspend_notifier_lock); +} +EXPORT_SYMBOL(unregister_suspend_notifier); + +int suspend_notifier_call_chain(unsigned long val) +{ + int error = 0; + + mutex_lock(&suspend_notifier_lock); + if (raw_notifier_call_chain(&suspend_chain, val, NULL) == NOTIFY_BAD) + error = -EINVAL; + + mutex_unlock(&suspend_notifier_lock); + return error; +} Index: linux-2.6.21-rc6-mm1/include/linux/suspend.h =================================================================== --- linux-2.6.21-rc6-mm1.orig/include/linux/suspend.h 2007-04-21 23:24:44.000000000 +0200 +++ linux-2.6.21-rc6-mm1/include/linux/suspend.h 2007-04-21 23:24:50.000000000 +0200 @@ -24,15 +24,16 @@ struct pbe { extern void drain_local_pages(void); extern void mark_free_pages(struct zone *zone); -#if defined(CONFIG_PM) && defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) +#ifdef CONFIG_PM +#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) extern int pm_prepare_console(void); extern void pm_restore_console(void); #else static inline int pm_prepare_console(void) { return 0; } static inline void pm_restore_console(void) {} -#endif +#endif /* defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) */ -#if defined(CONFIG_PM) && defined(CONFIG_SOFTWARE_SUSPEND) +#ifdef CONFIG_SOFTWARE_SUSPEND /* kernel/power/swsusp.c */ extern int software_suspend(void); /* kernel/power/snapshot.c */ @@ -52,7 +53,7 @@ static inline void register_nosave_regio static inline int swsusp_page_is_forbidden(struct page *p) { return 0; } static inline void swsusp_set_page_free(struct page *p) {} static inline void swsusp_unset_page_free(struct page *p) {} -#endif /* defined(CONFIG_PM) && defined(CONFIG_SOFTWARE_SUSPEND) */ +#endif /* CONFIG_SOFTWARE_SUSPEND */ void save_processor_state(void); void restore_processor_state(void); @@ -60,4 +61,22 @@ struct saved_context; void __save_processor_state(struct saved_context *ctxt); void __restore_processor_state(struct saved_context *ctxt); +int register_suspend_notifier(struct notifier_block *nb); +void unregister_suspend_notifier(struct notifier_block *nb); + +#define suspend_notifier(fn, pri) { \ + static struct notifier_block fn##_nb = \ + { .notifier_call = fn, .priority = pri }; \ + register_suspend_notifier(&fn##_nb); \ +} +#else /* CONFIG_PM */ +static inline int register_suspend_notifier(struct notifier_block *nb) { + return 0; +} +static inline void unregister_suspend_notifier(struct notifier_block *nb) { +} + +#define suspend_notifier(fn, pri) do { (void)(fn); } while (0) +#endif + #endif /* _LINUX_SWSUSP_H */ Index: linux-2.6.21-rc6-mm1/kernel/power/Makefile =================================================================== --- linux-2.6.21-rc6-mm1.orig/kernel/power/Makefile 2007-04-21 23:24:28.000000000 +0200 +++ linux-2.6.21-rc6-mm1/kernel/power/Makefile 2007-04-21 23:24:50.000000000 +0200 @@ -3,7 +3,7 @@ ifeq ($(CONFIG_PM_DEBUG),y) EXTRA_CFLAGS += -DDEBUG endif -obj-y := main.o process.o console.o +obj-y := main.o process.o console.o notify.o obj-$(CONFIG_PM_LEGACY) += pm.o obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o disk.o snapshot.o swap.o user.o Index: linux-2.6.21-rc6-mm1/kernel/power/power.h =================================================================== --- linux-2.6.21-rc6-mm1.orig/kernel/power/power.h 2007-04-21 23:24:44.000000000 +0200 +++ linux-2.6.21-rc6-mm1/kernel/power/power.h 2007-04-21 23:24:50.000000000 +0200 @@ -170,3 +170,6 @@ extern int suspend_enter(suspend_state_t struct timeval; extern void swsusp_show_speed(struct timeval *, struct timeval *, unsigned int, char *); + +/* kernel/power/notify.c */ +extern int suspend_notifier_call_chain(unsigned long val); Index: linux-2.6.21-rc6-mm1/include/linux/notifier.h =================================================================== --- linux-2.6.21-rc6-mm1.orig/include/linux/notifier.h 2007-04-21 23:24:28.000000000 +0200 +++ linux-2.6.21-rc6-mm1/include/linux/notifier.h 2007-04-21 23:24:50.000000000 +0200 @@ -197,5 +197,11 @@ extern int __srcu_notifier_call_chain(st #define CPU_LOCK_ACQUIRE 0x0008 /* Acquire all hotcpu locks */ #define CPU_LOCK_RELEASE 0x0009 /* Release all hotcpu locks */ +#define SUSPEND_PREPARE 0x0002 /* Going to freeze tasks */ +#define SUSPEND_ENTER_PREPARE 0x0003 /* Tasks are frozen, we are suspending */ +#define SUSPEND_THAW_PREPARE 0x0004 /* Going to thaw frozen tasks */ +#define SUSPEND_FINISHED 0x0005 /* Tasks have been thawed */ +#define SUSPEND_RESTORE_PREPARE 0x0006 /* STD restore is going to happen */ + #endif /* __KERNEL__ */ #endif /* _LINUX_NOTIFIER_H */ Index: linux-2.6.21-rc6-mm1/kernel/power/disk.c =================================================================== --- linux-2.6.21-rc6-mm1.orig/kernel/power/disk.c 2007-04-21 23:24:28.000000000 +0200 +++ linux-2.6.21-rc6-mm1/kernel/power/disk.c 2007-04-21 23:24:50.000000000 +0200 @@ -114,6 +114,7 @@ static int prepare_processes(void) pm_prepare_console(); if (freeze_processes()) { error = -EBUSY; + suspend_notifier_call_chain(SUSPEND_THAW_PREPARE); unprepare_processes(); } return error; @@ -139,6 +140,10 @@ int pm_suspend_disk(void) if (error) goto Exit; + error = suspend_notifier_call_chain(SUSPEND_PREPARE); + if (error) + goto Finish; + error = prepare_processes(); if (error) goto Finish; @@ -149,6 +154,10 @@ int pm_suspend_disk(void) goto Thaw; } + error = suspend_notifier_call_chain(SUSPEND_ENTER_PREPARE); + if (error) + goto Thaw; + /* Free memory before shutting down devices. */ error = swsusp_shrink_memory(); if (error) @@ -205,8 +214,10 @@ int pm_suspend_disk(void) device_resume(); resume_console(); Thaw: + suspend_notifier_call_chain(SUSPEND_THAW_PREPARE); unprepare_processes(); Finish: + suspend_notifier_call_chain(SUSPEND_FINISHED); free_basic_memory_bitmaps(); Exit: atomic_inc(&snapshot_device_available); @@ -267,6 +278,10 @@ static int software_resume(void) if (error) goto Finish; + error = suspend_notifier_call_chain(SUSPEND_PREPARE); + if (error) + goto Done; + pr_debug("PM: Preparing processes for restore.\n"); error = prepare_processes(); if (error) { @@ -282,6 +297,10 @@ static int software_resume(void) goto Thaw; } + error = suspend_notifier_call_chain(SUSPEND_RESTORE_PREPARE); + if (error) + goto Thaw; + pr_debug("PM: Preparing devices for restore.\n"); suspend_console(); @@ -300,8 +319,10 @@ static int software_resume(void) resume_console(); Thaw: printk(KERN_ERR "PM: Restore failed, recovering.\n"); + suspend_notifier_call_chain(SUSPEND_THAW_PREPARE); unprepare_processes(); Done: + suspend_notifier_call_chain(SUSPEND_FINISHED); free_basic_memory_bitmaps(); Finish: atomic_inc(&snapshot_device_available); Index: linux-2.6.21-rc6-mm1/kernel/power/main.c =================================================================== --- linux-2.6.21-rc6-mm1.orig/kernel/power/main.c 2007-04-21 23:24:28.000000000 +0200 +++ linux-2.6.21-rc6-mm1/kernel/power/main.c 2007-04-21 23:24:50.000000000 +0200 @@ -86,11 +86,19 @@ static int suspend_prepare(suspend_state pm_prepare_console(); + error = suspend_notifier_call_chain(SUSPEND_PREPARE); + if (error) + goto Finish; + if (freeze_processes()) { error = -EAGAIN; goto Thaw; } + error = suspend_notifier_call_chain(SUSPEND_ENTER_PREPARE); + if (error) + goto Thaw; + if ((free_pages = global_page_state(NR_FREE_PAGES)) < FREE_PAGE_NUMBER) { pr_debug("PM: free some memory\n"); @@ -123,8 +131,11 @@ static int suspend_prepare(suspend_state device_resume(); resume_console(); Thaw: + suspend_notifier_call_chain(SUSPEND_THAW_PREPARE); thaw_processes(); + Finish: pm_restore_console(); + suspend_notifier_call_chain(SUSPEND_FINISHED); return error; } @@ -162,8 +173,10 @@ static void suspend_finish(suspend_state pm_finish(state); device_resume(); resume_console(); + suspend_notifier_call_chain(SUSPEND_THAW_PREPARE); thaw_processes(); pm_restore_console(); + suspend_notifier_call_chain(SUSPEND_FINISHED); } Index: linux-2.6.21-rc6-mm1/kernel/power/user.c =================================================================== --- linux-2.6.21-rc6-mm1.orig/kernel/power/user.c 2007-04-21 23:24:28.000000000 +0200 +++ linux-2.6.21-rc6-mm1/kernel/power/user.c 2007-04-21 23:24:50.000000000 +0200 @@ -148,6 +148,10 @@ static inline int snapshot_suspend(int p int error; mutex_lock(&pm_mutex); + error = suspend_notifier_call_chain(SUSPEND_ENTER_PREPARE); + if (error) + goto Finish; + /* Free memory before shutting down devices. */ error = swsusp_shrink_memory(); if (error) @@ -186,6 +190,10 @@ static inline int snapshot_restore(int p mutex_lock(&pm_mutex); pm_prepare_console(); + error = suspend_notifier_call_chain(SUSPEND_RESTORE_PREPARE); + if (error) + goto Finish; + if (platform_suspend) { error = platform_prepare(); if (error) @@ -236,7 +244,12 @@ static int snapshot_ioctl(struct inode * if (data->frozen) break; mutex_lock(&pm_mutex); + error = suspend_notifier_call_chain(SUSPEND_PREPARE); + if (error) + break; + if (freeze_processes()) { + suspend_notifier_call_chain(SUSPEND_THAW_PREPARE); thaw_processes(); error = -EBUSY; } @@ -249,7 +262,9 @@ static int snapshot_ioctl(struct inode * if (!data->frozen) break; mutex_lock(&pm_mutex); + suspend_notifier_call_chain(SUSPEND_THAW_PREPARE); thaw_processes(); + suspend_notifier_call_chain(SUSPEND_FINISHED); mutex_unlock(&pm_mutex); data->frozen = 0; break; @@ -350,6 +365,10 @@ static int snapshot_ioctl(struct inode * break; } + error = suspend_notifier_call_chain(SUSPEND_ENTER_PREPARE); + if (error) + break; + if (pm_ops->prepare) { error = pm_ops->prepare(PM_SUSPEND_MEM); if (error) Index: linux-2.6.21-rc6-mm1/Documentation/power/suspend-notifiers.txt =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.21-rc6-mm1/Documentation/power/suspend-notifiers.txt 2007-04-21 23:24:50.000000000 +0200 @@ -0,0 +1,41 @@ +Suspend notifiers + (C) 2007 Rafael J. Wysocki <rjw@sisk.pl>, GPL + +There are some operations that device drivers may want to carry out in their +.suspend() routines, but shouldn't, because they can cause a suspend to fail. +For example, a driver may want to allocate a substantial amount of memory +(like 50 MB) in .suspend(), but that shouldn't be done after the swsusp's memory +shrinker has run. Also, there may be some operations, that subsystems may want +to carry out before a suspend or after a resume, requiring the system to be +fully functional, so the drivers' .suspend() and .resume() routines are not +suitable for this purpose. + +The subsystems that have such needs can register suspend notifiers that will be +notified of the following events by the suspend core: + +SUSPEND_PREPARE the system is going to suspend, tasks will be frozen + immediately + +SUSPEND_ENTER_PREPARE tasks have been frozen, memory is going to be freed + and devices are going to be suspended + +SUSPEND_THAW_PREPARE devices have been resumed, tasks will be thawed + immediately + +SUSPEND_FINISHED the resume is complete, the system is fully functional + +SUSPEND_RESTORE_PREPARE the system is preparing to restore the swsusp's suspend + image, tasks have been frozen and devices are going to + be suspended + +It is generally assumed that whatever the notifiers do for SUSPEND_PREPARE, +should be undone for SUSPEND_FINISHED, and what is done for +SUSPEND_ENTER_PREPARE, should be undone for SUSPEND_FINISHED (eg. if memory is +allocated for SUSPEND_ENTER_PREPARE, it should be freed for SUSPEND_FINISHED). + +The suspend notifiers are defined in the usual way, but their last argument is +meaningless (it is always NULL). To register and/or unregister a suspend +notifier use the functions register_suspend_notifier() and +unregister_suspend_notifier(), respectively, defined in kernel/power/notify.c . +If you don't need to unregister the notifier, you can also use the +suspend_notifier() macro, defined in include/linux/suspend.h . ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC][PATCH -mm 2/2] PM: Introduce suspend notifiers 2007-04-21 22:07 ` [RFC][PATCH -mm 2/2] PM: Introduce suspend notifiers Rafael J. Wysocki @ 2007-04-22 13:00 ` Pavel Machek 2007-04-22 16:14 ` Rafael J. Wysocki 0 siblings, 1 reply; 10+ messages in thread From: Pavel Machek @ 2007-04-22 13:00 UTC (permalink / raw) To: Rafael J. Wysocki; +Cc: pm list, Nigel Cunningham Hi! > Index: linux-2.6.21-rc6-mm1/Documentation/power/suspend-notifiers.txt > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ linux-2.6.21-rc6-mm1/Documentation/power/suspend-notifiers.txt 2007-04-21 23:24:50.000000000 +0200 > @@ -0,0 +1,41 @@ > +Suspend notifiers > + (C) 2007 Rafael J. Wysocki <rjw@sisk.pl>, GPL > + > +There are some operations that device drivers may want to carry out in their > +.suspend() routines, but shouldn't, because they can cause a suspend to fail. > +For example, a driver may want to allocate a substantial amount of memory > +(like 50 MB) in .suspend(), but that shouldn't be done after the swsusp's memory > +shrinker has run. Also, there may be some operations, that subsystems may want > +to carry out before a suspend or after a resume, requiring the system to be > +fully functional, so the drivers' .suspend() and .resume() routines are not > +suitable for this purpose. > + > +The subsystems that have such needs can register suspend notifiers that will be > +notified of the following events by the suspend core: > + > +SUSPEND_PREPARE the system is going to suspend, tasks will be frozen > + immediately > + > +SUSPEND_ENTER_PREPARE tasks have been frozen, memory is going to be freed > + and devices are going to be suspended > + > +SUSPEND_THAW_PREPARE devices have been resumed, tasks will be thawed > + immediately > + > +SUSPEND_FINISHED the resume is complete, the system is fully functional + This hook is called even if suspend fails, so that we do not + leak memory. ? Looks ok to me. -- (english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC][PATCH -mm 2/2] PM: Introduce suspend notifiers 2007-04-22 13:00 ` Pavel Machek @ 2007-04-22 16:14 ` Rafael J. Wysocki 0 siblings, 0 replies; 10+ messages in thread From: Rafael J. Wysocki @ 2007-04-22 16:14 UTC (permalink / raw) To: Pavel Machek; +Cc: pm list, Nigel Cunningham Hi, On Sunday, 22 April 2007 15:00, Pavel Machek wrote: > Hi! > > > > Index: linux-2.6.21-rc6-mm1/Documentation/power/suspend-notifiers.txt > > =================================================================== > > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > > +++ linux-2.6.21-rc6-mm1/Documentation/power/suspend-notifiers.txt 2007-04-21 23:24:50.000000000 +0200 > > @@ -0,0 +1,41 @@ > > +Suspend notifiers > > + (C) 2007 Rafael J. Wysocki <rjw@sisk.pl>, GPL > > + > > +There are some operations that device drivers may want to carry out in their > > +.suspend() routines, but shouldn't, because they can cause a suspend to fail. > > +For example, a driver may want to allocate a substantial amount of memory > > +(like 50 MB) in .suspend(), but that shouldn't be done after the swsusp's memory > > +shrinker has run. Also, there may be some operations, that subsystems may want > > +to carry out before a suspend or after a resume, requiring the system to be > > +fully functional, so the drivers' .suspend() and .resume() routines are not > > +suitable for this purpose. > > + > > +The subsystems that have such needs can register suspend notifiers that will be > > +notified of the following events by the suspend core: > > + > > +SUSPEND_PREPARE the system is going to suspend, tasks will be frozen > > + immediately > > + > > +SUSPEND_ENTER_PREPARE tasks have been frozen, memory is going to be freed > > + and devices are going to be suspended > > + > > +SUSPEND_THAW_PREPARE devices have been resumed, tasks will be thawed > > + immediately > > + > > +SUSPEND_FINISHED the resume is complete, the system is fully functional > > + This hook is called even if suspend fails, so that we do not > + leak memory. > > > ? Yes, I'll add something like this. ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2007-04-23 19:59 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-04-21 22:02 [RFC][PATCH -mm 0/2] Suspend notifiers Rafael J. Wysocki 2007-04-21 22:05 ` [RFC][PATCH -mm 1/2] swsusp: Free more memory Rafael J. Wysocki 2007-04-21 23:31 ` Nigel Cunningham 2007-04-22 9:37 ` Rafael J. Wysocki 2007-04-22 22:22 ` Nigel Cunningham 2007-04-23 19:59 ` Rafael J. Wysocki 2007-04-22 12:55 ` Pavel Machek 2007-04-21 22:07 ` [RFC][PATCH -mm 2/2] PM: Introduce suspend notifiers Rafael J. Wysocki 2007-04-22 13:00 ` Pavel Machek 2007-04-22 16:14 ` Rafael J. Wysocki
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox