~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to xen/drivers/acpi/tables.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  acpi_tables.c - ACPI Boot-Time Table Parsing
 
3
 *
 
4
 *  Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.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 <xen/init.h>
 
27
#include <xen/kernel.h>
 
28
#include <xen/smp.h>
 
29
#include <xen/string.h>
 
30
#include <xen/types.h>
 
31
#include <xen/irq.h>
 
32
#include <xen/errno.h>
 
33
#include <xen/acpi.h>
 
34
 
 
35
#define PREFIX                  "ACPI: "
 
36
 
 
37
#define ACPI_MAX_TABLES         128
 
38
 
 
39
static const char *__initdata
 
40
mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" };
 
41
static const char *__initdata
 
42
mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" };
 
43
 
 
44
static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata;
 
45
 
 
46
static int acpi_apic_instance __initdata;
 
47
 
 
48
void __init acpi_table_print_madt_entry(struct acpi_subtable_header *header)
 
49
{
 
50
        if (!header)
 
51
                return;
 
52
 
 
53
        switch (header->type) {
 
54
 
 
55
        case ACPI_MADT_TYPE_LOCAL_APIC:
 
56
                {
 
57
                        struct acpi_madt_local_apic *p =
 
58
                            (struct acpi_madt_local_apic *)header;
 
59
                        printk(KERN_INFO PREFIX
 
60
                               "LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n",
 
61
                               p->processor_id, p->id,
 
62
                               (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
 
63
                }
 
64
                break;
 
65
 
 
66
        case ACPI_MADT_TYPE_IO_APIC:
 
67
                {
 
68
                        struct acpi_madt_io_apic *p =
 
69
                            (struct acpi_madt_io_apic *)header;
 
70
                        printk(KERN_INFO PREFIX
 
71
                               "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n",
 
72
                               p->id, p->address, p->global_irq_base);
 
73
                }
 
74
                break;
 
75
 
 
76
        case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
 
77
                {
 
78
                        struct acpi_madt_interrupt_override *p =
 
79
                            (struct acpi_madt_interrupt_override *)header;
 
80
                        printk(KERN_INFO PREFIX
 
81
                               "INT_SRC_OVR (bus %d bus_irq %d global_irq %d %s %s)\n",
 
82
                               p->bus, p->source_irq, p->global_irq,
 
83
                               mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK],
 
84
                               mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2]);
 
85
                        if (p->inti_flags  &
 
86
                            ~(ACPI_MADT_POLARITY_MASK | ACPI_MADT_TRIGGER_MASK))
 
87
                                printk(KERN_INFO PREFIX
 
88
                                       "INT_SRC_OVR unexpected reserved flags: 0x%x\n",
 
89
                                       p->inti_flags  &
 
90
                                        ~(ACPI_MADT_POLARITY_MASK | ACPI_MADT_TRIGGER_MASK));
 
91
 
 
92
                }
 
93
                break;
 
94
 
 
95
        case ACPI_MADT_TYPE_NMI_SOURCE:
 
96
                {
 
97
                        struct acpi_madt_nmi_source *p =
 
98
                            (struct acpi_madt_nmi_source *)header;
 
99
                        printk(KERN_INFO PREFIX
 
100
                               "NMI_SRC (%s %s global_irq %d)\n",
 
101
                               mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK],
 
102
                               mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2],
 
103
                               p->global_irq);
 
104
                }
 
105
                break;
 
106
 
 
107
        case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
 
108
                {
 
109
                        struct acpi_madt_local_apic_nmi *p =
 
110
                            (struct acpi_madt_local_apic_nmi *)header;
 
111
                        printk(KERN_INFO PREFIX
 
112
                               "LAPIC_NMI (acpi_id[0x%02x] %s %s lint[0x%x])\n",
 
113
                               p->processor_id,
 
114
                               mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK  ],
 
115
                               mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2],
 
116
                               p->lint);
 
117
                }
 
118
                break;
 
119
 
 
120
        case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
 
121
                {
 
122
                        struct acpi_madt_local_apic_override *p =
 
123
                            (struct acpi_madt_local_apic_override *)header;
 
124
                        printk(KERN_INFO PREFIX
 
125
                               "LAPIC_ADDR_OVR (address[%p])\n",
 
126
                               (void *)(unsigned long)p->address);
 
127
                }
 
128
                break;
 
129
 
 
130
        case ACPI_MADT_TYPE_IO_SAPIC:
 
131
                {
 
132
                        struct acpi_madt_io_sapic *p =
 
133
                            (struct acpi_madt_io_sapic *)header;
 
134
                        printk(KERN_INFO PREFIX
 
135
                               "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n",
 
136
                               p->id, (void *)(unsigned long)p->address,
 
137
                               p->global_irq_base);
 
138
                }
 
139
                break;
 
140
 
 
141
        case ACPI_MADT_TYPE_LOCAL_SAPIC:
 
142
                {
 
143
                        struct acpi_madt_local_sapic *p =
 
144
                            (struct acpi_madt_local_sapic *)header;
 
145
                        printk(KERN_INFO PREFIX
 
146
                               "LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n",
 
147
                               p->processor_id, p->id, p->eid,
 
148
                               (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
 
149
                }
 
150
                break;
 
151
 
 
152
        case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
 
153
                {
 
154
                        struct acpi_madt_interrupt_source *p =
 
155
                            (struct acpi_madt_interrupt_source *)header;
 
156
                        printk(KERN_INFO PREFIX
 
157
                               "PLAT_INT_SRC (%s %s type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n",
 
158
                               mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK],
 
159
                               mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2],
 
160
                               p->type, p->id, p->eid, p->io_sapic_vector,
 
161
                               p->global_irq);
 
162
                }
 
163
                break;
 
