]> Pileus Git - ~andy/linux/commitdiff
x86-64, NUMA: Prepare numa_emulation() for moving NUMA emulation into a separate...
authorTejun Heo <tj@kernel.org>
Tue, 22 Feb 2011 10:10:08 +0000 (11:10 +0100)
committerTejun Heo <tj@kernel.org>
Tue, 22 Feb 2011 10:10:08 +0000 (11:10 +0100)
Update numa_emulation() such that, it

- takes @numa_meminfo and @numa_dist_cnt instead of directly
  referencing the global variables.

- copies the distance table by iterating each distance with
  node_distance() instead of memcpy'ing the distance table.

- tests emu_cmdline to determine whether emulation is requested and
  fills emu_nid_to_phys[] with identity mapping if emulation is not
  used.  This allows the caller to call numa_emulation()
  unconditionally and makes return value unncessary.

- defines dummy version if CONFIG_NUMA_EMU is disabled.

This patch doesn't introduce any behavior change.

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
arch/x86/mm/numa_64.c

index 6e4ee96d1b11995c2cb069fa1cfa459330850868..980d51458c4bd820a50b5db876b28b6bde73b1dd 100644 (file)
@@ -789,17 +789,20 @@ static int __init split_nodes_size_interleave(struct numa_meminfo *ei,
  * Sets up the system RAM area from start_pfn to last_pfn according to the
  * numa=fake command-line option.
  */
-static bool __init numa_emulation(void)
+static void __init numa_emulation(struct numa_meminfo *numa_meminfo,
+                                 int numa_dist_cnt)
 {
        static struct numa_meminfo ei __initdata;
        static struct numa_meminfo pi __initdata;
        const u64 max_addr = max_pfn << PAGE_SHIFT;
-       int phys_dist_cnt = numa_distance_cnt;
        u8 *phys_dist = NULL;
        int i, j, ret;
 
+       if (!emu_cmdline)
+               goto no_emu;
+
        memset(&ei, 0, sizeof(ei));
-       pi = numa_meminfo;
+       pi = *numa_meminfo;
 
        for (i = 0; i < MAX_NUMNODES; i++)
                emu_nid_to_phys[i] = NUMA_NO_NODE;
@@ -822,19 +825,19 @@ static bool __init numa_emulation(void)
        }
 
        if (ret < 0)
-               return false;
+               goto no_emu;
 
        if (numa_cleanup_meminfo(&ei) < 0) {
                pr_warning("NUMA: Warning: constructed meminfo invalid, disabling emulation\n");
-               return false;
+               goto no_emu;
        }
 
        /*
         * Copy the original distance table.  It's temporary so no need to
         * reserve it.
         */
-       if (phys_dist_cnt) {
-               size_t size = phys_dist_cnt * sizeof(numa_distance[0]);
+       if (numa_dist_cnt) {
+               size_t size = numa_dist_cnt * sizeof(phys_dist[0]);
                u64 phys;
 
                phys = memblock_find_in_range(0,
@@ -842,14 +845,18 @@ static bool __init numa_emulation(void)
                                              size, PAGE_SIZE);
                if (phys == MEMBLOCK_ERROR) {
                        pr_warning("NUMA: Warning: can't allocate copy of distance table, disabling emulation\n");
-                       return false;
+                       goto no_emu;
                }
                phys_dist = __va(phys);
-               memcpy(phys_dist, numa_distance, size);
+
+               for (i = 0; i < numa_dist_cnt; i++)
+                       for (j = 0; j < numa_dist_cnt; j++)
+                               phys_dist[i * numa_dist_cnt + j] =
+                                       node_distance(i, j);
        }
 
        /* commit */
-       numa_meminfo = ei;
+       *numa_meminfo = ei;
 
        /*
         * Transform __apicid_to_node table to use emulated nids by
@@ -878,18 +885,27 @@ static bool __init numa_emulation(void)
                        int physj = emu_nid_to_phys[j];
                        int dist;
 
-                       if (physi >= phys_dist_cnt || physj >= phys_dist_cnt)
+                       if (physi >= numa_dist_cnt || physj >= numa_dist_cnt)
                                dist = physi == physj ?
                                        LOCAL_DISTANCE : REMOTE_DISTANCE;
                        else
-                               dist = phys_dist[physi * phys_dist_cnt + physj];
+                               dist = phys_dist[physi * numa_dist_cnt + physj];
 
                        numa_set_distance(i, j, dist);
                }
        }
-       return true;
+       return;
+
+no_emu:
+       /* No emulation.  Build identity emu_nid_to_phys[] for numa_add_cpu() */
+       for (i = 0; i < ARRAY_SIZE(emu_nid_to_phys); i++)
+               emu_nid_to_phys[i] = i;
 }
-#endif /* CONFIG_NUMA_EMU */
+#else  /* CONFIG_NUMA_EMU */
+static inline void numa_emulation(struct numa_meminfo *numa_meminfo,
+                                 int numa_dist_cnt)
+{ }
+#endif /* CONFIG_NUMA_EMU */
 
 static int __init dummy_numa_init(void)
 {
@@ -937,15 +953,9 @@ void __init initmem_init(void)
 
                if (numa_cleanup_meminfo(&numa_meminfo) < 0)
                        continue;
-#ifdef CONFIG_NUMA_EMU
-               /*
-                * If requested, try emulation.  If emulation is not used,
-                * build identity emu_nid_to_phys[] for numa_add_cpu()
-                */
-               if (!emu_cmdline || !numa_emulation())
-                       for (j = 0; j < ARRAY_SIZE(emu_nid_to_phys); j++)
-                               emu_nid_to_phys[j] = j;
-#endif
+
+               numa_emulation(&numa_meminfo, numa_distance_cnt);
+
                if (numa_register_memblks(&numa_meminfo) < 0)
                        continue;