162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
362306a36Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
462306a36Sopenharmony_ci * for more details.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * This file contains NUMA specific variables and functions which are used on
762306a36Sopenharmony_ci * NUMA machines with contiguous memory.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci *                         2002/08/07 Erich Focht <efocht@ess.nec.de>
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/cpu.h>
1362306a36Sopenharmony_ci#include <linux/kernel.h>
1462306a36Sopenharmony_ci#include <linux/mm.h>
1562306a36Sopenharmony_ci#include <linux/node.h>
1662306a36Sopenharmony_ci#include <linux/init.h>
1762306a36Sopenharmony_ci#include <linux/memblock.h>
1862306a36Sopenharmony_ci#include <linux/module.h>
1962306a36Sopenharmony_ci#include <asm/mmzone.h>
2062306a36Sopenharmony_ci#include <asm/numa.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/*
2462306a36Sopenharmony_ci * The following structures are usually initialized by ACPI or
2562306a36Sopenharmony_ci * similar mechanisms and describe the NUMA characteristics of the machine.
2662306a36Sopenharmony_ci */
2762306a36Sopenharmony_ciint num_node_memblks;
2862306a36Sopenharmony_cistruct node_memblk_s node_memblk[NR_NODE_MEMBLKS];
2962306a36Sopenharmony_cistruct node_cpuid_s node_cpuid[NR_CPUS] =
3062306a36Sopenharmony_ci	{ [0 ... NR_CPUS-1] = { .phys_id = 0, .nid = NUMA_NO_NODE } };
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/*
3362306a36Sopenharmony_ci * This is a matrix with "distances" between nodes, they should be
3462306a36Sopenharmony_ci * proportional to the memory access latency ratios.
3562306a36Sopenharmony_ci */
3662306a36Sopenharmony_ciu8 numa_slit[MAX_NUMNODES * MAX_NUMNODES];
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ciint __node_distance(int from, int to)
3962306a36Sopenharmony_ci{
4062306a36Sopenharmony_ci	return slit_distance(from, to);
4162306a36Sopenharmony_ci}
4262306a36Sopenharmony_ciEXPORT_SYMBOL(__node_distance);
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci/* Identify which cnode a physical address resides on */
4562306a36Sopenharmony_ciint
4662306a36Sopenharmony_cipaddr_to_nid(unsigned long paddr)
4762306a36Sopenharmony_ci{
4862306a36Sopenharmony_ci	int	i;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	for (i = 0; i < num_node_memblks; i++)
5162306a36Sopenharmony_ci		if (paddr >= node_memblk[i].start_paddr &&
5262306a36Sopenharmony_ci		    paddr < node_memblk[i].start_paddr + node_memblk[i].size)
5362306a36Sopenharmony_ci			break;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	return (i < num_node_memblks) ? node_memblk[i].nid : (num_node_memblks ? -1 : 0);
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ciEXPORT_SYMBOL(paddr_to_nid);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_NUMA)
6062306a36Sopenharmony_civoid numa_clear_node(int cpu)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	unmap_cpu_from_node(cpu, NUMA_NO_NODE);
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci#ifdef CONFIG_MEMORY_HOTPLUG
6662306a36Sopenharmony_ci/*
6762306a36Sopenharmony_ci *  SRAT information is stored in node_memblk[], then we can use SRAT
6862306a36Sopenharmony_ci *  information at memory-hot-add if necessary.
6962306a36Sopenharmony_ci */
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ciint memory_add_physaddr_to_nid(u64 addr)
7262306a36Sopenharmony_ci{
7362306a36Sopenharmony_ci	int nid = paddr_to_nid(addr);
7462306a36Sopenharmony_ci	if (nid < 0)
7562306a36Sopenharmony_ci		return 0;
7662306a36Sopenharmony_ci	return nid;
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ciEXPORT_SYMBOL(memory_add_physaddr_to_nid);
7962306a36Sopenharmony_ci#endif
8062306a36Sopenharmony_ci#endif
81