Currently, the node_distance macro just indexes numa_slit. However, numa_slit is not currently exported, and so node_distance cannot be used by any modules, whether in-tree or out-of-tree. None of the in-tree modules use it directly, but NVMe used to. Instead of exporting numa_slit, this commit refactors the implementation to be more like x86 and arm64, by providing wrapper functions for getting and setting distances which perform bounds-checking on the parameters, and exporting the new __node_distance function. Signed-off-by: James Clarke <jrtc27@xxxxxxxxxx> --- arch/ia64/include/asm/numa.h | 13 ++++-------- arch/ia64/kernel/acpi.c | 18 +++++++++------- arch/ia64/mm/numa.c | 50 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/arch/ia64/include/asm/numa.h b/arch/ia64/include/asm/numa.h index ebef7f40aabb..43242d9283af 100644 --- a/arch/ia64/include/asm/numa.h +++ b/arch/ia64/include/asm/numa.h @@ -50,16 +50,11 @@ struct node_cpuid_s { extern struct node_memblk_s node_memblk[NR_NODE_MEMBLKS]; extern struct node_cpuid_s node_cpuid[NR_CPUS]; -/* - * ACPI 2.0 SLIT (System Locality Information Table) - * http://devresource.hp.com/devresource/Docs/TechPapers/IA64/slit.pdf - * - * This is a matrix with "distances" between nodes, they should be - * proportional to the memory access latency ratios. - */ +extern void __init numa_reset_distance(void); +extern void __init numa_set_distance(int from, int to, int distance); -extern u8 numa_slit[MAX_NUMNODES * MAX_NUMNODES]; -#define node_distance(from,to) (numa_slit[(from) * MAX_NUMNODES + (to)]) +extern int __node_distance(int, int); +#define node_distance(a, b) __node_distance(a, b) extern int paddr_to_nid(unsigned long paddr); diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 1d29b2f8726b..4cbc58519e25 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -571,24 +571,28 @@ void __init acpi_numa_fixup(void) num_node_memblks); if (!slit_table) { - for (i = 0; i < MAX_NUMNODES; i++) - for (j = 0; j < MAX_NUMNODES; j++) - node_distance(i, j) = i == j ? LOCAL_DISTANCE : - REMOTE_DISTANCE; + for (i = 0; i < MAX_NUMNODES; i++) { + for (j = 0; j < MAX_NUMNODES; j++) { + int dist = i == j ? + LOCAL_DISTANCE : REMOTE_DISTANCE; + numa_set_distance(i, j, dist); + } + } return; } - memset(numa_slit, -1, sizeof(numa_slit)); + numa_reset_distance(); for (i = 0; i < slit_table->locality_count; i++) { if (!pxm_bit_test(i)) continue; node_from = pxm_to_node(i); for (j = 0; j < slit_table->locality_count; j++) { + int dist; if (!pxm_bit_test(j)) continue; node_to = pxm_to_node(j); - node_distance(node_from, node_to) = - slit_table->entry[i * slit_table->locality_count + j]; + dist = slit_table->entry[i * slit_table->locality_count + j]; + numa_set_distance(node_from, node_to, dist); } } diff --git a/arch/ia64/mm/numa.c b/arch/ia64/mm/numa.c index aa19b7ac8222..7c0b563ca878 100644 --- a/arch/ia64/mm/numa.c +++ b/arch/ia64/mm/numa.c @@ -34,7 +34,55 @@ struct node_cpuid_s node_cpuid[NR_CPUS] = * This is a matrix with "distances" between nodes, they should be * proportional to the memory access latency ratios. */ -u8 numa_slit[MAX_NUMNODES * MAX_NUMNODES]; +static u8 numa_slit[MAX_NUMNODES * MAX_NUMNODES]; + +/** + * numa_reset_distance - Reset NUMA distance table + * + * The current table is filled with 0xFF. + */ +void __init numa_reset_distance(void) +{ + memset(numa_slit, -1, sizeof(numa_slit)); +} + +/** + * numa_set_distance - Set NUMA distance from one NUMA to another + * @from: the 'from' node to set distance + * @to: the 'to' node to set distance + * @distance: NUMA distance + * + * Set the distance from node @from to @to to @distance. If @from or @to is + * higher than the highest possible node or lower than zero, or @distance + * doesn't make sense, the call is ignored. This is to allow simplification of + * specific NUMA config implementations. + */ +void __init numa_set_distance(int from, int to, int distance) +{ + if (from >= MAX_NUMNODES || to >= MAX_NUMNODES || + from < 0 || to < 0) { + pr_warn_once("NUMA: Warning: node ids are out of bound, from=%d to=%d distance=%d\n", + from, to, distance); + return; + } + + if ((u8)distance != distance || + (from == to && distance != LOCAL_DISTANCE)) { + pr_warn_once("NUMA: Warning: invalid distance parameter, from=%d to=%d distance=%d\n", + from, to, distance); + return; + } + + numa_slit[from * MAX_NUMNODES + to] = distance; +} + +int __node_distance(int from, int to) +{ + if (from >= MAX_NUMNODES || to >= MAX_NUMNODES) + return from == to ? LOCAL_DISTANCE : REMOTE_DISTANCE; + return numa_slit[from * MAX_NUMNODES + to]; +} +EXPORT_SYMBOL(__node_distance); /* Identify which cnode a physical address resides on */ int -- 2.15.1 -- To unsubscribe from this list: send the line "unsubscribe linux-ia64" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html
![]() |