blob: 8122018d300029167518eb4a9c93e395e3efd304 [file] [log] [blame]
Dave Hansen208d54e2005-10-29 18:16:52 -07001#ifndef __LINUX_MEMORY_HOTPLUG_H
2#define __LINUX_MEMORY_HOTPLUG_H
3
4#include <linux/mmzone.h>
5#include <linux/spinlock.h>
Dave Hansen3947be12005-10-29 18:16:54 -07006#include <linux/notifier.h>
Dave Hansen208d54e2005-10-29 18:16:52 -07007
KAMEZAWA Hiroyuki78679302006-03-06 15:42:49 -08008struct page;
9struct zone;
10struct pglist_data;
Badari Pulavartyea01ea92008-04-28 02:12:01 -070011struct mem_section;
KAMEZAWA Hiroyuki78679302006-03-06 15:42:49 -080012
Dave Hansen208d54e2005-10-29 18:16:52 -070013#ifdef CONFIG_MEMORY_HOTPLUG
Yasunori Goto04753272008-04-28 02:13:31 -070014
15/*
Andrea Arcangeli5f24ce52011-01-13 15:47:00 -080016 * Types for free bootmem stored in page->lru.next. These have to be in
17 * some random range in unsigned long space for debugging purposes.
Yasunori Goto04753272008-04-28 02:13:31 -070018 */
Andrea Arcangeli5f24ce52011-01-13 15:47:00 -080019enum {
20 MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE = 12,
21 SECTION_INFO = MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE,
22 MIX_SECTION_INFO,
23 NODE_INFO,
24 MEMORY_HOTPLUG_MAX_BOOTMEM_TYPE = NODE_INFO,
25};
Yasunori Goto04753272008-04-28 02:13:31 -070026
Dave Hansen208d54e2005-10-29 18:16:52 -070027/*
28 * pgdat resizing functions
29 */
30static inline
31void pgdat_resize_lock(struct pglist_data *pgdat, unsigned long *flags)
32{
33 spin_lock_irqsave(&pgdat->node_size_lock, *flags);
34}
35static inline
36void pgdat_resize_unlock(struct pglist_data *pgdat, unsigned long *flags)
37{
Dave Hansenbdc8cb92005-10-29 18:16:53 -070038 spin_unlock_irqrestore(&pgdat->node_size_lock, *flags);
Dave Hansen208d54e2005-10-29 18:16:52 -070039}
40static inline
41void pgdat_resize_init(struct pglist_data *pgdat)
42{
43 spin_lock_init(&pgdat->node_size_lock);
44}
Dave Hansenbdc8cb92005-10-29 18:16:53 -070045/*
46 * Zone resizing functions
47 */
48static inline unsigned zone_span_seqbegin(struct zone *zone)
49{
50 return read_seqbegin(&zone->span_seqlock);
51}
52static inline int zone_span_seqretry(struct zone *zone, unsigned iv)
53{
54 return read_seqretry(&zone->span_seqlock, iv);
55}
56static inline void zone_span_writelock(struct zone *zone)
57{
58 write_seqlock(&zone->span_seqlock);
59}
60static inline void zone_span_writeunlock(struct zone *zone)
61{
62 write_sequnlock(&zone->span_seqlock);
63}
64static inline void zone_seqlock_init(struct zone *zone)
65{
66 seqlock_init(&zone->span_seqlock);
67}
Dave Hansen3947be12005-10-29 18:16:54 -070068extern int zone_grow_free_lists(struct zone *zone, unsigned long new_nr_pages);
69extern int zone_grow_waitqueues(struct zone *zone, unsigned long nr_pages);
70extern int add_one_highpage(struct page *page, int pfn, int bad_ppro);
71/* need some defines for these for archs that don't support it */
72extern void online_page(struct page *page);
73/* VM interface that may be used by firmware interface */
Dave Hansen3947be12005-10-29 18:16:54 -070074extern int online_pages(unsigned long, unsigned long);
KAMEZAWA Hiroyuki0c0e6192007-10-16 01:26:12 -070075extern void __offline_isolated_pages(unsigned long, unsigned long);
KAMEZAWA Hiroyuki48e94192007-10-16 01:26:14 -070076
KAMEZAWA Hiroyuki49ac8252010-10-26 14:21:30 -070077#ifdef CONFIG_MEMORY_HOTREMOVE
78extern bool is_pageblock_removable_nolock(struct page *page);
79#endif /* CONFIG_MEMORY_HOTREMOVE */
80
Dave Hansen3947be12005-10-29 18:16:54 -070081/* reasonably generic interface to expand the physical pages in a zone */
Gary Hadec04fc582009-01-06 14:39:14 -080082extern int __add_pages(int nid, struct zone *zone, unsigned long start_pfn,
Dave Hansen3947be12005-10-29 18:16:54 -070083 unsigned long nr_pages);
Badari Pulavartyea01ea92008-04-28 02:12:01 -070084extern int __remove_pages(struct zone *zone, unsigned long start_pfn,
85 unsigned long nr_pages);
Yasunori Gotobc02af92006-06-27 02:53:30 -070086
87#ifdef CONFIG_NUMA
88extern int memory_add_physaddr_to_nid(u64 start);
89#else
90static inline int memory_add_physaddr_to_nid(u64 start)
91{
92 return 0;
93}
94#endif
95
Yasunori Goto306d6cb2006-06-27 02:53:32 -070096#ifdef CONFIG_HAVE_ARCH_NODEDATA_EXTENSION
97/*
98 * For supporting node-hotadd, we have to allocate a new pgdat.
99 *
100 * If an arch has generic style NODE_DATA(),
101 * node_data[nid] = kzalloc() works well. But it depends on the architecture.
102 *
103 * In general, generic_alloc_nodedata() is used.
104 * Now, arch_free_nodedata() is just defined for error path of node_hot_add.
105 *
106 */
Yasunori Gotodd0932d2006-06-27 02:53:40 -0700107extern pg_data_t *arch_alloc_nodedata(int nid);
108extern void arch_free_nodedata(pg_data_t *pgdat);
Yasunori Goto70490272006-06-27 02:53:39 -0700109extern void arch_refresh_nodedata(int nid, pg_data_t *pgdat);
Yasunori Goto306d6cb2006-06-27 02:53:32 -0700110
111#else /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */
112
113#define arch_alloc_nodedata(nid) generic_alloc_nodedata(nid)
114#define arch_free_nodedata(pgdat) generic_free_nodedata(pgdat)
115
116#ifdef CONFIG_NUMA
117/*
118 * If ARCH_HAS_NODEDATA_EXTENSION=n, this func is used to allocate pgdat.
119 * XXX: kmalloc_node() can't work well to get new node's memory at this time.
120 * Because, pgdat for the new node is not allocated/initialized yet itself.
121 * To use new node's memory, more consideration will be necessary.
122 */
123#define generic_alloc_nodedata(nid) \
124({ \
125 kzalloc(sizeof(pg_data_t), GFP_KERNEL); \
126})
127/*
128 * This definition is just for error path in node hotadd.
129 * For node hotremove, we have to replace this.
130 */
131#define generic_free_nodedata(pgdat) kfree(pgdat)
132
Yasunori Goto10ad4002006-06-27 02:53:33 -0700133extern pg_data_t *node_data[];
134static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat)
135{
136 node_data[nid] = pgdat;
137}
138
Yasunori Goto306d6cb2006-06-27 02:53:32 -0700139#else /* !CONFIG_NUMA */
140
141/* never called */
142static inline pg_data_t *generic_alloc_nodedata(int nid)
143{
144 BUG();
145 return NULL;
146}
147static inline void generic_free_nodedata(pg_data_t *pgdat)
148{
149}
Yasunori Goto10ad4002006-06-27 02:53:33 -0700150static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat)
151{
152}
Yasunori Goto306d6cb2006-06-27 02:53:32 -0700153#endif /* CONFIG_NUMA */
154#endif /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */
155
Yasunori Goto04753272008-04-28 02:13:31 -0700156#ifdef CONFIG_SPARSEMEM_VMEMMAP
157static inline void register_page_bootmem_info_node(struct pglist_data *pgdat)
158{
159}
160static inline void put_page_bootmem(struct page *page)
161{
162}
163#else
164extern void register_page_bootmem_info_node(struct pglist_data *pgdat);
165extern void put_page_bootmem(struct page *page);
166#endif
167
KAMEZAWA Hiroyuki925268a2011-01-11 16:44:01 +0900168/*
169 * Lock for memory hotplug guarantees 1) all callbacks for memory hotplug
170 * notifier will be called under this. 2) offline/online/add/remove memory
171 * will not run simultaneously.
172 */
173
KOSAKI Motohiro20d6c962010-12-02 14:31:19 -0800174void lock_memory_hotplug(void);
175void unlock_memory_hotplug(void);
176
Dave Hansen208d54e2005-10-29 18:16:52 -0700177#else /* ! CONFIG_MEMORY_HOTPLUG */
178/*
179 * Stub functions for when hotplug is off
180 */
181static inline void pgdat_resize_lock(struct pglist_data *p, unsigned long *f) {}
182static inline void pgdat_resize_unlock(struct pglist_data *p, unsigned long *f) {}
183static inline void pgdat_resize_init(struct pglist_data *pgdat) {}
Dave Hansenbdc8cb92005-10-29 18:16:53 -0700184
185static inline unsigned zone_span_seqbegin(struct zone *zone)
186{
187 return 0;
188}
189static inline int zone_span_seqretry(struct zone *zone, unsigned iv)
190{
191 return 0;
192}
193static inline void zone_span_writelock(struct zone *zone) {}
194static inline void zone_span_writeunlock(struct zone *zone) {}
195static inline void zone_seqlock_init(struct zone *zone) {}
Dave Hansen3947be12005-10-29 18:16:54 -0700196
197static inline int mhp_notimplemented(const char *func)
198{
199 printk(KERN_WARNING "%s() called, with CONFIG_MEMORY_HOTPLUG disabled\n", func);
200 dump_stack();
201 return -ENOSYS;
202}
203
Yasunori Goto04753272008-04-28 02:13:31 -0700204static inline void register_page_bootmem_info_node(struct pglist_data *pgdat)
205{
206}
207
KOSAKI Motohiro20d6c962010-12-02 14:31:19 -0800208static inline void lock_memory_hotplug(void) {}
209static inline void unlock_memory_hotplug(void) {}
210
Dave Hansenbdc8cb92005-10-29 18:16:53 -0700211#endif /* ! CONFIG_MEMORY_HOTPLUG */
Andi Kleen9d99aaa2006-04-07 19:49:15 +0200212
Badari Pulavarty5c755e92008-07-23 21:28:19 -0700213#ifdef CONFIG_MEMORY_HOTREMOVE
214
215extern int is_mem_section_removable(unsigned long pfn, unsigned long nr_pages);
216
217#else
218static inline int is_mem_section_removable(unsigned long pfn,
219 unsigned long nr_pages)
220{
221 return 0;
222}
223#endif /* CONFIG_MEMORY_HOTREMOVE */
224
minskey guocf234222010-05-24 14:32:41 -0700225extern int mem_online_node(int nid);
Yasunori Gotobc02af92006-06-27 02:53:30 -0700226extern int add_memory(int nid, u64 start, u64 size);
227extern int arch_add_memory(int nid, u64 start, u64 size);
Andi Kleen9d99aaa2006-04-07 19:49:15 +0200228extern int remove_memory(u64 start, u64 size);
Keith Manntheyf28c5ed2006-09-30 23:27:04 -0700229extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
230 int nr_pages);
Badari Pulavartyea01ea92008-04-28 02:12:01 -0700231extern void sparse_remove_one_section(struct zone *zone, struct mem_section *ms);
Yasunori Goto04753272008-04-28 02:13:31 -0700232extern struct page *sparse_decode_mem_map(unsigned long coded_mem_map,
233 unsigned long pnum);
Andi Kleen9d99aaa2006-04-07 19:49:15 +0200234
Dave Hansen208d54e2005-10-29 18:16:52 -0700235#endif /* __LINUX_MEMORY_HOTPLUG_H */