|
@@ -363,6 +363,54 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
|
|
|
for (i = 0; i < MAX_NUMNODES; i++)
|
|
|
cutoff_node(i, start, end);
|
|
|
|
|
|
+ /*
|
|
|
+ * Join together blocks on the same node, holes between
|
|
|
+ * which don't overlap with memory on other nodes.
|
|
|
+ */
|
|
|
+ for (i = 0; i < num_node_memblks; ++i) {
|
|
|
+ int j, k;
|
|
|
+
|
|
|
+ for (j = i + 1; j < num_node_memblks; ++j) {
|
|
|
+ unsigned long start, end;
|
|
|
+
|
|
|
+ if (memblk_nodeid[i] != memblk_nodeid[j])
|
|
|
+ continue;
|
|
|
+ start = min(node_memblk_range[i].end,
|
|
|
+ node_memblk_range[j].end);
|
|
|
+ end = max(node_memblk_range[i].start,
|
|
|
+ node_memblk_range[j].start);
|
|
|
+ for (k = 0; k < num_node_memblks; ++k) {
|
|
|
+ if (memblk_nodeid[i] == memblk_nodeid[k])
|
|
|
+ continue;
|
|
|
+ if (start < node_memblk_range[k].end &&
|
|
|
+ end > node_memblk_range[k].start)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (k < num_node_memblks)
|
|
|
+ continue;
|
|
|
+ start = min(node_memblk_range[i].start,
|
|
|
+ node_memblk_range[j].start);
|
|
|
+ end = max(node_memblk_range[i].end,
|
|
|
+ node_memblk_range[j].end);
|
|
|
+ printk(KERN_INFO "SRAT: Node %d "
|
|
|
+ "[%Lx,%Lx) + [%Lx,%Lx) -> [%lx,%lx)\n",
|
|
|
+ memblk_nodeid[i],
|
|
|
+ node_memblk_range[i].start,
|
|
|
+ node_memblk_range[i].end,
|
|
|
+ node_memblk_range[j].start,
|
|
|
+ node_memblk_range[j].end,
|
|
|
+ start, end);
|
|
|
+ node_memblk_range[i].start = start;
|
|
|
+ node_memblk_range[i].end = end;
|
|
|
+ k = --num_node_memblks - j;
|
|
|
+ memmove(memblk_nodeid + j, memblk_nodeid + j+1,
|
|
|
+ k * sizeof(*memblk_nodeid));
|
|
|
+ memmove(node_memblk_range + j, node_memblk_range + j+1,
|
|
|
+ k * sizeof(*node_memblk_range));
|
|
|
+ --j;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
memnode_shift = compute_hash_shift(node_memblk_range, num_node_memblks,
|
|
|
memblk_nodeid);
|
|
|
if (memnode_shift < 0) {
|