ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / acpi / numa.c
1 /*
2  *  acpi_numa.c - ACPI NUMA support
3  *
4  *  Copyright (C) 2002 Takayoshi Kochi <t-kochi@bq.jp.nec.com>
5  *
6  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23  *
24  */
25
26 #include <linux/config.h>
27 #include <linux/init.h>
28 #include <linux/kernel.h>
29 #include <linux/types.h>
30 #include <linux/errno.h>
31 #include <linux/acpi.h>
32 #include <acpi/acpi_bus.h>
33 #include <acpi/acmacros.h>
34
35 #define ACPI_NUMA       0x80000000
36 #define _COMPONENT      ACPI_NUMA
37         ACPI_MODULE_NAME ("numa")
38
39 extern int __init acpi_table_parse_madt_family (enum acpi_table_id id, unsigned long madt_size, int entry_id, acpi_madt_entry_handler handler, unsigned int max_entries);
40
41 void __init
42 acpi_table_print_srat_entry (
43         acpi_table_entry_header *header)
44 {
45
46         ACPI_FUNCTION_NAME ("acpi_table_print_srat_entry");
47
48         if (!header)
49                 return;
50
51         switch (header->type) {
52
53         case ACPI_SRAT_PROCESSOR_AFFINITY:
54         {
55                 struct acpi_table_processor_affinity *p =
56                         (struct acpi_table_processor_affinity*) header;
57                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n",
58                        p->apic_id, p->lsapic_eid, p->proximity_domain,
59                        p->flags.enabled?"enabled":"disabled"));
60         }
61                 break;
62
63         case ACPI_SRAT_MEMORY_AFFINITY:
64         {
65                 struct acpi_table_memory_affinity *p =
66                         (struct acpi_table_memory_affinity*) header;
67                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SRAT Memory (0x%08x%08x length 0x%08x%08x type 0x%x) in proximity domain %d %s%s\n",
68                        p->base_addr_hi, p->base_addr_lo, p->length_hi, p->length_lo,
69                        p->memory_type, p->proximity_domain,
70                        p->flags.enabled ? "enabled" : "disabled",
71                        p->flags.hot_pluggable ? " hot-pluggable" : ""));
72         }
73                 break;
74
75         default:
76                 printk(KERN_WARNING PREFIX "Found unsupported SRAT entry (type = 0x%x)\n",
77                         header->type);
78                 break;
79         }
80 }
81
82
83 static int __init
84 acpi_parse_slit (unsigned long phys_addr, unsigned long size)
85 {
86         struct acpi_table_slit  *slit;
87         u32                     localities;
88
89         if (!phys_addr || !size)
90                 return -EINVAL;
91
92         slit = (struct acpi_table_slit *) __va(phys_addr);
93
94         /* downcast just for %llu vs %lu for i386/ia64  */
95         localities = (u32) slit->localities;
96
97         printk(KERN_INFO PREFIX "SLIT localities %ux%u\n", localities, localities);
98
99         acpi_numa_slit_init(slit);
100
101         return 0;
102 }
103
104
105 static int __init
106 acpi_parse_processor_affinity (acpi_table_entry_header *header)
107 {
108         struct acpi_table_processor_affinity *processor_affinity;
109
110         processor_affinity = (struct acpi_table_processor_affinity*) header;
111         if (!processor_affinity)
112                 return -EINVAL;
113
114         acpi_table_print_srat_entry(header);
115
116         /* let architecture-dependent part to do it */
117         acpi_numa_processor_affinity_init(processor_affinity);
118
119         return 0;
120 }
121
122
123 static int __init
124 acpi_parse_memory_affinity (acpi_table_entry_header *header)
125 {
126         struct acpi_table_memory_affinity *memory_affinity;
127
128         memory_affinity = (struct acpi_table_memory_affinity*) header;
129         if (!memory_affinity)
130                 return -EINVAL;
131
132         acpi_table_print_srat_entry(header);
133
134         /* let architecture-dependent part to do it */
135         acpi_numa_memory_affinity_init(memory_affinity);
136
137         return 0;
138 }
139
140
141 static int __init
142 acpi_parse_srat (unsigned long phys_addr, unsigned long size)
143 {
144         struct acpi_table_srat  *srat;
145
146         if (!phys_addr || !size)
147                 return -EINVAL;
148
149         srat = (struct acpi_table_srat *) __va(phys_addr);
150
151         printk(KERN_INFO PREFIX "SRAT revision %d\n", srat->table_revision);
152
153         return 0;
154 }
155
156
157 int __init
158 acpi_table_parse_srat (
159         enum acpi_srat_entry_id id,
160         acpi_madt_entry_handler handler,
161         unsigned int max_entries)
162 {
163         return acpi_table_parse_madt_family(ACPI_SRAT, sizeof(struct acpi_table_srat),
164                                             id, handler, max_entries);
165 }
166
167
168 int __init
169 acpi_numa_init()
170 {
171         int                     result;
172
173         /* SRAT: Static Resource Affinity Table */
174         result = acpi_table_parse(ACPI_SRAT, acpi_parse_srat);
175
176         if (result > 0) {
177                 result = acpi_table_parse_srat(ACPI_SRAT_PROCESSOR_AFFINITY,
178                                                acpi_parse_processor_affinity,
179                                                NR_CPUS);
180                 result = acpi_table_parse_srat(ACPI_SRAT_MEMORY_AFFINITY,
181                                                acpi_parse_memory_affinity,
182                                                NR_NODE_MEMBLKS);        // IA64 specific
183         } else {
184                 /* FIXME */
185                 printk("Warning: acpi_table_parse(ACPI_SRAT) returned %d!\n",result);
186         }
187
188         /* SLIT: System Locality Information Table */
189         result = acpi_table_parse(ACPI_SLIT, acpi_parse_slit);
190         if (result < 1) {
191                 /* FIXME */
192                 printk("Warning: acpi_table_parse(ACPI_SLIT) returned %d!\n",result);
193         }
194
195         acpi_numa_arch_fixup();
196         return 0;
197 }