aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/suspend.h21
-rw-r--r--mm/Kconfig5
-rw-r--r--mm/memory_hotplug.c21
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
304extern struct mutex pm_mutex;
305
304#ifndef CONFIG_HIBERNATION 306#ifndef CONFIG_HIBERNATION
305static inline void register_nosave_region(unsigned long b, unsigned long e) 307static 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)
308static inline void register_nosave_region_late(unsigned long b, unsigned long e) 310static inline void register_nosave_region_late(unsigned long b, unsigned long e)
309{ 311{
310} 312}
311#endif
312 313
313extern struct mutex pm_mutex; 314static inline void lock_system_sleep(void) {}
315static inline void unlock_system_sleep(void) {}
316
317#else
318
319/* Let some subsystems like memory hotadd exclude hibernation */
320
321static inline void lock_system_sleep(void)
322{
323 mutex_lock(&pm_mutex);
324}
325
326static 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
128config MEMORY_HOTPLUG 128config 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
134comment "Memory hotplug is currently incompatible with Software Suspend"
135 depends on SPARSEMEM && HOTPLUG && HIBERNATION && !S390
136
137config MEMORY_HOTPLUG_SPARSE 134config 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
519error: 525error:
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
532out:
533 unlock_system_sleep();
526 return ret; 534 return ret;
527} 535}
528EXPORT_SYMBOL_GPL(add_memory); 536EXPORT_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
849failed_removal: 860failed_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
867out:
868 unlock_system_sleep();
856 return ret; 869 return ret;
857} 870}
858 871