blob: 5a468e2779aecf5c167e7ee4c8e433a965f43fb3 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * acpi_osl.c - OS-dependent functions ($Revision: 83 $)
3 *
4 * Copyright (C) 2000 Andrew Henroid
5 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
6 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
7 *
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 *
26 */
27
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/module.h>
29#include <linux/kernel.h>
30#include <linux/slab.h>
31#include <linux/mm.h>
32#include <linux/pci.h>
33#include <linux/smp_lock.h>
34#include <linux/interrupt.h>
35#include <linux/kmod.h>
36#include <linux/delay.h>
37#include <linux/workqueue.h>
38#include <linux/nmi.h>
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -040039#include <linux/kthread.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <acpi/acpi.h>
41#include <asm/io.h>
42#include <acpi/acpi_bus.h>
43#include <acpi/processor.h>
44#include <asm/uaccess.h>
45
46#include <linux/efi.h>
47
Linus Torvalds1da177e2005-04-16 15:20:36 -070048#define _COMPONENT ACPI_OS_SERVICES
Len Brown4be44fc2005-08-05 00:44:28 -040049ACPI_MODULE_NAME("osl")
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#define PREFIX "ACPI: "
Len Brown4be44fc2005-08-05 00:44:28 -040051struct acpi_os_dpc {
52 acpi_osd_exec_callback function;
53 void *context;
Linus Torvalds1da177e2005-04-16 15:20:36 -070054};
55
56#ifdef CONFIG_ACPI_CUSTOM_DSDT
57#include CONFIG_ACPI_CUSTOM_DSDT_FILE
58#endif
59
60#ifdef ENABLE_DEBUGGER
61#include <linux/kdb.h>
62
63/* stuff for debugger support */
64int acpi_in_debugger;
65EXPORT_SYMBOL(acpi_in_debugger);
66
67extern char line_buf[80];
Len Brown4be44fc2005-08-05 00:44:28 -040068#endif /*ENABLE_DEBUGGER */
Linus Torvalds1da177e2005-04-16 15:20:36 -070069
Luming Yu30e332f2005-08-12 00:31:00 -040070int acpi_specific_hotkey_enabled = TRUE;
Luming Yufb9802f2005-03-18 18:03:45 -050071EXPORT_SYMBOL(acpi_specific_hotkey_enabled);
72
Linus Torvalds1da177e2005-04-16 15:20:36 -070073static unsigned int acpi_irq_irq;
74static acpi_osd_handler acpi_irq_handler;
75static void *acpi_irq_context;
76static struct workqueue_struct *kacpid_wq;
77
Len Brown4be44fc2005-08-05 00:44:28 -040078acpi_status acpi_os_initialize(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070079{
80 return AE_OK;
81}
82
Len Brown4be44fc2005-08-05 00:44:28 -040083acpi_status acpi_os_initialize1(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070084{
85 /*
86 * Initialize PCI configuration space access, as we'll need to access
87 * it while walking the namespace (bus 0 and root bridges w/ _BBNs).
88 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 if (!raw_pci_ops) {
Len Brown4be44fc2005-08-05 00:44:28 -040090 printk(KERN_ERR PREFIX
91 "Access to PCI configuration space unavailable\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 return AE_NULL_ENTRY;
93 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070094 kacpid_wq = create_singlethread_workqueue("kacpid");
95 BUG_ON(!kacpid_wq);
96
97 return AE_OK;
98}
99
Len Brown4be44fc2005-08-05 00:44:28 -0400100acpi_status acpi_os_terminate(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101{
102 if (acpi_irq_handler) {
103 acpi_os_remove_interrupt_handler(acpi_irq_irq,
104 acpi_irq_handler);
105 }
106
107 destroy_workqueue(kacpid_wq);
108
109 return AE_OK;
110}
111
Len Brown4be44fc2005-08-05 00:44:28 -0400112void acpi_os_printf(const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113{
114 va_list args;
115 va_start(args, fmt);
116 acpi_os_vprintf(fmt, args);
117 va_end(args);
118}
Len Brown4be44fc2005-08-05 00:44:28 -0400119
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120EXPORT_SYMBOL(acpi_os_printf);
121
Len Brown4be44fc2005-08-05 00:44:28 -0400122void acpi_os_vprintf(const char *fmt, va_list args)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123{
124 static char buffer[512];
Len Brown4be44fc2005-08-05 00:44:28 -0400125
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 vsprintf(buffer, fmt, args);
127
128#ifdef ENABLE_DEBUGGER
129 if (acpi_in_debugger) {
130 kdb_printf("%s", buffer);
131 } else {
132 printk("%s", buffer);
133 }
134#else
135 printk("%s", buffer);
136#endif
137}
138
Thomas Renningera6fc6722006-06-26 23:58:43 -0400139
David Shaohua Li11e981f12005-08-03 23:46:33 -0400140extern int acpi_in_resume;
Len Brown4be44fc2005-08-05 00:44:28 -0400141void *acpi_os_allocate(acpi_size size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142{
David Shaohua Li11e981f12005-08-03 23:46:33 -0400143 if (acpi_in_resume)
144 return kmalloc(size, GFP_ATOMIC);
145 else
146 return kmalloc(size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147}
148
Len Brown4be44fc2005-08-05 00:44:28 -0400149void acpi_os_free(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150{
151 kfree(ptr);
152}
Len Brown4be44fc2005-08-05 00:44:28 -0400153
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154EXPORT_SYMBOL(acpi_os_free);
155
Len Brown4be44fc2005-08-05 00:44:28 -0400156acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157{
158 if (efi_enabled) {
159 addr->pointer_type = ACPI_PHYSICAL_POINTER;
Bjorn Helgaasb2c99e32006-03-26 01:37:08 -0800160 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
161 addr->pointer.physical = efi.acpi20;
162 else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
163 addr->pointer.physical = efi.acpi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 else {
Len Brown4be44fc2005-08-05 00:44:28 -0400165 printk(KERN_ERR PREFIX
166 "System description tables not found\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 return AE_NOT_FOUND;
168 }
169 } else {
170 if (ACPI_FAILURE(acpi_find_root_pointer(flags, addr))) {
Len Brown4be44fc2005-08-05 00:44:28 -0400171 printk(KERN_ERR PREFIX
172 "System description tables not found\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 return AE_NOT_FOUND;
174 }
175 }
176
177 return AE_OK;
178}
179
180acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400181acpi_os_map_memory(acpi_physical_address phys, acpi_size size,
182 void __iomem ** virt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183{
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800184 if (phys > ULONG_MAX) {
185 printk(KERN_ERR PREFIX "Cannot map memory that high\n");
186 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 }
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800188 /*
189 * ioremap checks to ensure this is in reserved space
190 */
191 *virt = ioremap((unsigned long)phys, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192
193 if (!*virt)
194 return AE_NO_MEMORY;
195
196 return AE_OK;
197}
Kylene Jo Hall55a82ab2006-01-08 01:03:15 -0800198EXPORT_SYMBOL_GPL(acpi_os_map_memory);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199
Len Brown4be44fc2005-08-05 00:44:28 -0400200void acpi_os_unmap_memory(void __iomem * virt, acpi_size size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201{
202 iounmap(virt);
203}
Kylene Jo Hall55a82ab2006-01-08 01:03:15 -0800204EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
206#ifdef ACPI_FUTURE_USAGE
207acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400208acpi_os_get_physical_address(void *virt, acpi_physical_address * phys)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209{
Len Brown4be44fc2005-08-05 00:44:28 -0400210 if (!phys || !virt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 return AE_BAD_PARAMETER;
212
213 *phys = virt_to_phys(virt);
214
215 return AE_OK;
216}
217#endif
218
219#define ACPI_MAX_OVERRIDE_LEN 100
220
221static char acpi_os_name[ACPI_MAX_OVERRIDE_LEN];
222
223acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400224acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
225 acpi_string * new_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226{
227 if (!init_val || !new_val)
228 return AE_BAD_PARAMETER;
229
230 *new_val = NULL;
Len Brown4be44fc2005-08-05 00:44:28 -0400231 if (!memcmp(init_val->name, "_OS_", 4) && strlen(acpi_os_name)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 printk(KERN_INFO PREFIX "Overriding _OS definition to '%s'\n",
Len Brown4be44fc2005-08-05 00:44:28 -0400233 acpi_os_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 *new_val = acpi_os_name;
235 }
236
237 return AE_OK;
238}
239
240acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400241acpi_os_table_override(struct acpi_table_header * existing_table,
242 struct acpi_table_header ** new_table)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243{
244 if (!existing_table || !new_table)
245 return AE_BAD_PARAMETER;
246
247#ifdef CONFIG_ACPI_CUSTOM_DSDT
248 if (strncmp(existing_table->signature, "DSDT", 4) == 0)
Len Brown4be44fc2005-08-05 00:44:28 -0400249 *new_table = (struct acpi_table_header *)AmlCode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 else
251 *new_table = NULL;
252#else
253 *new_table = NULL;
254#endif
255 return AE_OK;
256}
257
Len Brown4be44fc2005-08-05 00:44:28 -0400258static irqreturn_t acpi_irq(int irq, void *dev_id, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259{
Len Brown4be44fc2005-08-05 00:44:28 -0400260 return (*acpi_irq_handler) (acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261}
262
263acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400264acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
265 void *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266{
267 unsigned int irq;
268
269 /*
270 * Ignore the GSI from the core, and use the value in our copy of the
271 * FADT. It may not be the same if an interrupt source override exists
272 * for the SCI.
273 */
274 gsi = acpi_fadt.sci_int;
275 if (acpi_gsi_to_irq(gsi, &irq) < 0) {
276 printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n",
277 gsi);
278 return AE_OK;
279 }
280
281 acpi_irq_handler = handler;
282 acpi_irq_context = context;
Thomas Gleixnerdace1452006-07-01 19:29:38 -0700283 if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq);
285 return AE_NOT_ACQUIRED;
286 }
287 acpi_irq_irq = irq;
288
289 return AE_OK;
290}
291
Len Brown4be44fc2005-08-05 00:44:28 -0400292acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293{
294 if (irq) {
295 free_irq(irq, acpi_irq);
296 acpi_irq_handler = NULL;
297 acpi_irq_irq = 0;
298 }
299
300 return AE_OK;
301}
302
303/*
304 * Running in interpreter thread context, safe to sleep
305 */
306
Len Brown4be44fc2005-08-05 00:44:28 -0400307void acpi_os_sleep(acpi_integer ms)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308{
Nishanth Aravamudan01a527e2005-11-07 01:01:14 -0800309 schedule_timeout_interruptible(msecs_to_jiffies(ms));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310}
Len Brown4be44fc2005-08-05 00:44:28 -0400311
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312EXPORT_SYMBOL(acpi_os_sleep);
313
Len Brown4be44fc2005-08-05 00:44:28 -0400314void acpi_os_stall(u32 us)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315{
316 while (us) {
317 u32 delay = 1000;
318
319 if (delay > us)
320 delay = us;
321 udelay(delay);
322 touch_nmi_watchdog();
323 us -= delay;
324 }
325}
Len Brown4be44fc2005-08-05 00:44:28 -0400326
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327EXPORT_SYMBOL(acpi_os_stall);
328
329/*
330 * Support ACPI 3.0 AML Timer operand
331 * Returns 64-bit free-running, monotonically increasing timer
332 * with 100ns granularity
333 */
Len Brown4be44fc2005-08-05 00:44:28 -0400334u64 acpi_os_get_timer(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335{
336 static u64 t;
337
338#ifdef CONFIG_HPET
339 /* TBD: use HPET if available */
340#endif
341
342#ifdef CONFIG_X86_PM_TIMER
343 /* TBD: default to PM timer if HPET was not available */
344#endif
345 if (!t)
346 printk(KERN_ERR PREFIX "acpi_os_get_timer() TBD\n");
347
348 return ++t;
349}
350
Len Brown4be44fc2005-08-05 00:44:28 -0400351acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352{
353 u32 dummy;
354
355 if (!value)
356 value = &dummy;
357
Len Brown4be44fc2005-08-05 00:44:28 -0400358 switch (width) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 case 8:
Len Brown4be44fc2005-08-05 00:44:28 -0400360 *(u8 *) value = inb(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 break;
362 case 16:
Len Brown4be44fc2005-08-05 00:44:28 -0400363 *(u16 *) value = inw(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 break;
365 case 32:
Len Brown4be44fc2005-08-05 00:44:28 -0400366 *(u32 *) value = inl(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 break;
368 default:
369 BUG();
370 }
371
372 return AE_OK;
373}
Len Brown4be44fc2005-08-05 00:44:28 -0400374
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375EXPORT_SYMBOL(acpi_os_read_port);
376
Len Brown4be44fc2005-08-05 00:44:28 -0400377acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378{
Len Brown4be44fc2005-08-05 00:44:28 -0400379 switch (width) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 case 8:
381 outb(value, port);
382 break;
383 case 16:
384 outw(value, port);
385 break;
386 case 32:
387 outl(value, port);
388 break;
389 default:
390 BUG();
391 }
392
393 return AE_OK;
394}
Len Brown4be44fc2005-08-05 00:44:28 -0400395
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396EXPORT_SYMBOL(acpi_os_write_port);
397
398acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400399acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400{
Len Brown4be44fc2005-08-05 00:44:28 -0400401 u32 dummy;
402 void __iomem *virt_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800404 virt_addr = ioremap(phys_addr, width);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 if (!value)
406 value = &dummy;
407
408 switch (width) {
409 case 8:
Len Brown4be44fc2005-08-05 00:44:28 -0400410 *(u8 *) value = readb(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 break;
412 case 16:
Len Brown4be44fc2005-08-05 00:44:28 -0400413 *(u16 *) value = readw(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 break;
415 case 32:
Len Brown4be44fc2005-08-05 00:44:28 -0400416 *(u32 *) value = readl(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 break;
418 default:
419 BUG();
420 }
421
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800422 iounmap(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
424 return AE_OK;
425}
426
427acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400428acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429{
Len Brown4be44fc2005-08-05 00:44:28 -0400430 void __iomem *virt_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800432 virt_addr = ioremap(phys_addr, width);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433
434 switch (width) {
435 case 8:
436 writeb(value, virt_addr);
437 break;
438 case 16:
439 writew(value, virt_addr);
440 break;
441 case 32:
442 writel(value, virt_addr);
443 break;
444 default:
445 BUG();
446 }
447
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800448 iounmap(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449
450 return AE_OK;
451}
452
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400454acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
455 void *value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456{
457 int result, size;
458
459 if (!value)
460 return AE_BAD_PARAMETER;
461
462 switch (width) {
463 case 8:
464 size = 1;
465 break;
466 case 16:
467 size = 2;
468 break;
469 case 32:
470 size = 4;
471 break;
472 default:
473 return AE_ERROR;
474 }
475
476 BUG_ON(!raw_pci_ops);
477
478 result = raw_pci_ops->read(pci_id->segment, pci_id->bus,
Len Brown4be44fc2005-08-05 00:44:28 -0400479 PCI_DEVFN(pci_id->device, pci_id->function),
480 reg, size, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481
482 return (result ? AE_ERROR : AE_OK);
483}
Len Brown4be44fc2005-08-05 00:44:28 -0400484
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485EXPORT_SYMBOL(acpi_os_read_pci_configuration);
486
487acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400488acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
489 acpi_integer value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490{
491 int result, size;
492
493 switch (width) {
494 case 8:
495 size = 1;
496 break;
497 case 16:
498 size = 2;
499 break;
500 case 32:
501 size = 4;
502 break;
503 default:
504 return AE_ERROR;
505 }
506
507 BUG_ON(!raw_pci_ops);
508
509 result = raw_pci_ops->write(pci_id->segment, pci_id->bus,
Len Brown4be44fc2005-08-05 00:44:28 -0400510 PCI_DEVFN(pci_id->device, pci_id->function),
511 reg, size, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
513 return (result ? AE_ERROR : AE_OK);
514}
515
516/* TODO: Change code to take advantage of driver model more */
Len Brown4be44fc2005-08-05 00:44:28 -0400517static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */
518 acpi_handle chandle, /* current node */
519 struct acpi_pci_id **id,
520 int *is_bridge, u8 * bus_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521{
Len Brown4be44fc2005-08-05 00:44:28 -0400522 acpi_handle handle;
523 struct acpi_pci_id *pci_id = *id;
524 acpi_status status;
525 unsigned long temp;
526 acpi_object_type type;
527 u8 tu8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528
529 acpi_get_parent(chandle, &handle);
530 if (handle != rhandle) {
Len Brown4be44fc2005-08-05 00:44:28 -0400531 acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge,
532 bus_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533
534 status = acpi_get_type(handle, &type);
Len Brown4be44fc2005-08-05 00:44:28 -0400535 if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 return;
537
Len Brown4be44fc2005-08-05 00:44:28 -0400538 status =
539 acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
540 &temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 if (ACPI_SUCCESS(status)) {
Len Brown4be44fc2005-08-05 00:44:28 -0400542 pci_id->device = ACPI_HIWORD(ACPI_LODWORD(temp));
543 pci_id->function = ACPI_LOWORD(ACPI_LODWORD(temp));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544
545 if (*is_bridge)
546 pci_id->bus = *bus_number;
547
548 /* any nicer way to get bus number of bridge ? */
Len Brown4be44fc2005-08-05 00:44:28 -0400549 status =
550 acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8,
551 8);
552 if (ACPI_SUCCESS(status)
553 && ((tu8 & 0x7f) == 1 || (tu8 & 0x7f) == 2)) {
554 status =
555 acpi_os_read_pci_configuration(pci_id, 0x18,
556 &tu8, 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 if (!ACPI_SUCCESS(status)) {
558 /* Certainly broken... FIX ME */
559 return;
560 }
561 *is_bridge = 1;
562 pci_id->bus = tu8;
Len Brown4be44fc2005-08-05 00:44:28 -0400563 status =
564 acpi_os_read_pci_configuration(pci_id, 0x19,
565 &tu8, 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 if (ACPI_SUCCESS(status)) {
567 *bus_number = tu8;
568 }
569 } else
570 *is_bridge = 0;
571 }
572 }
573}
574
Len Brown4be44fc2005-08-05 00:44:28 -0400575void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */
576 acpi_handle chandle, /* current node */
577 struct acpi_pci_id **id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578{
579 int is_bridge = 1;
580 u8 bus_number = (*id)->bus;
581
582 acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number);
583}
584
Len Brown4be44fc2005-08-05 00:44:28 -0400585static void acpi_os_execute_deferred(void *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586{
Len Brown4be44fc2005-08-05 00:44:28 -0400587 struct acpi_os_dpc *dpc = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589
Len Brown4be44fc2005-08-05 00:44:28 -0400590 dpc = (struct acpi_os_dpc *)context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 if (!dpc) {
Len Brown64684632006-06-26 23:41:38 -0400592 printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
Patrick Mocheld550d982006-06-27 00:41:40 -0400593 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 }
595
596 dpc->function(dpc->context);
597
598 kfree(dpc);
599
Patrick Mocheld550d982006-06-27 00:41:40 -0400600 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601}
602
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400603static int acpi_os_execute_thread(void *context)
604{
605 struct acpi_os_dpc *dpc = (struct acpi_os_dpc *)context;
606 if (dpc) {
607 dpc->function(dpc->context);
608 kfree(dpc);
609 }
610 do_exit(0);
611}
612
613/*******************************************************************************
614 *
615 * FUNCTION: acpi_os_execute
616 *
617 * PARAMETERS: Type - Type of the callback
618 * Function - Function to be executed
619 * Context - Function parameters
620 *
621 * RETURN: Status
622 *
623 * DESCRIPTION: Depending on type, either queues function for deferred execution or
624 * immediately executes function on a separate thread.
625 *
626 ******************************************************************************/
627
628acpi_status acpi_os_execute(acpi_execute_type type,
Len Brown4be44fc2005-08-05 00:44:28 -0400629 acpi_osd_exec_callback function, void *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630{
Len Brown4be44fc2005-08-05 00:44:28 -0400631 acpi_status status = AE_OK;
632 struct acpi_os_dpc *dpc;
633 struct work_struct *task;
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400634 struct task_struct *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
636 if (!function)
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400637 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 /*
639 * Allocate/initialize DPC structure. Note that this memory will be
640 * freed by the callee. The kernel handles the tq_struct list in a
641 * way that allows us to also free its memory inside the callee.
642 * Because we may want to schedule several tasks with different
643 * parameters we can't use the approach some kernel code uses of
644 * having a static tq_struct.
645 * We can save time and code by allocating the DPC and tq_structs
646 * from the same memory.
647 */
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400648 if (type == OSL_NOTIFY_HANDLER) {
649 dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_KERNEL);
650 } else {
651 dpc = kmalloc(sizeof(struct acpi_os_dpc) +
652 sizeof(struct work_struct), GFP_ATOMIC);
653 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 if (!dpc)
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400655 return AE_NO_MEMORY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 dpc->function = function;
657 dpc->context = context;
658
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400659 if (type == OSL_NOTIFY_HANDLER) {
660 p = kthread_create(acpi_os_execute_thread, dpc, "kacpid_notify");
661 if (!IS_ERR(p)) {
662 wake_up_process(p);
663 } else {
664 status = AE_NO_MEMORY;
665 kfree(dpc);
666 }
667 } else {
668 task = (void *)(dpc + 1);
669 INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc);
670 if (!queue_work(kacpid_wq, task)) {
671 status = AE_ERROR;
672 kfree(dpc);
673 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 }
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400675 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676}
Len Brown4be44fc2005-08-05 00:44:28 -0400677
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400678EXPORT_SYMBOL(acpi_os_execute);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
Len Brown4be44fc2005-08-05 00:44:28 -0400680void acpi_os_wait_events_complete(void *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681{
682 flush_workqueue(kacpid_wq);
683}
Len Brown4be44fc2005-08-05 00:44:28 -0400684
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685EXPORT_SYMBOL(acpi_os_wait_events_complete);
686
687/*
688 * Allocate the memory for a spinlock and initialize it.
689 */
Bob Moore967440e2006-06-23 17:04:00 -0400690acpi_status acpi_os_create_lock(acpi_spinlock * handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691{
Bob Moore967440e2006-06-23 17:04:00 -0400692 spin_lock_init(*handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
Patrick Mocheld550d982006-06-27 00:41:40 -0400694 return AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695}
696
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697/*
698 * Deallocate the memory for a spinlock.
699 */
Bob Moore967440e2006-06-23 17:04:00 -0400700void acpi_os_delete_lock(acpi_spinlock handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701{
Patrick Mocheld550d982006-06-27 00:41:40 -0400702 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703}
704
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400706acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707{
Len Brown4be44fc2005-08-05 00:44:28 -0400708 struct semaphore *sem = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
711 sem = acpi_os_allocate(sizeof(struct semaphore));
712 if (!sem)
Patrick Mocheld550d982006-06-27 00:41:40 -0400713 return AE_NO_MEMORY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 memset(sem, 0, sizeof(struct semaphore));
715
716 sema_init(sem, initial_units);
717
Len Brown4be44fc2005-08-05 00:44:28 -0400718 *handle = (acpi_handle *) sem;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719
Len Brown4be44fc2005-08-05 00:44:28 -0400720 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Creating semaphore[%p|%d].\n",
721 *handle, initial_units));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722
Patrick Mocheld550d982006-06-27 00:41:40 -0400723 return AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
Len Brown4be44fc2005-08-05 00:44:28 -0400726EXPORT_SYMBOL(acpi_os_create_semaphore);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727
728/*
729 * TODO: A better way to delete semaphores? Linux doesn't have a
730 * 'delete_semaphore()' function -- may result in an invalid
731 * pointer dereference for non-synchronized consumers. Should
732 * we at least check for blocked threads and signal/cancel them?
733 */
734
Len Brown4be44fc2005-08-05 00:44:28 -0400735acpi_status acpi_os_delete_semaphore(acpi_handle handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736{
Len Brown4be44fc2005-08-05 00:44:28 -0400737 struct semaphore *sem = (struct semaphore *)handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739
740 if (!sem)
Patrick Mocheld550d982006-06-27 00:41:40 -0400741 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742
Len Brown4be44fc2005-08-05 00:44:28 -0400743 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744
Len Brown4be44fc2005-08-05 00:44:28 -0400745 acpi_os_free(sem);
746 sem = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
Patrick Mocheld550d982006-06-27 00:41:40 -0400748 return AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750
Len Brown4be44fc2005-08-05 00:44:28 -0400751EXPORT_SYMBOL(acpi_os_delete_semaphore);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752
753/*
754 * TODO: The kernel doesn't have a 'down_timeout' function -- had to
755 * improvise. The process is to sleep for one scheduler quantum
756 * until the semaphore becomes available. Downside is that this
757 * may result in starvation for timeout-based waits when there's
758 * lots of semaphore activity.
759 *
760 * TODO: Support for units > 1?
761 */
Len Brown4be44fc2005-08-05 00:44:28 -0400762acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763{
Len Brown4be44fc2005-08-05 00:44:28 -0400764 acpi_status status = AE_OK;
765 struct semaphore *sem = (struct semaphore *)handle;
766 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768
769 if (!sem || (units < 1))
Patrick Mocheld550d982006-06-27 00:41:40 -0400770 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771
772 if (units > 1)
Patrick Mocheld550d982006-06-27 00:41:40 -0400773 return AE_SUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774
Len Brown4be44fc2005-08-05 00:44:28 -0400775 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n",
776 handle, units, timeout));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777
Len Brown4be44fc2005-08-05 00:44:28 -0400778 switch (timeout) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 /*
780 * No Wait:
781 * --------
782 * A zero timeout value indicates that we shouldn't wait - just
783 * acquire the semaphore if available otherwise return AE_TIME
784 * (a.k.a. 'would block').
785 */
Len Brown4be44fc2005-08-05 00:44:28 -0400786 case 0:
787 if (down_trylock(sem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 status = AE_TIME;
789 break;
790
791 /*
792 * Wait Indefinitely:
793 * ------------------
794 */
Len Brown4be44fc2005-08-05 00:44:28 -0400795 case ACPI_WAIT_FOREVER:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 down(sem);
797 break;
798
799 /*
800 * Wait w/ Timeout:
801 * ----------------
802 */
Len Brown4be44fc2005-08-05 00:44:28 -0400803 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 // TODO: A better timeout algorithm?
805 {
806 int i = 0;
Len Brown4be44fc2005-08-05 00:44:28 -0400807 static const int quantum_ms = 1000 / HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808
809 ret = down_trylock(sem);
Yu Lumingdacd9b82005-12-31 01:45:00 -0500810 for (i = timeout; (i > 0 && ret != 0); i -= quantum_ms) {
Nishanth Aravamudan01a527e2005-11-07 01:01:14 -0800811 schedule_timeout_interruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 ret = down_trylock(sem);
813 }
Len Brown4be44fc2005-08-05 00:44:28 -0400814
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 if (ret != 0)
816 status = AE_TIME;
817 }
818 break;
819 }
820
821 if (ACPI_FAILURE(status)) {
Bjorn Helgaas9e7e2c02006-04-27 05:25:00 -0400822 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
Thomas Renningera6fc6722006-06-26 23:58:43 -0400823 "Failed to acquire semaphore[%p|%d|%d], %s",
Len Brown4be44fc2005-08-05 00:44:28 -0400824 handle, units, timeout,
825 acpi_format_exception(status)));
826 } else {
827 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
Thomas Renningera6fc6722006-06-26 23:58:43 -0400828 "Acquired semaphore[%p|%d|%d]", handle,
Len Brown4be44fc2005-08-05 00:44:28 -0400829 units, timeout));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 }
831
Patrick Mocheld550d982006-06-27 00:41:40 -0400832 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834
Len Brown4be44fc2005-08-05 00:44:28 -0400835EXPORT_SYMBOL(acpi_os_wait_semaphore);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836
837/*
838 * TODO: Support for units > 1?
839 */
Len Brown4be44fc2005-08-05 00:44:28 -0400840acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841{
Len Brown4be44fc2005-08-05 00:44:28 -0400842 struct semaphore *sem = (struct semaphore *)handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844
845 if (!sem || (units < 1))
Patrick Mocheld550d982006-06-27 00:41:40 -0400846 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847
848 if (units > 1)
Patrick Mocheld550d982006-06-27 00:41:40 -0400849 return AE_SUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850
Len Brown4be44fc2005-08-05 00:44:28 -0400851 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle,
852 units));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853
854 up(sem);
855
Patrick Mocheld550d982006-06-27 00:41:40 -0400856 return AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857}
Len Brown4be44fc2005-08-05 00:44:28 -0400858
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859EXPORT_SYMBOL(acpi_os_signal_semaphore);
860
861#ifdef ACPI_FUTURE_USAGE
Len Brown4be44fc2005-08-05 00:44:28 -0400862u32 acpi_os_get_line(char *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863{
864
865#ifdef ENABLE_DEBUGGER
866 if (acpi_in_debugger) {
867 u32 chars;
868
869 kdb_read(buffer, sizeof(line_buf));
870
871 /* remove the CR kdb includes */
872 chars = strlen(buffer) - 1;
873 buffer[chars] = '\0';
874 }
875#endif
876
877 return 0;
878}
Len Brown4be44fc2005-08-05 00:44:28 -0400879#endif /* ACPI_FUTURE_USAGE */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880
881/* Assumes no unreadable holes inbetween */
Len Brown4be44fc2005-08-05 00:44:28 -0400882u8 acpi_os_readable(void *ptr, acpi_size len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883{
Len Brown4be44fc2005-08-05 00:44:28 -0400884#if defined(__i386__) || defined(__x86_64__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 char tmp;
Len Brown4be44fc2005-08-05 00:44:28 -0400886 return !__get_user(tmp, (char __user *)ptr)
887 && !__get_user(tmp, (char __user *)ptr + len - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888#endif
889 return 1;
890}
891
892#ifdef ACPI_FUTURE_USAGE
Len Brown4be44fc2005-08-05 00:44:28 -0400893u8 acpi_os_writable(void *ptr, acpi_size len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894{
895 /* could do dummy write (racy) or a kernel page table lookup.
896 The later may be difficult at early boot when kmap doesn't work yet. */
897 return 1;
898}
899#endif
900
Len Brown4be44fc2005-08-05 00:44:28 -0400901acpi_status acpi_os_signal(u32 function, void *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902{
Len Brown4be44fc2005-08-05 00:44:28 -0400903 switch (function) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 case ACPI_SIGNAL_FATAL:
905 printk(KERN_ERR PREFIX "Fatal opcode executed\n");
906 break;
907 case ACPI_SIGNAL_BREAKPOINT:
908 /*
909 * AML Breakpoint
910 * ACPI spec. says to treat it as a NOP unless
911 * you are debugging. So if/when we integrate
912 * AML debugger into the kernel debugger its
913 * hook will go here. But until then it is
914 * not useful to print anything on breakpoints.
915 */
916 break;
917 default:
918 break;
919 }
920
921 return AE_OK;
922}
Len Brown4be44fc2005-08-05 00:44:28 -0400923
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924EXPORT_SYMBOL(acpi_os_signal);
925
Len Brown4be44fc2005-08-05 00:44:28 -0400926static int __init acpi_os_name_setup(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927{
928 char *p = acpi_os_name;
Len Brown4be44fc2005-08-05 00:44:28 -0400929 int count = ACPI_MAX_OVERRIDE_LEN - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930
931 if (!str || !*str)
932 return 0;
933
934 for (; count-- && str && *str; str++) {
935 if (isalnum(*str) || *str == ' ' || *str == ':')
936 *p++ = *str;
937 else if (*str == '\'' || *str == '"')
938 continue;
939 else
940 break;
941 }
942 *p = 0;
943
944 return 1;
Len Brown4be44fc2005-08-05 00:44:28 -0400945
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946}
947
948__setup("acpi_os_name=", acpi_os_name_setup);
949
950/*
951 * _OSI control
952 * empty string disables _OSI
953 * TBD additional string adds to _OSI
954 */
Len Brown4be44fc2005-08-05 00:44:28 -0400955static int __init acpi_osi_setup(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956{
957 if (str == NULL || *str == '\0') {
958 printk(KERN_INFO PREFIX "_OSI method disabled\n");
959 acpi_gbl_create_osi_method = FALSE;
Len Brown4be44fc2005-08-05 00:44:28 -0400960 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 /* TBD */
Len Brown4be44fc2005-08-05 00:44:28 -0400962 printk(KERN_ERR PREFIX "_OSI additional string ignored -- %s\n",
963 str);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 }
965
966 return 1;
967}
968
969__setup("acpi_osi=", acpi_osi_setup);
970
971/* enable serialization to combat AE_ALREADY_EXISTS errors */
Len Brown4be44fc2005-08-05 00:44:28 -0400972static int __init acpi_serialize_setup(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973{
974 printk(KERN_INFO PREFIX "serialize enabled\n");
975
976 acpi_gbl_all_methods_serialized = TRUE;
977
978 return 1;
979}
980
981__setup("acpi_serialize", acpi_serialize_setup);
982
983/*
984 * Wake and Run-Time GPES are expected to be separate.
985 * We disable wake-GPEs at run-time to prevent spurious
986 * interrupts.
987 *
988 * However, if a system exists that shares Wake and
989 * Run-time events on the same GPE this flag is available
990 * to tell Linux to keep the wake-time GPEs enabled at run-time.
991 */
Len Brown4be44fc2005-08-05 00:44:28 -0400992static int __init acpi_wake_gpes_always_on_setup(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993{
994 printk(KERN_INFO PREFIX "wake GPEs not disabled\n");
995
996 acpi_gbl_leave_wake_gpes_disabled = FALSE;
997
998 return 1;
999}
1000
1001__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
1002
Adrian Bunk8713cbe2005-09-02 17:16:48 -04001003static int __init acpi_hotkey_setup(char *str)
Luming Yufb9802f2005-03-18 18:03:45 -05001004{
Luming Yu30e332f2005-08-12 00:31:00 -04001005 acpi_specific_hotkey_enabled = FALSE;
Luming Yufb9802f2005-03-18 18:03:45 -05001006 return 1;
1007}
1008
Luming Yu30e332f2005-08-12 00:31:00 -04001009__setup("acpi_generic_hotkey", acpi_hotkey_setup);
Luming Yufb9802f2005-03-18 18:03:45 -05001010
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011/*
1012 * max_cstate is defined in the base kernel so modules can
1013 * change it w/o depending on the state of the processor module.
1014 */
1015unsigned int max_cstate = ACPI_PROCESSOR_MAX_POWER;
1016
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017EXPORT_SYMBOL(max_cstate);
Robert Moore73459f72005-06-24 00:00:00 -04001018
1019/*
1020 * Acquire a spinlock.
1021 *
1022 * handle is a pointer to the spinlock_t.
Robert Moore73459f72005-06-24 00:00:00 -04001023 */
1024
Bob Moore967440e2006-06-23 17:04:00 -04001025acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp)
Robert Moore73459f72005-06-24 00:00:00 -04001026{
Bob Mooreb8e4d892006-01-27 16:43:00 -05001027 acpi_cpu_flags flags;
Bob Moore967440e2006-06-23 17:04:00 -04001028 spin_lock_irqsave(lockp, flags);
Robert Moore73459f72005-06-24 00:00:00 -04001029 return flags;
1030}
1031
1032/*
1033 * Release a spinlock. See above.
1034 */
1035
Bob Moore967440e2006-06-23 17:04:00 -04001036void acpi_os_release_lock(acpi_spinlock lockp, acpi_cpu_flags flags)
Robert Moore73459f72005-06-24 00:00:00 -04001037{
Bob Moore967440e2006-06-23 17:04:00 -04001038 spin_unlock_irqrestore(lockp, flags);
Robert Moore73459f72005-06-24 00:00:00 -04001039}
1040
Robert Moore73459f72005-06-24 00:00:00 -04001041#ifndef ACPI_USE_LOCAL_CACHE
1042
1043/*******************************************************************************
1044 *
1045 * FUNCTION: acpi_os_create_cache
1046 *
Bob Mooreb229cf92006-04-21 17:15:00 -04001047 * PARAMETERS: name - Ascii name for the cache
1048 * size - Size of each cached object
1049 * depth - Maximum depth of the cache (in objects) <ignored>
1050 * cache - Where the new cache object is returned
Robert Moore73459f72005-06-24 00:00:00 -04001051 *
Bob Mooreb229cf92006-04-21 17:15:00 -04001052 * RETURN: status
Robert Moore73459f72005-06-24 00:00:00 -04001053 *
1054 * DESCRIPTION: Create a cache object
1055 *
1056 ******************************************************************************/
1057
1058acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -04001059acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache)
Robert Moore73459f72005-06-24 00:00:00 -04001060{
Len Brown4be44fc2005-08-05 00:44:28 -04001061 *cache = kmem_cache_create(name, size, 0, 0, NULL, NULL);
Bob Mooreb229cf92006-04-21 17:15:00 -04001062 if (cache == NULL)
1063 return AE_ERROR;
1064 else
1065 return AE_OK;
Robert Moore73459f72005-06-24 00:00:00 -04001066}
1067
1068/*******************************************************************************
1069 *
1070 * FUNCTION: acpi_os_purge_cache
1071 *
1072 * PARAMETERS: Cache - Handle to cache object
1073 *
1074 * RETURN: Status
1075 *
1076 * DESCRIPTION: Free all objects within the requested cache.
1077 *
1078 ******************************************************************************/
1079
Len Brown4be44fc2005-08-05 00:44:28 -04001080acpi_status acpi_os_purge_cache(acpi_cache_t * cache)
Robert Moore73459f72005-06-24 00:00:00 -04001081{
Len Brown4be44fc2005-08-05 00:44:28 -04001082 (void)kmem_cache_shrink(cache);
1083 return (AE_OK);
Robert Moore73459f72005-06-24 00:00:00 -04001084}
1085
1086/*******************************************************************************
1087 *
1088 * FUNCTION: acpi_os_delete_cache
1089 *
1090 * PARAMETERS: Cache - Handle to cache object
1091 *
1092 * RETURN: Status
1093 *
1094 * DESCRIPTION: Free all objects within the requested cache and delete the
1095 * cache object.
1096 *
1097 ******************************************************************************/
1098
Len Brown4be44fc2005-08-05 00:44:28 -04001099acpi_status acpi_os_delete_cache(acpi_cache_t * cache)
Robert Moore73459f72005-06-24 00:00:00 -04001100{
Len Brown4be44fc2005-08-05 00:44:28 -04001101 (void)kmem_cache_destroy(cache);
1102 return (AE_OK);
Robert Moore73459f72005-06-24 00:00:00 -04001103}
1104
1105/*******************************************************************************
1106 *
1107 * FUNCTION: acpi_os_release_object
1108 *
1109 * PARAMETERS: Cache - Handle to cache object
1110 * Object - The object to be released
1111 *
1112 * RETURN: None
1113 *
1114 * DESCRIPTION: Release an object to the specified cache. If cache is full,
1115 * the object is deleted.
1116 *
1117 ******************************************************************************/
1118
Len Brown4be44fc2005-08-05 00:44:28 -04001119acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
Robert Moore73459f72005-06-24 00:00:00 -04001120{
Len Brown4be44fc2005-08-05 00:44:28 -04001121 kmem_cache_free(cache, object);
1122 return (AE_OK);
Robert Moore73459f72005-06-24 00:00:00 -04001123}
1124
1125/*******************************************************************************
1126 *
1127 * FUNCTION: acpi_os_acquire_object
1128 *
1129 * PARAMETERS: Cache - Handle to cache object
1130 * ReturnObject - Where the object is returned
1131 *
1132 * RETURN: Status
1133 *
Bob Moore61686122006-03-17 16:44:00 -05001134 * DESCRIPTION: Return a zero-filled object.
Robert Moore73459f72005-06-24 00:00:00 -04001135 *
1136 ******************************************************************************/
1137
Len Brown4be44fc2005-08-05 00:44:28 -04001138void *acpi_os_acquire_object(acpi_cache_t * cache)
Robert Moore73459f72005-06-24 00:00:00 -04001139{
Bob Moore61686122006-03-17 16:44:00 -05001140 void *object = kmem_cache_zalloc(cache, GFP_KERNEL);
Len Brown4be44fc2005-08-05 00:44:28 -04001141 WARN_ON(!object);
1142 return object;
Robert Moore73459f72005-06-24 00:00:00 -04001143}
1144
Bob Mooreb229cf92006-04-21 17:15:00 -04001145/******************************************************************************
1146 *
1147 * FUNCTION: acpi_os_validate_interface
1148 *
1149 * PARAMETERS: interface - Requested interface to be validated
1150 *
1151 * RETURN: AE_OK if interface is supported, AE_SUPPORT otherwise
1152 *
1153 * DESCRIPTION: Match an interface string to the interfaces supported by the
1154 * host. Strings originate from an AML call to the _OSI method.
1155 *
1156 *****************************************************************************/
1157
1158acpi_status
1159acpi_os_validate_interface (char *interface)
1160{
1161
1162 return AE_SUPPORT;
1163}
1164
1165
1166/******************************************************************************
1167 *
1168 * FUNCTION: acpi_os_validate_address
1169 *
1170 * PARAMETERS: space_id - ACPI space ID
1171 * address - Physical address
1172 * length - Address length
1173 *
1174 * RETURN: AE_OK if address/length is valid for the space_id. Otherwise,
1175 * should return AE_AML_ILLEGAL_ADDRESS.
1176 *
1177 * DESCRIPTION: Validate a system address via the host OS. Used to validate
1178 * the addresses accessed by AML operation regions.
1179 *
1180 *****************************************************************************/
1181
1182acpi_status
1183acpi_os_validate_address (
1184 u8 space_id,
1185 acpi_physical_address address,
1186 acpi_size length)
1187{
1188
1189 return AE_OK;
1190}
1191
1192
Robert Moore73459f72005-06-24 00:00:00 -04001193#endif