164
 
 
165
        default:
 
166
                printk(KERN_WARNING PREFIX
 
167
                       "Found unsupported MADT entry (type = 0x%x)\n",
 
168
                       header->type);
 
169
                break;
 
170
        }
 
171
}
 
172
 
 
173
 
 
174
int __init
 
175
acpi_table_parse_entries(char *id,
 
176
                             unsigned long table_size,
 
177
                             int entry_id,
 
178
                             acpi_table_entry_handler handler,
 
179
                             unsigned int max_entries)
 
180
{
 
181
        struct acpi_table_header *table_header = NULL;
 
182
        struct acpi_subtable_header *entry;
 
183
        unsigned int count = 0;
 
184
        unsigned long table_end;
 
185
 
 
186
        if (!handler)
 
187
                return -EINVAL;
 
188
 
 
189
        if (strncmp(id, ACPI_SIG_MADT, 4) == 0)
 
190
                acpi_get_table(id, acpi_apic_instance, &table_header);
 
191
        else
 
192
                acpi_get_table(id, 0, &table_header);
 
193
 
 
194
        if (!table_header) {
 
195
                printk(KERN_WARNING PREFIX "%4.4s not present\n", id);
 
196
                return -ENODEV;
 
197
        }
 
198
 
 
199
        table_end = (unsigned long)table_header + table_header->length;
 
200
 
 
201
        /* Parse all entries looking for a match. */
 
202
 
 
203
        entry = (struct acpi_subtable_header *)
 
204
            ((unsigned long)table_header + table_size);
 
205
 
 
206
        while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) <
 
207
               table_end) {
 
208
                if (entry->type == entry_id
 
209
                    && (!max_entries || count++ < max_entries))
 
210
                        if (handler(entry, table_end))
 
211
                                return -EINVAL;
 
212
 
 
213
                entry = (struct acpi_subtable_header *)
 
214
                    ((unsigned long)entry + entry->length);
 
215
        }
 
216
        if (max_entries && count > max_entries) {
 
217
                printk(KERN_WARNING PREFIX "[%4.4s:0x%02x] ignored %i entries of "
 
218
                       "%i found\n", id, entry_id, count - max_entries, count);
 
219
        }
 
220
 
 
221
        return count;
 
222
}
 
223
 
 
224
int __init
 
225
acpi_table_parse_madt(enum acpi_madt_type id,
 
226
                      acpi_table_entry_handler handler, unsigned int max_entries)
 
227
{
 
228
        return acpi_table_parse_entries(ACPI_SIG_MADT,
 
229
                                            sizeof(struct acpi_table_madt), id,
 
230
                                            handler, max_entries);
 
231
}
 
232
 
 
233
/**
 
234
 * acpi_table_parse - find table with @id, run @handler on it
 
235
 *
 
236
 * @id: table id to find
 
237
 * @handler: handler to run
 
238
 *
 
239
 * Scan the ACPI System Descriptor Table (STD) for a table matching @id,
 
240
 * run @handler on it.  Return 0 if table found, return on if not.
 
241
 */
 
242
int __init acpi_table_parse(char *id, acpi_table_handler handler)
 
243
{
 
244
        struct acpi_table_header *table = NULL;
 
245
 
 
246
        if (!handler)
 
247
                return -EINVAL;
 
248
 
 
249
        if (strncmp(id, ACPI_SIG_MADT, 4) == 0)
 
250
                acpi_get_table(id, acpi_apic_instance, &table);
 
251
        else
 
252
                acpi_get_table(id, 0, &table);
 
253
 
 
254
        if (table) {
 
255
                handler(table);
 
256
                return 0;
 
257
        } else
 
258
                return 1;
 
259
}
 
260
 
 
261
/* 
 
262
 * The BIOS is supposed to supply a single APIC/MADT,
 
263
 * but some report two.  Provide a knob to use either.
 
264
 * (don't you wish instance 0 and 1 were not the same?)
 
265
 */
 
266
static void __init check_multiple_madt(void)
 
267
{
 
268
        struct acpi_table_header *table = NULL;
 
269
 
 
270
        acpi_get_table(ACPI_SIG_MADT, 2, &table);
 
271
        if (table) {
 
272
                printk(KERN_WARNING PREFIX
 
273
                       "BIOS bug: multiple APIC/MADT found,"
 
274
                       " using %d\n", acpi_apic_instance);
 
275
                printk(KERN_WARNING PREFIX
 
276
                       "If \"acpi_apic_instance=%d\" works better, "
 
277
                       "notify linux-acpi@vger.kernel.org\n",
 
278
                       acpi_apic_instance ? 0 : 2);
 
279
 
 
280
        } else
 
281
                acpi_apic_instance = 0;
 
282
 
 
283
        return;
 
284
}
 
285
 
 
286
/*
 
287
 * acpi_table_init()
 
288
 *
 
289
 * find RSDP, find and checksum SDT/XSDT.
 
290
 * checksum all tables, print SDT/XSDT
 
291
 *
 
292
 * result: sdt_entry[] is initialized
 
293
 */
 
294
 
 
295
int __init acpi_table_init(void)
 
296
{
 
297
        acpi_ut_init_globals();
 
298
        acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
 
299
        check_multiple_madt();
 
300
        return 0;
 
301
}
 
302
 
 
303
static int __init acpi_parse_apic_instance(char *str)
 
304
{
 
305
 
 
306
        acpi_apic_instance = simple_strtoul(str, NULL, 0);
 
307
 
 
308
        printk(KERN_NOTICE PREFIX "Shall use APIC/MADT table %d\n",
 
309
               acpi_apic_instance);
 
310
 
 
311
        return 0;
 
312
}
 
313
custom_param("acpi_apic_instance", acpi_parse_apic_instance);