Commit 346e2fee authored by Erich Focht's avatar Erich Focht Committed by David Mosberger

[PATCH] acpi-numa for ia64

Add ACPI NUMA support for ia64.
parent ce8b6d64
......@@ -8,6 +8,9 @@
* Copyright (C) 2000 Intel Corp.
* Copyright (C) 2000,2001 J.I. Lee <jung-ik.lee@intel.com>
* Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
* Copyright (C) 2001 Jenna Hall <jenna.s.hall@intel.com>
* Copyright (C) 2001 Takayoshi Kochi <t-kouchi@cq.jp.nec.com>
* Copyright (C) 2002 Erich Focht <efocht@ess.nec.de>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
......@@ -43,6 +46,7 @@
#include <asm/machvec.h>
#include <asm/page.h>
#include <asm/system.h>
#include <asm/numa.h>
#define PREFIX "ACPI: "
......@@ -447,6 +451,158 @@ acpi_parse_madt (unsigned long phys_addr, unsigned long size)
}
#ifdef CONFIG_ACPI_NUMA
#define SLIT_DEBUG
#define PXM_FLAG_LEN ((MAX_PXM_DOMAINS + 1)/32)
static int __initdata srat_num_cpus; /* number of cpus */
static u32 __initdata pxm_flag[PXM_FLAG_LEN];
#define pxm_bit_set(bit) (set_bit(bit,(void *)pxm_flag))
#define pxm_bit_test(bit) (test_bit(bit,(void *)pxm_flag))
/* maps to convert between proximity domain and logical node ID */
int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS];
int __initdata nid_to_pxm_map[NR_NODES];
static struct acpi_table_slit __initdata *slit_table;
/*
* ACPI 2.0 SLIT (System Locality Information Table)
* http://devresource.hp.com/devresource/Docs/TechPapers/IA64/slit.pdf
*/
void __init
acpi_numa_slit_init (struct acpi_table_slit *slit)
{
int i, j, node_from, node_to;
u32 len;
len = sizeof(struct acpi_table_header) + 8
+ slit->localities * slit->localities;
if (slit->header.length != len) {
printk("ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n",
len, slit->header.length);
memset(numa_slit, 10, sizeof(numa_slit));
return;
}
slit_table = slit;
}
void __init
acpi_numa_processor_affinity_init (struct acpi_table_processor_affinity *pa)
{
/* record this node in proximity bitmap */
pxm_bit_set(pa->proximity_domain);
node_cpuid[srat_num_cpus].phys_id = (pa->apic_id << 8) | (pa->lsapic_eid);
/* nid should be overridden as logical node id later */
node_cpuid[srat_num_cpus].nid = pa->proximity_domain;
srat_num_cpus++;
}
void __init
acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma)
{
unsigned long paddr, size;
u8 pxm;
struct node_memblk_s *p, *q, *pend;
pxm = ma->proximity_domain;
/* record this node in proximity bitmap */
pxm_bit_set(pxm);
/* fill node memory chunk structure */
paddr = ma->base_addr_hi;
paddr = (paddr << 32) | ma->base_addr_lo;
size = ma->length_hi;
size = (size << 32) | ma->length_lo;
if (num_memblks >= NR_MEMBLKS) {
printk("Too many mem chunks in SRAT. Ignoring %ld MBytes at %lx\n",
size/(1024*1024), paddr);
return;
}
/* Insertion sort based on base address */
pend = &node_memblk[num_memblks];
for (p = &node_memblk[0]; p < pend; p++) {
if (paddr < p->start_paddr)
break;
}
if (p < pend) {
for (q = pend; q >= p; q--)
*(q + 1) = *q;
}
p->start_paddr = paddr;
p->size = size;
p->nid = pxm;
num_memblks++;
}
void __init
acpi_numa_arch_fixup(void)
{
int i, j;
/* calculate total number of nodes in system from PXM bitmap */
numnodes = 0; /* init total nodes in system */
memset(pxm_to_nid_map, -1, sizeof(pxm_to_nid_map));
memset(nid_to_pxm_map, -1, sizeof(nid_to_pxm_map));
for (i = 0; i < MAX_PXM_DOMAINS; i++) {
if (pxm_bit_test(i)) {
pxm_to_nid_map[i] = numnodes;
nid_to_pxm_map[numnodes++] = i;
}
}
/* set logical node id in memory chunk structure */
for (i = 0; i < num_memblks; i++)
node_memblk[i].nid = pxm_to_nid_map[node_memblk[i].nid];
/* assign memory bank numbers for each chunk on each node */
for (i = 0; i < numnodes; i++) {
int bank;
bank = 0;
for (j = 0; j < num_memblks; j++)
if (node_memblk[j].nid == i)
node_memblk[j].bank = bank++;
}
/* set logical node id in cpu structure */
for (i = 0; i < srat_num_cpus; i++)
node_cpuid[i].nid = pxm_to_nid_map[node_cpuid[i].nid];
printk("Number of logical nodes in system = %d\n", numnodes);
printk("Number of memory chunks in system = %d\n", num_memblks);
if (!slit_table) return;
memset(numa_slit, -1, sizeof(numa_slit));
for (i=0; i<slit_table->localities; i++) {
if (!pxm_bit_test(i))
continue;
node_from = pxm_to_nid_map[i];
for (j=0; j<slit_table->localities; j++) {
if (!pxm_bit_test(j))
continue;
node_to = pxm_to_nid_map[j];
node_distance(node_from, node_to) =
slit_table->entry[i*slit_table->localities + j];
}
}
#ifdef SLIT_DEBUG
printk("ACPI 2.0 SLIT locality table:\n");
for (i = 0; i < numnodes; i++) {
for (j = 0; j < numnodes; j++)
printk("%03d ", node_distance(i,j));
printk("\n");
}
#endif
}
#endif /* CONFIG_ACPI_NUMA */
static int __init
acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
{
......@@ -556,12 +712,6 @@ acpi_parse_spcr (unsigned long phys_addr, unsigned long size)
int __init
acpi_boot_init (char *cmdline)
{
int result;
/* Initialize the ACPI boot-time table parser */
result = acpi_table_init(cmdline);
if (result)
return result;
/*
* MADT
......
......@@ -296,6 +296,16 @@ setup_arch (char **cmdline_p)
efi_init();
#ifdef CONFIG_ACPI_BOOT
/* Initialize the ACPI boot-time table parser */
acpi_table_init(*cmdline_p);
#ifdef CONFIG_ACPI_NUMA
acpi_numa_init();
#endif
#endif /* CONFIG_APCI_BOOT */
find_memory();
#if 0
......
......@@ -9,5 +9,6 @@
obj-y := init.o fault.o tlb.o extable.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_NUMA) += numa.o
include $(TOPDIR)/Rules.make
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* This file contains NUMA specific variables and functions which can
* be split away from DISCONTIGMEM and are used on NUMA machines with
* contiguous memory.
*
* 2002/08/07 Erich Focht <efocht@ess.nec.de>
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/mmzone.h>
#include <asm/numa.h>
/*
* The following structures are usually initialized by ACPI or
* similar mechanisms and describe the NUMA characteristics of the machine.
*/
int num_memblks = 0;
struct node_memblk_s node_memblk[NR_MEMBLKS];
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[NR_NODES * NR_NODES];
/* Identify which cnode a physical address resides on */
int
paddr_to_nid(unsigned long paddr)
{
int i;
for (i = 0; i < num_memblks; i++)
if (paddr >= node_memblk[i].start_paddr &&
paddr < node_memblk[i].start_paddr + node_memblk[i].size)
break;
return (i < num_memblks) ? node_memblk[i].nid : -1;
}
......@@ -97,17 +97,18 @@
} while (0)
const char *acpi_get_sysname (void);
int acpi_boot_init (char *cdline);
int acpi_request_vector (u32 int_type);
int acpi_get_prt (struct pci_vector_struct **vectors, int *count);
int acpi_get_interrupt_model (int *type);
int acpi_irq_to_vector (u32 irq);
#ifdef CONFIG_DISCONTIGMEM
#define NODE_ARRAY_INDEX(x) ((x) / 8) /* 8 bits/char */
#define NODE_ARRAY_OFFSET(x) ((x) % 8) /* 8 bits/char */
#define MAX_PXM_DOMAINS (256)
#endif /* CONFIG_DISCONTIGMEM */
#ifdef CONFIG_ACPI_NUMA
#include <asm/numa.h>
/* Proximity bitmap length; _PXM is at most 255 (8 bit)*/
#define MAX_PXM_DOMAINS (256)
extern int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS];
extern int __initdata nid_to_pxm_map[NR_NODES];
#endif
#endif /*__KERNEL__*/
......
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* This file contains NUMA specific prototypes and definitions.
*
* 2002/08/05 Erich Focht <efocht@ess.nec.de>
*
*/
#ifndef _ASM_IA64_NUMA_H
#define _ASM_IA64_NUMA_H
#ifdef CONFIG_NUMA
#ifdef CONFIG_DISCONTIGMEM
# include <asm/mmzone.h>
# define NR_NODES (PLAT_MAX_COMPACT_NODES)
# define NR_MEMBLKS (PLAT_MAXCLUMPS)
#else
# define NR_NODES (8)
# define NR_MEMBLKS (NR_NODES * 8)
#endif
/* Stuff below this line could be architecture independent */
extern int num_memblks; /* total number of memory chunks */
/*
* List of node memory chunks. Filled when parsing SRAT table to
* obtain information about memory nodes.
*/
struct node_memblk_s {
unsigned long start_paddr;
unsigned long size;
int nid; /* which logical node contains this chunk? */
int bank; /* which mem bank on this node */
};
struct node_cpuid_s {
u16 phys_id; /* id << 8 | eid */
int nid; /* logical node containing this CPU */
};
extern struct node_memblk_s node_memblk[NR_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 u8 numa_slit[NR_NODES * NR_NODES];
#define node_distance(from,to) (numa_slit[from * numnodes + to])
extern int paddr_to_nid(unsigned long paddr);
#endif /* CONFIG_NUMA */
#endif /* _ASM_IA64_NUMA_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment