diff options
-rw-r--r-- | include/linux/suspend.h | 21 | ||||
-rw-r--r-- | mm/Kconfig | 5 | ||||
-rw-r--r-- | mm/memory_hotplug.c | 21 |
3 files changed, 37 insertions, 10 deletions
diff --git a/include/linux/suspend.h b/include/linux/suspend.h index cd15df6c63cd..5e781d824e6d 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h | |||
@@ -301,6 +301,8 @@ static inline int unregister_pm_notifier(struct notifier_block *nb) | |||
301 | #define pm_notifier(fn, pri) do { (void)(fn); } while (0) | 301 | #define pm_notifier(fn, pri) do { (void)(fn); } while (0) |
302 | #endif /* !CONFIG_PM_SLEEP */ | 302 | #endif /* !CONFIG_PM_SLEEP */ |
303 | 303 | ||
304 | extern struct mutex pm_mutex; | ||
305 | |||
304 | #ifndef CONFIG_HIBERNATION | 306 | #ifndef CONFIG_HIBERNATION |
305 | static inline void register_nosave_region(unsigned long b, unsigned long e) | 307 | static inline void register_nosave_region(unsigned long b, unsigned long e) |
306 | { | 308 | { |
@@ -308,8 +310,23 @@ static inline void register_nosave_region(unsigned long b, unsigned long e) | |||
308 | static inline void register_nosave_region_late(unsigned long b, unsigned long e) | 310 | static inline void register_nosave_region_late(unsigned long b, unsigned long e) |
309 | { | 311 | { |
310 | } | 312 | } |
311 | #endif | ||
312 | 313 | ||
313 | extern struct mutex pm_mutex; | 314 | static inline void lock_system_sleep(void) {} |
315 | static inline void unlock_system_sleep(void) {} | ||
316 | |||
317 | #else | ||
318 | |||
319 | /* Let some subsystems like memory hotadd exclude hibernation */ | ||
320 | |||
321 | static inline void lock_system_sleep(void) | ||
322 | { | ||
323 | mutex_lock(&pm_mutex); | ||
324 | } | ||
325 | |||
326 | static inline void unlock_system_sleep(void) | ||
327 | { | ||
328 | mutex_unlock(&pm_mutex); | ||
329 | } | ||
330 | #endif | ||
314 | 331 | ||
315 | #endif /* _LINUX_SUSPEND_H */ | 332 | #endif /* _LINUX_SUSPEND_H */ |
diff --git a/mm/Kconfig b/mm/Kconfig index fd3386242cf0..44cf6f0a3a6d 100644 --- a/mm/Kconfig +++ b/mm/Kconfig | |||
@@ -128,12 +128,9 @@ config SPARSEMEM_VMEMMAP | |||
128 | config MEMORY_HOTPLUG | 128 | config MEMORY_HOTPLUG |
129 | bool "Allow for memory hot-add" | 129 | bool "Allow for memory hot-add" |
130 | depends on SPARSEMEM || X86_64_ACPI_NUMA | 130 | depends on SPARSEMEM || X86_64_ACPI_NUMA |
131 | depends on HOTPLUG && !(HIBERNATION && !S390) && ARCH_ENABLE_MEMORY_HOTPLUG | 131 | depends on HOTPLUG && ARCH_ENABLE_MEMORY_HOTPLUG |
132 | depends on (IA64 || X86 || PPC_BOOK3S_64 || SUPERH || S390) | 132 | depends on (IA64 || X86 || PPC_BOOK3S_64 || SUPERH || S390) |
133 | 133 | ||
134 | comment "Memory hotplug is currently incompatible with Software Suspend" | ||
135 | depends on SPARSEMEM && HOTPLUG && HIBERNATION && !S390 | ||
136 | |||
137 | config MEMORY_HOTPLUG_SPARSE | 134 | config MEMORY_HOTPLUG_SPARSE |
138 | def_bool y | 135 | def_bool y |
139 | depends on SPARSEMEM && MEMORY_HOTPLUG | 136 | depends on SPARSEMEM && MEMORY_HOTPLUG |
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 380aef45c2cf..2047465cd27c 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/migrate.h> | 26 | #include <linux/migrate.h> |
27 | #include <linux/page-isolation.h> | 27 | #include <linux/page-isolation.h> |
28 | #include <linux/pfn.h> | 28 | #include <linux/pfn.h> |
29 | #include <linux/suspend.h> | ||
29 | 30 | ||
30 | #include <asm/tlbflush.h> | 31 | #include <asm/tlbflush.h> |
31 | 32 | ||
@@ -485,14 +486,18 @@ int __ref add_memory(int nid, u64 start, u64 size) | |||
485 | struct resource *res; | 486 | struct resource *res; |
486 | int ret; | 487 | int ret; |
487 | 488 | ||
489 | lock_system_sleep(); | ||
490 | |||
488 | res = register_memory_resource(start, size); | 491 | res = register_memory_resource(start, size); |
492 | ret = -EEXIST; | ||
489 | if (!res) | 493 | if (!res) |
490 | return -EEXIST; | 494 | goto out; |
491 | 495 | ||
492 | if (!node_online(nid)) { | 496 | if (!node_online(nid)) { |
493 | pgdat = hotadd_new_pgdat(nid, start); | 497 | pgdat = hotadd_new_pgdat(nid, start); |
498 | ret = -ENOMEM; | ||
494 | if (!pgdat) | 499 | if (!pgdat) |
495 | return -ENOMEM; | 500 | goto out; |
496 | new_pgdat = 1; | 501 | new_pgdat = 1; |
497 | } | 502 | } |
498 | 503 | ||
@@ -515,7 +520,8 @@ int __ref add_memory(int nid, u64 start, u64 size) | |||
515 | BUG_ON(ret); | 520 | BUG_ON(ret); |
516 | } | 521 | } |
517 | 522 | ||
518 | return ret; | 523 | goto out; |
524 | |||
519 | error: | 525 | error: |
520 | /* rollback pgdat allocation and others */ | 526 | /* rollback pgdat allocation and others */ |
521 | if (new_pgdat) | 527 | if (new_pgdat) |
@@ -523,6 +529,8 @@ error: | |||
523 | if (res) | 529 | if (res) |
524 | release_memory_resource(res); | 530 | release_memory_resource(res); |
525 | 531 | ||
532 | out: | ||
533 | unlock_system_sleep(); | ||
526 | return ret; | 534 | return ret; |
527 | } | 535 | } |
528 | EXPORT_SYMBOL_GPL(add_memory); | 536 | EXPORT_SYMBOL_GPL(add_memory); |
@@ -759,6 +767,8 @@ int offline_pages(unsigned long start_pfn, | |||
759 | if (!test_pages_in_a_zone(start_pfn, end_pfn)) | 767 | if (!test_pages_in_a_zone(start_pfn, end_pfn)) |
760 | return -EINVAL; | 768 | return -EINVAL; |
761 | 769 | ||
770 | lock_system_sleep(); | ||
771 | |||
762 | zone = page_zone(pfn_to_page(start_pfn)); | 772 | zone = page_zone(pfn_to_page(start_pfn)); |
763 | node = zone_to_nid(zone); | 773 | node = zone_to_nid(zone); |
764 | nr_pages = end_pfn - start_pfn; | 774 | nr_pages = end_pfn - start_pfn; |
@@ -766,7 +776,7 @@ int offline_pages(unsigned long start_pfn, | |||
766 | /* set above range as isolated */ | 776 | /* set above range as isolated */ |
767 | ret = start_isolate_page_range(start_pfn, end_pfn); | 777 | ret = start_isolate_page_range(start_pfn, end_pfn); |
768 | if (ret) | 778 | if (ret) |
769 | return ret; | 779 | goto out; |
770 | 780 | ||
771 | arg.start_pfn = start_pfn; | 781 | arg.start_pfn = start_pfn; |
772 | arg.nr_pages = nr_pages; | 782 | arg.nr_pages = nr_pages; |
@@ -844,6 +854,7 @@ repeat: | |||
844 | writeback_set_ratelimit(); | 854 | writeback_set_ratelimit(); |
845 | 855 | ||
846 | memory_notify(MEM_OFFLINE, &arg); | 856 | memory_notify(MEM_OFFLINE, &arg); |
857 | unlock_system_sleep(); | ||
847 | return 0; | 858 | return 0; |
848 | 859 | ||
849 | failed_removal: | 860 | failed_removal: |
@@ -853,6 +864,8 @@ failed_removal: | |||
853 | /* pushback to free area */ | 864 | /* pushback to free area */ |
854 | undo_isolate_page_range(start_pfn, end_pfn); | 865 | undo_isolate_page_range(start_pfn, end_pfn); |
855 | 866 | ||
867 | out: | ||
868 | unlock_system_sleep(); | ||
856 | return ret; | 869 | return ret; |
857 | } | 870 | } |
858 | 871 | ||