linux/include/linux/memory_hotplug.h
<<
>>
Prefs
   1#ifndef __LINUX_MEMORY_HOTPLUG_H
   2#define __LINUX_MEMORY_HOTPLUG_H
   3
   4#include <linux/mmzone.h>
   5#include <linux/spinlock.h>
   6#include <linux/notifier.h>
   7#include <linux/bug.h>
   8
   9struct page;
  10struct zone;
  11struct pglist_data;
  12struct mem_section;
  13struct memory_block;
  14struct resource;
  15
  16#ifdef CONFIG_MEMORY_HOTPLUG
  17
  18/*
  19 * Types for free bootmem stored in page->lru.next. These have to be in
  20 * some random range in unsigned long space for debugging purposes.
  21 */
  22enum {
  23        MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE = 12,
  24        SECTION_INFO = MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE,
  25        MIX_SECTION_INFO,
  26        NODE_INFO,
  27        MEMORY_HOTPLUG_MAX_BOOTMEM_TYPE = NODE_INFO,
  28};
  29
  30/* Types for control the zone type of onlined and offlined memory */
  31enum {
  32        MMOP_OFFLINE = -1,
  33        MMOP_ONLINE_KEEP,
  34        MMOP_ONLINE_KERNEL,
  35        MMOP_ONLINE_MOVABLE,
  36};
  37
  38/*
  39 * pgdat resizing functions
  40 */
  41static inline
  42void pgdat_resize_lock(struct pglist_data *pgdat, unsigned long *flags)
  43{
  44        spin_lock_irqsave(&pgdat->node_size_lock, *flags);
  45}
  46static inline
  47void pgdat_resize_unlock(struct pglist_data *pgdat, unsigned long *flags)
  48{
  49        spin_unlock_irqrestore(&pgdat->node_size_lock, *flags);
  50}
  51static inline
  52void pgdat_resize_init(struct pglist_data *pgdat)
  53{
  54        spin_lock_init(&pgdat->node_size_lock);
  55}
  56/*
  57 * Zone resizing functions
  58 *
  59 * Note: any attempt to resize a zone should has pgdat_resize_lock()
  60 * zone_span_writelock() both held. This ensure the size of a zone
  61 * can't be changed while pgdat_resize_lock() held.
  62 */
  63static inline unsigned zone_span_seqbegin(struct zone *zone)
  64{
  65        return read_seqbegin(&zone->span_seqlock);
  66}
  67static inline int zone_span_seqretry(struct zone *zone, unsigned iv)
  68{
  69        return read_seqretry(&zone->span_seqlock, iv);
  70}
  71static inline void zone_span_writelock(struct zone *zone)
  72{
  73        write_seqlock(&zone->span_seqlock);
  74}
  75static inline void zone_span_writeunlock(struct zone *zone)
  76{
  77        write_sequnlock(&zone->span_seqlock);
  78}
  79static inline void zone_seqlock_init(struct zone *zone)
  80{
  81        seqlock_init(&zone->span_seqlock);
  82}
  83extern int zone_grow_free_lists(struct zone *zone, unsigned long new_nr_pages);
  84extern int zone_grow_waitqueues(struct zone *zone, unsigned long nr_pages);
  85extern int add_one_highpage(struct page *page, int pfn, int bad_ppro);
  86/* VM interface that may be used by firmware interface */
  87extern int online_pages(unsigned long, unsigned long, int);
  88extern int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
  89        unsigned long *valid_start, unsigned long *valid_end);
  90extern void __offline_isolated_pages(unsigned long, unsigned long);
  91
  92typedef void (*online_page_callback_t)(struct page *page);
  93
  94extern int set_online_page_callback(online_page_callback_t callback);
  95extern int restore_online_page_callback(online_page_callback_t callback);
  96
  97extern void __online_page_set_limits(struct page *page);
  98extern void __online_page_increment_counters(struct page *page);
  99extern void __online_page_free(struct page *page);
 100
 101extern int try_online_node(int nid);
 102
 103extern bool memhp_auto_online;
 104
 105#ifdef CONFIG_MEMORY_HOTREMOVE
 106extern bool is_pageblock_removable_nolock(struct page *page);
 107extern int arch_remove_memory(u64 start, u64 size);
 108extern int __remove_pages(struct zone *zone, unsigned long start_pfn,
 109        unsigned long nr_pages);
 110#endif /* CONFIG_MEMORY_HOTREMOVE */
 111
 112/* reasonably generic interface to expand the physical pages in a zone  */
 113extern int __add_pages(int nid, struct zone *zone, unsigned long start_pfn,
 114        unsigned long nr_pages);
 115
 116#ifdef CONFIG_NUMA
 117extern int memory_add_physaddr_to_nid(u64 start);
 118#else
 119static inline int memory_add_physaddr_to_nid(u64 start)
 120{
 121        return 0;
 122}
 123#endif
 124
 125#ifdef CONFIG_HAVE_ARCH_NODEDATA_EXTENSION
 126/*
 127 * For supporting node-hotadd, we have to allocate a new pgdat.
 128 *
 129 * If an arch has generic style NODE_DATA(),
 130 * node_data[nid] = kzalloc() works well. But it depends on the architecture.
 131 *
 132 * In general, generic_alloc_nodedata() is used.
 133 * Now, arch_free_nodedata() is just defined for error path of node_hot_add.
 134 *
 135 */
 136extern pg_data_t *arch_alloc_nodedata(int nid);
 137extern void arch_free_nodedata(pg_data_t *pgdat);
 138extern void arch_refresh_nodedata(int nid, pg_data_t *pgdat);
 139
 140#else /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */
 141
 142#define arch_alloc_nodedata(nid)        generic_alloc_nodedata(nid)
 143#define arch_free_nodedata(pgdat)       generic_free_nodedata(pgdat)
 144
 145#ifdef CONFIG_NUMA
 146/*
 147 * If ARCH_HAS_NODEDATA_EXTENSION=n, this func is used to allocate pgdat.
 148 * XXX: kmalloc_node() can't work well to get new node's memory at this time.
 149 *      Because, pgdat for the new node is not allocated/initialized yet itself.
 150 *      To use new node's memory, more consideration will be necessary.
 151 */
 152#define generic_alloc_nodedata(nid)                             \
 153({                                                              \
 154        kzalloc(sizeof(pg_data_t), GFP_KERNEL);                 \
 155})
 156/*
 157 * This definition is just for error path in node hotadd.
 158 * For node hotremove, we have to replace this.
 159 */
 160#define generic_free_nodedata(pgdat)    kfree(pgdat)
 161
 162extern pg_data_t *node_data[];
 163static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat)
 164{
 165        node_data[nid] = pgdat;
 166}
 167
 168#else /* !CONFIG_NUMA */
 169
 170/* never called */
 171static inline pg_data_t *generic_alloc_nodedata(int nid)
 172{
 173        BUG();
 174        return NULL;
 175}
 176static inline void generic_free_nodedata(pg_data_t *pgdat)
 177{
 178}
 179static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat)
 180{
 181}
 182#endif /* CONFIG_NUMA */
 183#endif /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */
 184
 185#ifdef CONFIG_HAVE_BOOTMEM_INFO_NODE
 186extern void __init register_page_bootmem_info_node(struct pglist_data *pgdat);
 187#else
 188static inline void register_page_bootmem_info_node(struct pglist_data *pgdat)
 189{
 190}
 191#endif
 192extern void put_page_bootmem(struct page *page);
 193extern void get_page_bootmem(unsigned long ingo, struct page *page,
 194                             unsigned long type);
 195
 196void get_online_mems(void);
 197void put_online_mems(void);
 198
 199void mem_hotplug_begin(void);
 200void mem_hotplug_done(void);
 201
 202extern void set_zone_contiguous(struct zone *zone);
 203extern void clear_zone_contiguous(struct zone *zone);
 204
 205#else /* ! CONFIG_MEMORY_HOTPLUG */
 206/*
 207 * Stub functions for when hotplug is off
 208 */
 209static inline void pgdat_resize_lock(struct pglist_data *p, unsigned long *f) {}
 210static inline void pgdat_resize_unlock(struct pglist_data *p, unsigned long *f) {}
 211static inline void pgdat_resize_init(struct pglist_data *pgdat) {}
 212
 213static inline unsigned zone_span_seqbegin(struct zone *zone)
 214{
 215        return 0;
 216}
 217static inline int zone_span_seqretry(struct zone *zone, unsigned iv)
 218{
 219        return 0;
 220}
 221static inline void zone_span_writelock(struct zone *zone) {}
 222static inline void zone_span_writeunlock(struct zone *zone) {}
 223static inline void zone_seqlock_init(struct zone *zone) {}
 224
 225static inline int mhp_notimplemented(const char *func)
 226{
 227        printk(KERN_WARNING "%s() called, with CONFIG_MEMORY_HOTPLUG disabled\n", func);
 228        dump_stack();
 229        return -ENOSYS;
 230}
 231
 232static inline void register_page_bootmem_info_node(struct pglist_data *pgdat)
 233{
 234}
 235
 236static inline int try_online_node(int nid)
 237{
 238        return 0;
 239}
 240
 241static inline void get_online_mems(void) {}
 242static inline void put_online_mems(void) {}
 243
 244static inline void mem_hotplug_begin(void) {}
 245static inline void mem_hotplug_done(void) {}
 246
 247#endif /* ! CONFIG_MEMORY_HOTPLUG */
 248
 249#ifdef CONFIG_MEMORY_HOTREMOVE
 250
 251extern bool is_mem_section_removable(unsigned long pfn, unsigned long nr_pages);
 252extern void try_offline_node(int nid);
 253extern int offline_pages(unsigned long start_pfn, unsigned long nr_pages);
 254extern void remove_memory(int nid, u64 start, u64 size);
 255
 256#else
 257static inline bool is_mem_section_removable(unsigned long pfn,
 258                                        unsigned long nr_pages)
 259{
 260        return false;
 261}
 262
 263static inline void try_offline_node(int nid) {}
 264
 265static inline int offline_pages(unsigned long start_pfn, unsigned long nr_pages)
 266{
 267        return -EINVAL;
 268}
 269
 270static inline void remove_memory(int nid, u64 start, u64 size) {}
 271#endif /* CONFIG_MEMORY_HOTREMOVE */
 272
 273extern int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn,
 274                void *arg, int (*func)(struct memory_block *, void *));
 275extern int add_memory(int nid, u64 start, u64 size);
 276extern int add_memory_resource(int nid, struct resource *resource, bool online);
 277extern int zone_for_memory(int nid, u64 start, u64 size, int zone_default,
 278                bool for_device);
 279extern int arch_add_memory(int nid, u64 start, u64 size, bool for_device);
 280extern int offline_pages(unsigned long start_pfn, unsigned long nr_pages);
 281extern bool is_memblock_offlined(struct memory_block *mem);
 282extern void remove_memory(int nid, u64 start, u64 size);
 283extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn);
 284extern void sparse_remove_one_section(struct zone *zone, struct mem_section *ms,
 285                unsigned long map_offset);
 286extern struct page *sparse_decode_mem_map(unsigned long coded_mem_map,
 287                                          unsigned long pnum);
 288extern bool zone_can_shift(unsigned long pfn, unsigned long nr_pages,
 289                          enum zone_type target, int *zone_shift);
 290
 291#endif /* __LINUX_MEMORY_HOTPLUG_H */
 292