Merge x86-64 update from Andi
[powerpc.git] / include / linux / mmzone.h
index 5ed471b..2c8edad 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/threads.h>
 #include <linux/numa.h>
 #include <linux/init.h>
+#include <linux/seqlock.h>
 #include <asm/atomic.h>
 
 /* Free memory management - zoned buddy allocator.  */
@@ -70,10 +71,11 @@ struct per_cpu_pageset {
 #endif
 
 #define ZONE_DMA               0
-#define ZONE_NORMAL            1
-#define ZONE_HIGHMEM           2
+#define ZONE_DMA32             1
+#define ZONE_NORMAL            2
+#define ZONE_HIGHMEM           3
 
-#define MAX_NR_ZONES           3       /* Sync this with ZONES_SHIFT */
+#define MAX_NR_ZONES           4       /* Sync this with ZONES_SHIFT */
 #define ZONES_SHIFT            2       /* ceil(log2(MAX_NR_ZONES)) */
 
 
@@ -107,9 +109,10 @@ struct per_cpu_pageset {
 
 /*
  * On machines where it is needed (eg PCs) we divide physical memory
- * into multiple physical zones. On a PC we have 3 zones:
+ * into multiple physical zones. On a PC we have 4 zones:
  *
  * ZONE_DMA      < 16 MB       ISA DMA capable memory
+ * ZONE_DMA32       0 MB       Empty
  * ZONE_NORMAL 16-896 MB       direct mapped by the kernel
  * ZONE_HIGHMEM         > 896 MB       only page cache and user processes
  */
@@ -137,6 +140,10 @@ struct zone {
         * free areas of different sizes
         */
        spinlock_t              lock;
+#ifdef CONFIG_MEMORY_HOTPLUG
+       /* see spanned/present_pages for more description */
+       seqlock_t               span_seqlock;
+#endif
        struct free_area        free_area[MAX_ORDER];
 
 
@@ -220,6 +227,16 @@ struct zone {
        /* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */
        unsigned long           zone_start_pfn;
 
+       /*
+        * zone_start_pfn, spanned_pages and present_pages are all
+        * protected by span_seqlock.  It is a seqlock because it has
+        * to be read outside of zone->lock, and it is done in the main
+        * allocator path.  But, it is written quite infrequently.
+        *
+        * The lock is declared along with zone->lock because it is
+        * frequently read in proximity to zone->lock.  It's good to
+        * give them a chance of being in the same cacheline.
+        */
        unsigned long           spanned_pages;  /* total size, including holes */
        unsigned long           present_pages;  /* amount of memory (excluding holes) */
 
@@ -273,6 +290,16 @@ typedef struct pglist_data {
        struct page *node_mem_map;
 #endif
        struct bootmem_data *bdata;
+#ifdef CONFIG_MEMORY_HOTPLUG
+       /*
+        * Must be held any time you expect node_start_pfn, node_present_pages
+        * or node_spanned_pages stay constant.  Holding this will also
+        * guarantee that any pfn_valid() stays that way.
+        *
+        * Nests above zone->lock and zone->size_seqlock.
+        */
+       spinlock_t node_size_lock;
+#endif
        unsigned long node_start_pfn;
        unsigned long node_present_pages; /* total number of physical pages */
        unsigned long node_spanned_pages; /* total size of physical page
@@ -293,6 +320,8 @@ typedef struct pglist_data {
 #endif
 #define nid_page_nr(nid, pagenr)       pgdat_page_nr(NODE_DATA(nid),(pagenr))
 
+#include <linux/memory_hotplug.h>
+
 extern struct pglist_data *pgdat_list;
 
 void __get_zone_counts(unsigned long *active, unsigned long *inactive,
@@ -302,7 +331,7 @@ void get_zone_counts(unsigned long *active, unsigned long *inactive,
 void build_all_zonelists(void);
 void wakeup_kswapd(struct zone *zone, int order);
 int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
-               int alloc_type, int can_try_harder, int gfp_high);
+               int classzone_idx, int alloc_flags);
 
 #ifdef CONFIG_HAVE_MEMORY_PRESENT
 void memory_present(int nid, unsigned long start, unsigned long end);
@@ -406,7 +435,9 @@ int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *, int, struct file *,
 
 #include <linux/topology.h>
 /* Returns the number of the current Node. */
+#ifndef numa_node_id
 #define numa_node_id()         (cpu_to_node(raw_smp_processor_id()))
+#endif
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES
 
@@ -426,12 +457,12 @@ extern struct pglist_data contig_page_data;
 #include <asm/sparsemem.h>
 #endif
 
-#if BITS_PER_LONG == 32 || defined(ARCH_HAS_ATOMIC_UNSIGNED)
+#if BITS_PER_LONG == 32
 /*
- * with 32 bit page->flags field, we reserve 8 bits for node/zone info.
- * there are 3 zones (2 bits) and this leaves 8-2=6 bits for nodes.
+ * with 32 bit page->flags field, we reserve 9 bits for node/zone info.
+ * there are 4 zones (3 bits) and this leaves 9-3=6 bits for nodes.
  */
-#define FLAGS_RESERVED         8
+#define FLAGS_RESERVED         9
 
 #elif BITS_PER_LONG == 64
 /*
@@ -509,6 +540,7 @@ static inline struct mem_section *__nr_to_section(unsigned long nr)
                return NULL;
        return &mem_section[SECTION_NR_TO_ROOT(nr)][nr & SECTION_ROOT_MASK];
 }
+extern int __section_nr(struct mem_section* ms);
 
 /*
  * We use the lower bits of the mem_map pointer to store