|
@@ -4551,39 +4551,41 @@ int __meminit init_currently_empty_zone(struct zone *zone,
|
|
|
|
|
|
#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
|
|
#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
|
|
#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
|
|
#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Required by SPARSEMEM. Given a PFN, return what node the PFN is on.
|
|
* Required by SPARSEMEM. Given a PFN, return what node the PFN is on.
|
|
*/
|
|
*/
|
|
-int __meminit __early_pfn_to_nid(unsigned long pfn)
|
|
|
|
|
|
+int __meminit __early_pfn_to_nid(unsigned long pfn,
|
|
|
|
+ struct mminit_pfnnid_cache *state)
|
|
{
|
|
{
|
|
unsigned long start_pfn, end_pfn;
|
|
unsigned long start_pfn, end_pfn;
|
|
int nid;
|
|
int nid;
|
|
- /*
|
|
|
|
- * NOTE: The following SMP-unsafe globals are only used early in boot
|
|
|
|
- * when the kernel is running single-threaded.
|
|
|
|
- */
|
|
|
|
- static unsigned long __meminitdata last_start_pfn, last_end_pfn;
|
|
|
|
- static int __meminitdata last_nid;
|
|
|
|
|
|
|
|
- if (last_start_pfn <= pfn && pfn < last_end_pfn)
|
|
|
|
- return last_nid;
|
|
|
|
|
|
+ if (state->last_start <= pfn && pfn < state->last_end)
|
|
|
|
+ return state->last_nid;
|
|
|
|
|
|
nid = memblock_search_pfn_nid(pfn, &start_pfn, &end_pfn);
|
|
nid = memblock_search_pfn_nid(pfn, &start_pfn, &end_pfn);
|
|
if (nid != -1) {
|
|
if (nid != -1) {
|
|
- last_start_pfn = start_pfn;
|
|
|
|
- last_end_pfn = end_pfn;
|
|
|
|
- last_nid = nid;
|
|
|
|
|
|
+ state->last_start = start_pfn;
|
|
|
|
+ state->last_end = end_pfn;
|
|
|
|
+ state->last_nid = nid;
|
|
}
|
|
}
|
|
|
|
|
|
return nid;
|
|
return nid;
|
|
}
|
|
}
|
|
#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
|
|
#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
|
|
|
|
|
|
|
|
+static struct mminit_pfnnid_cache early_pfnnid_cache __meminitdata;
|
|
|
|
+
|
|
|
|
+/* Only safe to use early in boot when initialisation is single-threaded */
|
|
int __meminit early_pfn_to_nid(unsigned long pfn)
|
|
int __meminit early_pfn_to_nid(unsigned long pfn)
|
|
{
|
|
{
|
|
int nid;
|
|
int nid;
|
|
|
|
|
|
- nid = __early_pfn_to_nid(pfn);
|
|
|
|
|
|
+ /* The system will behave unpredictably otherwise */
|
|
|
|
+ BUG_ON(system_state != SYSTEM_BOOTING);
|
|
|
|
+
|
|
|
|
+ nid = __early_pfn_to_nid(pfn, &early_pfnnid_cache);
|
|
if (nid >= 0)
|
|
if (nid >= 0)
|
|
return nid;
|
|
return nid;
|
|
/* just returns 0 */
|
|
/* just returns 0 */
|
|
@@ -4591,15 +4593,23 @@ int __meminit early_pfn_to_nid(unsigned long pfn)
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_NODES_SPAN_OTHER_NODES
|
|
#ifdef CONFIG_NODES_SPAN_OTHER_NODES
|
|
-bool __meminit early_pfn_in_nid(unsigned long pfn, int node)
|
|
|
|
|
|
+bool __meminit meminit_pfn_in_nid(unsigned long pfn, int node,
|
|
|
|
+ struct mminit_pfnnid_cache *state)
|
|
{
|
|
{
|
|
int nid;
|
|
int nid;
|
|
|
|
|
|
- nid = __early_pfn_to_nid(pfn);
|
|
|
|
|
|
+ nid = __early_pfn_to_nid(pfn, state);
|
|
if (nid >= 0 && nid != node)
|
|
if (nid >= 0 && nid != node)
|
|
return false;
|
|
return false;
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+/* Only safe to use early in boot when initialisation is single-threaded */
|
|
|
|
+bool __meminit early_pfn_in_nid(unsigned long pfn, int node)
|
|
|
|
+{
|
|
|
|
+ return meminit_pfn_in_nid(pfn, node, &early_pfnnid_cache);
|
|
|
|
+}
|
|
|
|
+
|
|
#endif
|
|
#endif
|
|
|
|
|
|
/**
|
|
/**
|