Linux-2.6.12-rc2
[linux-flexiantxendom0-natty.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 #include <linux/module.h>
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 #ifdef ACPI_DEBUG_OUTPUT
55         {
56                 struct acpi_table_processor_affinity *p =
57                         (struct acpi_table_processor_affinity*) header;
58                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n",
59                        p->apic_id, p->lsapic_eid, p->proximity_domain,
60                        p->flags.enabled?"enabled":"disabled"));
61         }
62 #endif /* ACPI_DEBUG_OUTPUT */
63                 break;
64
65         case ACPI_SRAT_MEMORY_AFFINITY:
66 #ifdef ACPI_DEBUG_OUTPUT
67         {
68                 struct acpi_table_memory_affinity *p =
69                         (struct acpi_table_memory_affinity*) header;
70                 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",
71                        p->base_addr_hi, p->base_addr_lo, p->length_hi, p->length_lo,
72                        p->memory_type, p->proximity_domain,
73                        p->flags.enabled ? "enabled" : "disabled",
74                        p->flags.hot_pluggable ? " hot-pluggable" : ""));
75         }
76 #endif /* ACPI_DEBUG_OUTPUT */
77                 break;
78
79         default:
80                 printk(KERN_WARNING PREFIX "Found unsupported SRAT entry (type = 0x%x)\n",
81                         header->type);
82                 break;
83         }
84 }
85
86
87 static int __init
88 acpi_parse_slit (unsigned long phys_addr, unsigned long size)
89 {
90         struct acpi_table_slit  *slit;
91         u32                     localities;
92
93         if (!phys_addr || !size)
94                 return -EINVAL;
95
96         slit = (struct acpi_table_slit *) __va(phys_addr);
97
98         /* downcast just for %llu vs %lu for i386/ia64  */
99         localities = (u32) slit->localities;
100
101         acpi_numa_slit_init(slit);
102
103         return 0;
104 }
105
106
107 static int __init
108 acpi_parse_processor_affinity (
109         acpi_table_entry_header *header,
110         const unsigned long end)
111 {
112         struct acpi_table_processor_affinity *processor_affinity;
113
114         processor_affinity = (struct acpi_table_processor_affinity*) header;
115         if (!processor_affinity)
116                 return -EINVAL;
117
118         acpi_table_print_srat_entry(header);
119
120         /* let architecture-dependent part to do it */
121         acpi_numa_processor_affinity_init(processor_affinity);
122
123         return 0;
124 }
125
126
127 static int __init
128 acpi_parse_memory_affinity (
129         acpi_table_entry_header *header,
130         const unsigned long end)
131 {
132         struct acpi_table_memory_affinity *memory_affinity;
133
134         memory_affinity = (struct acpi_table_memory_affinity*) header;
135         if (!memory_affinity)
136                 return -EINVAL;
137
138         acpi_table_print_srat_entry(header);
139
140         /* let architecture-dependent part to do it */
141         acpi_numa_memory_affinity_init(memory_affinity);
142
143         return 0;
144 }
145
146
147 static int __init
148 acpi_parse_srat (unsigned long phys_addr, unsigned long size)
149 {
150         struct acpi_table_srat  *srat;
151
152         if (!phys_addr || !size)
153                 return -EINVAL;
154
155         srat = (struct acpi_table_srat *) __va(phys_addr);
156
157         return 0;
158 }
159
160
161 int __init
162 acpi_table_parse_srat (
163         enum acpi_srat_entry_id id,
164         acpi_madt_entry_handler handler,
165         unsigned int max_entries)
166 {
167         return acpi_table_parse_madt_family(ACPI_SRAT, sizeof(struct acpi_table_srat),
168                                             id, handler, max_entries);
169 }
170
171
172 int __init
173 acpi_numa_init(void)
174 {
175         int                     result;
176
177         /* SRAT: Static Resource Affinity Table */
178         result = acpi_table_parse(ACPI_SRAT, acpi_parse_srat);
179
180         if (result > 0) {
181                 result = acpi_table_parse_srat(ACPI_SRAT_PROCESSOR_AFFINITY,
182                                                acpi_parse_processor_affinity,
183                                                NR_CPUS);
184                 result = acpi_table_parse_srat(ACPI_SRAT_MEMORY_AFFINITY,
185                                                acpi_parse_memory_affinity,
186                                                NR_NODE_MEMBLKS);        // IA64 specific
187         }
188
189         /* SLIT: System Locality Information Table */
190         result = acpi_table_parse(ACPI_SLIT, acpi_parse_slit);
191
192         acpi_numa_arch_fixup();
193         return 0;
194 }
195
196 int
197 acpi_get_pxm(acpi_handle h)
198 {
199         unsigned long pxm;
200         acpi_status status;
201         acpi_handle handle;
202         acpi_handle phandle = h;
203
204         do {
205                 handle = phandle;
206                 status = acpi_evaluate_integer(handle, "_PXM", NULL, &pxm);
207                 if (ACPI_SUCCESS(status))
208                         return (int)pxm;
209                 status = acpi_get_parent(handle, &phandle);
210         } while(ACPI_SUCCESS(status));
211         return -1;
212 }
213 EXPORT_SYMBOL(acpi_get_pxm);