blob: c68b1bb138c3bfd9c14485477424bfd6e66cf046 [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
28#include <linux/config.h>
29#include <linux/module.h>
30#include <linux/kernel.h>
31#include <linux/slab.h>
32#include <linux/mm.h>
33#include <linux/pci.h>
34#include <linux/smp_lock.h>
35#include <linux/interrupt.h>
36#include <linux/kmod.h>
37#include <linux/delay.h>
38#include <linux/workqueue.h>
39#include <linux/nmi.h>
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -040040#include <linux/kthread.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <acpi/acpi.h>
42#include <asm/io.h>
43#include <acpi/acpi_bus.h>
44#include <acpi/processor.h>
45#include <asm/uaccess.h>
46
47#include <linux/efi.h>
48
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#define _COMPONENT ACPI_OS_SERVICES
Len Brown4be44fc2005-08-05 00:44:28 -040050ACPI_MODULE_NAME("osl")
Linus Torvalds1da177e2005-04-16 15:20:36 -070051#define PREFIX "ACPI: "
Len Brown4be44fc2005-08-05 00:44:28 -040052struct acpi_os_dpc {
53 acpi_osd_exec_callback function;
54 void *context;
Linus Torvalds1da177e2005-04-16 15:20:36 -070055};
56
57#ifdef CONFIG_ACPI_CUSTOM_DSDT
58#include CONFIG_ACPI_CUSTOM_DSDT_FILE
59#endif
60
61#ifdef ENABLE_DEBUGGER
62#include <linux/kdb.h>
63
64/* stuff for debugger support */
65int acpi_in_debugger;
66EXPORT_SYMBOL(acpi_in_debugger);
67
68extern char line_buf[80];
Len Brown4be44fc2005-08-05 00:44:28 -040069#endif /*ENABLE_DEBUGGER */
Linus Torvalds1da177e2005-04-16 15:20:36 -070070
Luming Yu30e332f2005-08-12 00:31:00 -040071int acpi_specific_hotkey_enabled = TRUE;
Luming Yufb9802f2005-03-18 18:03:45 -050072EXPORT_SYMBOL(acpi_specific_hotkey_enabled);
73
Linus Torvalds1da177e2005-04-16 15:20:36 -070074static unsigned int acpi_irq_irq;
75static acpi_osd_handler acpi_irq_handler;
76static void *acpi_irq_context;
77static struct workqueue_struct *kacpid_wq;
78
Len Brown4be44fc2005-08-05 00:44:28 -040079acpi_status acpi_os_initialize(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070080{
81 return AE_OK;
82}
83
Len Brown4be44fc2005-08-05 00:44:28 -040084acpi_status acpi_os_initialize1(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070085{
86 /*
87 * Initialize PCI configuration space access, as we'll need to access
88 * it while walking the namespace (bus 0 and root bridges w/ _BBNs).
89 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 if (!raw_pci_ops) {
Len Brown4be44fc2005-08-05 00:44:28 -040091 printk(KERN_ERR PREFIX
92 "Access to PCI configuration space unavailable\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 return AE_NULL_ENTRY;
94 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 kacpid_wq = create_singlethread_workqueue("kacpid");
96 BUG_ON(!kacpid_wq);
97
98 return AE_OK;
99}
100
Len Brown4be44fc2005-08-05 00:44:28 -0400101acpi_status acpi_os_terminate(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102{
103 if (acpi_irq_handler) {
104 acpi_os_remove_interrupt_handler(acpi_irq_irq,
105 acpi_irq_handler);
106 }
107
108 destroy_workqueue(kacpid_wq);
109
110 return AE_OK;
111}
112
Len Brown4be44fc2005-08-05 00:44:28 -0400113void acpi_os_printf(const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114{
115 va_list args;
116 va_start(args, fmt);
117 acpi_os_vprintf(fmt, args);
118 va_end(args);
119}
Len Brown4be44fc2005-08-05 00:44:28 -0400120
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121EXPORT_SYMBOL(acpi_os_printf);
122
Len Brown4be44fc2005-08-05 00:44:28 -0400123void acpi_os_vprintf(const char *fmt, va_list args)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124{
125 static char buffer[512];
Len Brown4be44fc2005-08-05 00:44:28 -0400126
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 vsprintf(buffer, fmt, args);
128
129#ifdef ENABLE_DEBUGGER
130 if (acpi_in_debugger) {
131 kdb_printf("%s", buffer);
132 } else {
133 printk("%s", buffer);
134 }
135#else
136 printk("%s", buffer);
137#endif
138}
139
Thomas Renningera6fc6722006-06-26 23:58:43 -0400140
David Shaohua Li11e981f2005-08-03 23:46:33 -0400141extern int acpi_in_resume;
Len Brown4be44fc2005-08-05 00:44:28 -0400142void *acpi_os_allocate(acpi_size size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143{
David Shaohua Li11e981f2005-08-03 23:46:33 -0400144 if (acpi_in_resume)
145 return kmalloc(size, GFP_ATOMIC);
146 else
147 return kmalloc(size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148}
149
Len Brown4be44fc2005-08-05 00:44:28 -0400150acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151{
152 if (efi_enabled) {
153 addr->pointer_type = ACPI_PHYSICAL_POINTER;
Bjorn Helgaasb2c99e32006-03-26 01:37:08 -0800154 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
155 addr->pointer.physical = efi.acpi20;
156 else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
157 addr->pointer.physical = efi.acpi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 else {
Len Brown4be44fc2005-08-05 00:44:28 -0400159 printk(KERN_ERR PREFIX
160 "System description tables not found\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161 return AE_NOT_FOUND;
162 }
163 } else {
164 if (ACPI_FAILURE(acpi_find_root_pointer(flags, addr))) {
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 }
170
171 return AE_OK;
172}
173
174acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400175acpi_os_map_memory(acpi_physical_address phys, acpi_size size,
176 void __iomem ** virt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177{
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800178 if (phys > ULONG_MAX) {
179 printk(KERN_ERR PREFIX "Cannot map memory that high\n");
180 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 }
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800182 /*
183 * ioremap checks to ensure this is in reserved space
184 */
185 *virt = ioremap((unsigned long)phys, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186
187 if (!*virt)
188 return AE_NO_MEMORY;
189
190 return AE_OK;
191}
Kylene Jo Hall55a82ab2006-01-08 01:03:15 -0800192EXPORT_SYMBOL_GPL(acpi_os_map_memory);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
Len Brown4be44fc2005-08-05 00:44:28 -0400194void acpi_os_unmap_memory(void __iomem * virt, acpi_size size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195{
196 iounmap(virt);
197}
Kylene Jo Hall55a82ab2006-01-08 01:03:15 -0800198EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199
200#ifdef ACPI_FUTURE_USAGE
201acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400202acpi_os_get_physical_address(void *virt, acpi_physical_address * phys)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203{
Len Brown4be44fc2005-08-05 00:44:28 -0400204 if (!phys || !virt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 return AE_BAD_PARAMETER;
206
207 *phys = virt_to_phys(virt);
208
209 return AE_OK;
210}
211#endif
212
213#define ACPI_MAX_OVERRIDE_LEN 100
214
215static char acpi_os_name[ACPI_MAX_OVERRIDE_LEN];
216
217acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400218acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
219 acpi_string * new_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220{
221 if (!init_val || !new_val)
222 return AE_BAD_PARAMETER;
223
224 *new_val = NULL;
Len Brown4be44fc2005-08-05 00:44:28 -0400225 if (!memcmp(init_val->name, "_OS_", 4) && strlen(acpi_os_name)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 printk(KERN_INFO PREFIX "Overriding _OS definition to '%s'\n",
Len Brown4be44fc2005-08-05 00:44:28 -0400227 acpi_os_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228 *new_val = acpi_os_name;
229 }
230
231 return AE_OK;
232}
233
234acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400235acpi_os_table_override(struct acpi_table_header * existing_table,
236 struct acpi_table_header ** new_table)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237{
238 if (!existing_table || !new_table)
239 return AE_BAD_PARAMETER;
240
241#ifdef CONFIG_ACPI_CUSTOM_DSDT
242 if (strncmp(existing_table->signature, "DSDT", 4) == 0)
Len Brown4be44fc2005-08-05 00:44:28 -0400243 *new_table = (struct acpi_table_header *)AmlCode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 else
245 *new_table = NULL;
246#else
247 *new_table = NULL;
248#endif
249 return AE_OK;
250}
251
Len Brown4be44fc2005-08-05 00:44:28 -0400252static irqreturn_t acpi_irq(int irq, void *dev_id, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253{
Len Brown4be44fc2005-08-05 00:44:28 -0400254 return (*acpi_irq_handler) (acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255}
256
257acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400258acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
259 void *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260{
261 unsigned int irq;
262
263 /*
264 * Ignore the GSI from the core, and use the value in our copy of the
265 * FADT. It may not be the same if an interrupt source override exists
266 * for the SCI.
267 */
268 gsi = acpi_fadt.sci_int;
269 if (acpi_gsi_to_irq(gsi, &irq) < 0) {
270 printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n",
271 gsi);
272 return AE_OK;
273 }
274
275 acpi_irq_handler = handler;
276 acpi_irq_context = context;
277 if (request_irq(irq, acpi_irq, SA_SHIRQ, "acpi", acpi_irq)) {
278 printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq);
279 return AE_NOT_ACQUIRED;
280 }
281 acpi_irq_irq = irq;
282
283 return AE_OK;
284}
285
Len Brown4be44fc2005-08-05 00:44:28 -0400286acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287{
288 if (irq) {
289 free_irq(irq, acpi_irq);
290 acpi_irq_handler = NULL;
291 acpi_irq_irq = 0;
292 }
293
294 return AE_OK;
295}
296
297/*
298 * Running in interpreter thread context, safe to sleep
299 */
300
Len Brown4be44fc2005-08-05 00:44:28 -0400301void acpi_os_sleep(acpi_integer ms)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302{
Nishanth Aravamudan01a527e2005-11-07 01:01:14 -0800303 schedule_timeout_interruptible(msecs_to_jiffies(ms));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304}
Len Brown4be44fc2005-08-05 00:44:28 -0400305
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306EXPORT_SYMBOL(acpi_os_sleep);
307
Len Brown4be44fc2005-08-05 00:44:28 -0400308void acpi_os_stall(u32 us)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309{
310 while (us) {
311 u32 delay = 1000;
312
313 if (delay > us)
314 delay = us;
315 udelay(delay);
316 touch_nmi_watchdog();
317 us -= delay;
318 }
319}
Len Brown4be44fc2005-08-05 00:44:28 -0400320
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321EXPORT_SYMBOL(acpi_os_stall);
322
323/*
324 * Support ACPI 3.0 AML Timer operand
325 * Returns 64-bit free-running, monotonically increasing timer
326 * with 100ns granularity
327 */
Len Brown4be44fc2005-08-05 00:44:28 -0400328u64 acpi_os_get_timer(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329{
330 static u64 t;
331
332#ifdef CONFIG_HPET
333 /* TBD: use HPET if available */
334#endif
335
336#ifdef CONFIG_X86_PM_TIMER
337 /* TBD: default to PM timer if HPET was not available */
338#endif
339 if (!t)
340 printk(KERN_ERR PREFIX "acpi_os_get_timer() TBD\n");
341
342 return ++t;
343}
344
Len Brown4be44fc2005-08-05 00:44:28 -0400345acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346{
347 u32 dummy;
348
349 if (!value)
350 value = &dummy;
351
Len Brown4be44fc2005-08-05 00:44:28 -0400352 switch (width) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 case 8:
Len Brown4be44fc2005-08-05 00:44:28 -0400354 *(u8 *) value = inb(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 break;
356 case 16:
Len Brown4be44fc2005-08-05 00:44:28 -0400357 *(u16 *) value = inw(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 break;
359 case 32:
Len Brown4be44fc2005-08-05 00:44:28 -0400360 *(u32 *) value = inl(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 break;
362 default:
363 BUG();
364 }
365
366 return AE_OK;
367}
Len Brown4be44fc2005-08-05 00:44:28 -0400368
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369EXPORT_SYMBOL(acpi_os_read_port);
370
Len Brown4be44fc2005-08-05 00:44:28 -0400371acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372{
Len Brown4be44fc2005-08-05 00:44:28 -0400373 switch (width) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 case 8:
375 outb(value, port);
376 break;
377 case 16:
378 outw(value, port);
379 break;
380 case 32:
381 outl(value, port);
382 break;
383 default:
384 BUG();
385 }
386
387 return AE_OK;
388}
Len Brown4be44fc2005-08-05 00:44:28 -0400389
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390EXPORT_SYMBOL(acpi_os_write_port);
391
392acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400393acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394{
Len Brown4be44fc2005-08-05 00:44:28 -0400395 u32 dummy;
396 void __iomem *virt_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800398 virt_addr = ioremap(phys_addr, width);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 if (!value)
400 value = &dummy;
401
402 switch (width) {
403 case 8:
Len Brown4be44fc2005-08-05 00:44:28 -0400404 *(u8 *) value = readb(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 break;
406 case 16:
Len Brown4be44fc2005-08-05 00:44:28 -0400407 *(u16 *) value = readw(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 break;
409 case 32:
Len Brown4be44fc2005-08-05 00:44:28 -0400410 *(u32 *) value = readl(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 break;
412 default:
413 BUG();
414 }
415
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800416 iounmap(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
418 return AE_OK;
419}
420
421acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400422acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423{
Len Brown4be44fc2005-08-05 00:44:28 -0400424 void __iomem *virt_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800426 virt_addr = ioremap(phys_addr, width);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427
428 switch (width) {
429 case 8:
430 writeb(value, virt_addr);
431 break;
432 case 16:
433 writew(value, virt_addr);
434 break;
435 case 32:
436 writel(value, virt_addr);
437 break;
438 default:
439 BUG();
440 }
441
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800442 iounmap(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443
444 return AE_OK;
445}
446
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400448acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
449 void *value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450{
451 int result, size;
452
453 if (!value)
454 return AE_BAD_PARAMETER;
455
456 switch (width) {
457 case 8:
458 size = 1;
459 break;
460 case 16:
461 size = 2;
462 break;
463 case 32:
464 size = 4;
465 break;
466 default:
467 return AE_ERROR;
468 }
469
470 BUG_ON(!raw_pci_ops);
471
472 result = raw_pci_ops->read(pci_id->segment, pci_id->bus,
Len Brown4be44fc2005-08-05 00:44:28 -0400473 PCI_DEVFN(pci_id->device, pci_id->function),
474 reg, size, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475
476 return (result ? AE_ERROR : AE_OK);
477}
Len Brown4be44fc2005-08-05 00:44:28 -0400478
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479EXPORT_SYMBOL(acpi_os_read_pci_configuration);
480
481acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400482acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
483 acpi_integer value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484{
485 int result, size;
486
487 switch (width) {
488 case 8:
489 size = 1;
490 break;
491 case 16:
492 size = 2;
493 break;
494 case 32:
495 size = 4;
496 break;
497 default:
498 return AE_ERROR;
499 }
500
501 BUG_ON(!raw_pci_ops);
502
503 result = raw_pci_ops->write(pci_id->segment, pci_id->bus,
Len Brown4be44fc2005-08-05 00:44:28 -0400504 PCI_DEVFN(pci_id->device, pci_id->function),
505 reg, size, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
507 return (result ? AE_ERROR : AE_OK);
508}
509
510/* TODO: Change code to take advantage of driver model more */
Len Brown4be44fc2005-08-05 00:44:28 -0400511static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */
512 acpi_handle chandle, /* current node */
513 struct acpi_pci_id **id,
514 int *is_bridge, u8 * bus_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515{
Len Brown4be44fc2005-08-05 00:44:28 -0400516 acpi_handle handle;
517 struct acpi_pci_id *pci_id = *id;
518 acpi_status status;
519 unsigned long temp;
520 acpi_object_type type;
521 u8 tu8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522
523 acpi_get_parent(chandle, &handle);
524 if (handle != rhandle) {
Len Brown4be44fc2005-08-05 00:44:28 -0400525 acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge,
526 bus_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527
528 status = acpi_get_type(handle, &type);
Len Brown4be44fc2005-08-05 00:44:28 -0400529 if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 return;
531
Len Brown4be44fc2005-08-05 00:44:28 -0400532 status =
533 acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
534 &temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 if (ACPI_SUCCESS(status)) {
Len Brown4be44fc2005-08-05 00:44:28 -0400536 pci_id->device = ACPI_HIWORD(ACPI_LODWORD(temp));
537 pci_id->function = ACPI_LOWORD(ACPI_LODWORD(temp));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
539 if (*is_bridge)
540 pci_id->bus = *bus_number;
541
542 /* any nicer way to get bus number of bridge ? */
Len Brown4be44fc2005-08-05 00:44:28 -0400543 status =
544 acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8,
545 8);
546 if (ACPI_SUCCESS(status)
547 && ((tu8 & 0x7f) == 1 || (tu8 & 0x7f) == 2)) {
548 status =
549 acpi_os_read_pci_configuration(pci_id, 0x18,
550 &tu8, 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 if (!ACPI_SUCCESS(status)) {
552 /* Certainly broken... FIX ME */
553 return;
554 }
555 *is_bridge = 1;
556 pci_id->bus = tu8;
Len Brown4be44fc2005-08-05 00:44:28 -0400557 status =
558 acpi_os_read_pci_configuration(pci_id, 0x19,
559 &tu8, 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 if (ACPI_SUCCESS(status)) {
561 *bus_number = tu8;
562 }
563 } else
564 *is_bridge = 0;
565 }
566 }
567}
568
Len Brown4be44fc2005-08-05 00:44:28 -0400569void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */
570 acpi_handle chandle, /* current node */
571 struct acpi_pci_id **id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572{
573 int is_bridge = 1;
574 u8 bus_number = (*id)->bus;
575
576 acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number);
577}
578
Len Brown4be44fc2005-08-05 00:44:28 -0400579static void acpi_os_execute_deferred(void *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580{
Len Brown4be44fc2005-08-05 00:44:28 -0400581 struct acpi_os_dpc *dpc = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583
Len Brown4be44fc2005-08-05 00:44:28 -0400584 dpc = (struct acpi_os_dpc *)context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 if (!dpc) {
Len Brown64684632006-06-26 23:41:38 -0400586 printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
Patrick Mocheld550d982006-06-27 00:41:40 -0400587 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 }
589
590 dpc->function(dpc->context);
591
592 kfree(dpc);
593
Patrick Mocheld550d982006-06-27 00:41:40 -0400594 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595}
596
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400597static int acpi_os_execute_thread(void *context)
598{
599 struct acpi_os_dpc *dpc = (struct acpi_os_dpc *)context;
600 if (dpc) {
601 dpc->function(dpc->context);
602 kfree(dpc);
603 }
604 do_exit(0);
605}
606
607/*******************************************************************************
608 *
609 * FUNCTION: acpi_os_execute
610 *
611 * PARAMETERS: Type - Type of the callback
612 * Function - Function to be executed
613 * Context - Function parameters
614 *
615 * RETURN: Status
616 *
617 * DESCRIPTION: Depending on type, either queues function for deferred execution or
618 * immediately executes function on a separate thread.
619 *
620 ******************************************************************************/
621
622acpi_status acpi_os_execute(acpi_execute_type type,
Len Brown4be44fc2005-08-05 00:44:28 -0400623 acpi_osd_exec_callback function, void *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624{
Len Brown4be44fc2005-08-05 00:44:28 -0400625 acpi_status status = AE_OK;
626 struct acpi_os_dpc *dpc;
627 struct work_struct *task;
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400628 struct task_struct *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629
630 if (!function)
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400631 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 /*
633 * Allocate/initialize DPC structure. Note that this memory will be
634 * freed by the callee. The kernel handles the tq_struct list in a
635 * way that allows us to also free its memory inside the callee.
636 * Because we may want to schedule several tasks with different
637 * parameters we can't use the approach some kernel code uses of
638 * having a static tq_struct.
639 * We can save time and code by allocating the DPC and tq_structs
640 * from the same memory.
641 */
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400642 if (type == OSL_NOTIFY_HANDLER) {
643 dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_KERNEL);
644 } else {
645 dpc = kmalloc(sizeof(struct acpi_os_dpc) +
646 sizeof(struct work_struct), GFP_ATOMIC);
647 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 if (!dpc)
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400649 return AE_NO_MEMORY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 dpc->function = function;
651 dpc->context = context;
652
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400653 if (type == OSL_NOTIFY_HANDLER) {
654 p = kthread_create(acpi_os_execute_thread, dpc, "kacpid_notify");
655 if (!IS_ERR(p)) {
656 wake_up_process(p);
657 } else {
658 status = AE_NO_MEMORY;
659 kfree(dpc);
660 }
661 } else {
662 task = (void *)(dpc + 1);
663 INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc);
664 if (!queue_work(kacpid_wq, task)) {
665 status = AE_ERROR;
666 kfree(dpc);
667 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 }
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400669 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670}
Len Brown4be44fc2005-08-05 00:44:28 -0400671
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400672EXPORT_SYMBOL(acpi_os_execute);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673
Len Brown4be44fc2005-08-05 00:44:28 -0400674void acpi_os_wait_events_complete(void *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675{
676 flush_workqueue(kacpid_wq);
677}
Len Brown4be44fc2005-08-05 00:44:28 -0400678
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679EXPORT_SYMBOL(acpi_os_wait_events_complete);
680
681/*
682 * Allocate the memory for a spinlock and initialize it.
683 */
Bob Moore967440e2006-06-23 17:04:00 -0400684acpi_status acpi_os_create_lock(acpi_spinlock * handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685{
Bob Moore967440e2006-06-23 17:04:00 -0400686 spin_lock_init(*handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687
Patrick Mocheld550d982006-06-27 00:41:40 -0400688 return AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689}
690
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691/*
692 * Deallocate the memory for a spinlock.
693 */
Bob Moore967440e2006-06-23 17:04:00 -0400694void acpi_os_delete_lock(acpi_spinlock handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695{
Patrick Mocheld550d982006-06-27 00:41:40 -0400696 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697}
698
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400700acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701{
Len Brown4be44fc2005-08-05 00:44:28 -0400702 struct semaphore *sem = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704
705 sem = acpi_os_allocate(sizeof(struct semaphore));
706 if (!sem)
Patrick Mocheld550d982006-06-27 00:41:40 -0400707 return AE_NO_MEMORY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 memset(sem, 0, sizeof(struct semaphore));
709
710 sema_init(sem, initial_units);
711
Len Brown4be44fc2005-08-05 00:44:28 -0400712 *handle = (acpi_handle *) sem;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
Len Brown4be44fc2005-08-05 00:44:28 -0400714 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Creating semaphore[%p|%d].\n",
715 *handle, initial_units));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
Patrick Mocheld550d982006-06-27 00:41:40 -0400717 return AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719
Len Brown4be44fc2005-08-05 00:44:28 -0400720EXPORT_SYMBOL(acpi_os_create_semaphore);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721
722/*
723 * TODO: A better way to delete semaphores? Linux doesn't have a
724 * 'delete_semaphore()' function -- may result in an invalid
725 * pointer dereference for non-synchronized consumers. Should
726 * we at least check for blocked threads and signal/cancel them?
727 */
728
Len Brown4be44fc2005-08-05 00:44:28 -0400729acpi_status acpi_os_delete_semaphore(acpi_handle handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730{
Len Brown4be44fc2005-08-05 00:44:28 -0400731 struct semaphore *sem = (struct semaphore *)handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733
734 if (!sem)
Patrick Mocheld550d982006-06-27 00:41:40 -0400735 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736
Len Brown4be44fc2005-08-05 00:44:28 -0400737 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738
Len Brown02438d82006-06-30 03:19:10 -0400739 kfree(sem);
Len Brown4be44fc2005-08-05 00:44:28 -0400740 sem = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741
Patrick Mocheld550d982006-06-27 00:41:40 -0400742 return AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744
Len Brown4be44fc2005-08-05 00:44:28 -0400745EXPORT_SYMBOL(acpi_os_delete_semaphore);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746
747/*
748 * TODO: The kernel doesn't have a 'down_timeout' function -- had to
749 * improvise. The process is to sleep for one scheduler quantum
750 * until the semaphore becomes available. Downside is that this
751 * may result in starvation for timeout-based waits when there's
752 * lots of semaphore activity.
753 *
754 * TODO: Support for units > 1?
755 */
Len Brown4be44fc2005-08-05 00:44:28 -0400756acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757{
Len Brown4be44fc2005-08-05 00:44:28 -0400758 acpi_status status = AE_OK;
759 struct semaphore *sem = (struct semaphore *)handle;
760 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762
763 if (!sem || (units < 1))
Patrick Mocheld550d982006-06-27 00:41:40 -0400764 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765
766 if (units > 1)
Patrick Mocheld550d982006-06-27 00:41:40 -0400767 return AE_SUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768
Len Brown4be44fc2005-08-05 00:44:28 -0400769 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n",
770 handle, units, timeout));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771
Len Brown4be44fc2005-08-05 00:44:28 -0400772 switch (timeout) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 /*
774 * No Wait:
775 * --------
776 * A zero timeout value indicates that we shouldn't wait - just
777 * acquire the semaphore if available otherwise return AE_TIME
778 * (a.k.a. 'would block').
779 */
Len Brown4be44fc2005-08-05 00:44:28 -0400780 case 0:
781 if (down_trylock(sem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 status = AE_TIME;
783 break;
784
785 /*
786 * Wait Indefinitely:
787 * ------------------
788 */
Len Brown4be44fc2005-08-05 00:44:28 -0400789 case ACPI_WAIT_FOREVER:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 down(sem);
791 break;
792
793 /*
794 * Wait w/ Timeout:
795 * ----------------
796 */
Len Brown4be44fc2005-08-05 00:44:28 -0400797 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 // TODO: A better timeout algorithm?
799 {
800 int i = 0;
Len Brown4be44fc2005-08-05 00:44:28 -0400801 static const int quantum_ms = 1000 / HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802
803 ret = down_trylock(sem);
Yu Lumingdacd9b82005-12-31 01:45:00 -0500804 for (i = timeout; (i > 0 && ret != 0); i -= quantum_ms) {
Nishanth Aravamudan01a527e2005-11-07 01:01:14 -0800805 schedule_timeout_interruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 ret = down_trylock(sem);
807 }
Len Brown4be44fc2005-08-05 00:44:28 -0400808
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 if (ret != 0)
810 status = AE_TIME;
811 }
812 break;
813 }
814
815 if (ACPI_FAILURE(status)) {
Bjorn Helgaas9e7e2c02006-04-27 05:25:00 -0400816 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
Thomas Renningera6fc6722006-06-26 23:58:43 -0400817 "Failed to acquire semaphore[%p|%d|%d], %s",
Len Brown4be44fc2005-08-05 00:44:28 -0400818 handle, units, timeout,
819 acpi_format_exception(status)));
820 } else {
821 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
Thomas Renningera6fc6722006-06-26 23:58:43 -0400822 "Acquired semaphore[%p|%d|%d]", handle,
Len Brown4be44fc2005-08-05 00:44:28 -0400823 units, timeout));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 }
825
Patrick Mocheld550d982006-06-27 00:41:40 -0400826 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828
Len Brown4be44fc2005-08-05 00:44:28 -0400829EXPORT_SYMBOL(acpi_os_wait_semaphore);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830
831/*
832 * TODO: Support for units > 1?
833 */
Len Brown4be44fc2005-08-05 00:44:28 -0400834acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835{
Len Brown4be44fc2005-08-05 00:44:28 -0400836 struct semaphore *sem = (struct semaphore *)handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838
839 if (!sem || (units < 1))
Patrick Mocheld550d982006-06-27 00:41:40 -0400840 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841
842 if (units > 1)
Patrick Mocheld550d982006-06-27 00:41:40 -0400843 return AE_SUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844
Len Brown4be44fc2005-08-05 00:44:28 -0400845 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle,
846 units));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847
848 up(sem);
849
Patrick Mocheld550d982006-06-27 00:41:40 -0400850 return AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851}
Len Brown4be44fc2005-08-05 00:44:28 -0400852
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853EXPORT_SYMBOL(acpi_os_signal_semaphore);
854
855#ifdef ACPI_FUTURE_USAGE
Len Brown4be44fc2005-08-05 00:44:28 -0400856u32 acpi_os_get_line(char *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857{
858
859#ifdef ENABLE_DEBUGGER
860 if (acpi_in_debugger) {
861 u32 chars;
862
863 kdb_read(buffer, sizeof(line_buf));
864
865 /* remove the CR kdb includes */
866 chars = strlen(buffer) - 1;
867 buffer[chars] = '\0';
868 }
869#endif
870
871 return 0;
872}
Len Brown4be44fc2005-08-05 00:44:28 -0400873#endif /* ACPI_FUTURE_USAGE */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874
875/* Assumes no unreadable holes inbetween */
Len Brown4be44fc2005-08-05 00:44:28 -0400876u8 acpi_os_readable(void *ptr, acpi_size len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877{
Len Brown4be44fc2005-08-05 00:44:28 -0400878#if defined(__i386__) || defined(__x86_64__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 char tmp;
Len Brown4be44fc2005-08-05 00:44:28 -0400880 return !__get_user(tmp, (char __user *)ptr)
881 && !__get_user(tmp, (char __user *)ptr + len - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882#endif
883 return 1;
884}
885
886#ifdef ACPI_FUTURE_USAGE
Len Brown4be44fc2005-08-05 00:44:28 -0400887u8 acpi_os_writable(void *ptr, acpi_size len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888{
889 /* could do dummy write (racy) or a kernel page table lookup.
890 The later may be difficult at early boot when kmap doesn't work yet. */
891 return 1;
892}
893#endif
894
Len Brown4be44fc2005-08-05 00:44:28 -0400895acpi_status acpi_os_signal(u32 function, void *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896{
Len Brown4be44fc2005-08-05 00:44:28 -0400897 switch (function) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 case ACPI_SIGNAL_FATAL:
899 printk(KERN_ERR PREFIX "Fatal opcode executed\n");
900 break;
901 case ACPI_SIGNAL_BREAKPOINT:
902 /*
903 * AML Breakpoint
904 * ACPI spec. says to treat it as a NOP unless
905 * you are debugging. So if/when we integrate
906 * AML debugger into the kernel debugger its
907 * hook will go here. But until then it is
908 * not useful to print anything on breakpoints.
909 */
910 break;
911 default:
912 break;
913 }
914
915 return AE_OK;
916}
Len Brown4be44fc2005-08-05 00:44:28 -0400917
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918EXPORT_SYMBOL(acpi_os_signal);
919
Len Brown4be44fc2005-08-05 00:44:28 -0400920static int __init acpi_os_name_setup(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921{
922 char *p = acpi_os_name;
Len Brown4be44fc2005-08-05 00:44:28 -0400923 int count = ACPI_MAX_OVERRIDE_LEN - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924
925 if (!str || !*str)
926 return 0;
927
928 for (; count-- && str && *str; str++) {
929 if (isalnum(*str) || *str == ' ' || *str == ':')
930 *p++ = *str;
931 else if (*str == '\'' || *str == '"')
932 continue;
933 else
934 break;
935 }
936 *p = 0;
937
938 return 1;
Len Brown4be44fc2005-08-05 00:44:28 -0400939
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940}
941
942__setup("acpi_os_name=", acpi_os_name_setup);
943
944/*
945 * _OSI control
946 * empty string disables _OSI
947 * TBD additional string adds to _OSI
948 */
Len Brown4be44fc2005-08-05 00:44:28 -0400949static int __init acpi_osi_setup(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950{
951 if (str == NULL || *str == '\0') {
952 printk(KERN_INFO PREFIX "_OSI method disabled\n");
953 acpi_gbl_create_osi_method = FALSE;
Len Brown4be44fc2005-08-05 00:44:28 -0400954 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 /* TBD */
Len Brown4be44fc2005-08-05 00:44:28 -0400956 printk(KERN_ERR PREFIX "_OSI additional string ignored -- %s\n",
957 str);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 }
959
960 return 1;
961}
962
963__setup("acpi_osi=", acpi_osi_setup);
964
965/* enable serialization to combat AE_ALREADY_EXISTS errors */
Len Brown4be44fc2005-08-05 00:44:28 -0400966static int __init acpi_serialize_setup(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967{
968 printk(KERN_INFO PREFIX "serialize enabled\n");
969
970 acpi_gbl_all_methods_serialized = TRUE;
971
972 return 1;
973}
974
975__setup("acpi_serialize", acpi_serialize_setup);
976
977/*
978 * Wake and Run-Time GPES are expected to be separate.
979 * We disable wake-GPEs at run-time to prevent spurious
980 * interrupts.
981 *
982 * However, if a system exists that shares Wake and
983 * Run-time events on the same GPE this flag is available
984 * to tell Linux to keep the wake-time GPEs enabled at run-time.
985 */
Len Brown4be44fc2005-08-05 00:44:28 -0400986static int __init acpi_wake_gpes_always_on_setup(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987{
988 printk(KERN_INFO PREFIX "wake GPEs not disabled\n");
989
990 acpi_gbl_leave_wake_gpes_disabled = FALSE;
991
992 return 1;
993}
994
995__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
996
Adrian Bunk8713cbe2005-09-02 17:16:48 -0400997static int __init acpi_hotkey_setup(char *str)
Luming Yufb9802f2005-03-18 18:03:45 -0500998{
Luming Yu30e332f2005-08-12 00:31:00 -0400999 acpi_specific_hotkey_enabled = FALSE;
Luming Yufb9802f2005-03-18 18:03:45 -05001000 return 1;
1001}
1002
Luming Yu30e332f2005-08-12 00:31:00 -04001003__setup("acpi_generic_hotkey", acpi_hotkey_setup);
Luming Yufb9802f2005-03-18 18:03:45 -05001004
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005/*
1006 * max_cstate is defined in the base kernel so modules can
1007 * change it w/o depending on the state of the processor module.
1008 */
1009unsigned int max_cstate = ACPI_PROCESSOR_MAX_POWER;
1010
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011EXPORT_SYMBOL(max_cstate);
Robert Moore73459f72005-06-24 00:00:00 -04001012
1013/*
1014 * Acquire a spinlock.
1015 *
1016 * handle is a pointer to the spinlock_t.
Robert Moore73459f72005-06-24 00:00:00 -04001017 */
1018
Bob Moore967440e2006-06-23 17:04:00 -04001019acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp)
Robert Moore73459f72005-06-24 00:00:00 -04001020{
Bob Mooreb8e4d892006-01-27 16:43:00 -05001021 acpi_cpu_flags flags;
Bob Moore967440e2006-06-23 17:04:00 -04001022 spin_lock_irqsave(lockp, flags);
Robert Moore73459f72005-06-24 00:00:00 -04001023 return flags;
1024}
1025
1026/*
1027 * Release a spinlock. See above.
1028 */
1029
Bob Moore967440e2006-06-23 17:04:00 -04001030void acpi_os_release_lock(acpi_spinlock lockp, acpi_cpu_flags flags)
Robert Moore73459f72005-06-24 00:00:00 -04001031{
Bob Moore967440e2006-06-23 17:04:00 -04001032 spin_unlock_irqrestore(lockp, flags);
Robert Moore73459f72005-06-24 00:00:00 -04001033}
1034
Robert Moore73459f72005-06-24 00:00:00 -04001035#ifndef ACPI_USE_LOCAL_CACHE
1036
1037/*******************************************************************************
1038 *
1039 * FUNCTION: acpi_os_create_cache
1040 *
Bob Mooreb229cf92006-04-21 17:15:00 -04001041 * PARAMETERS: name - Ascii name for the cache
1042 * size - Size of each cached object
1043 * depth - Maximum depth of the cache (in objects) <ignored>
1044 * cache - Where the new cache object is returned
Robert Moore73459f72005-06-24 00:00:00 -04001045 *
Bob Mooreb229cf92006-04-21 17:15:00 -04001046 * RETURN: status
Robert Moore73459f72005-06-24 00:00:00 -04001047 *
1048 * DESCRIPTION: Create a cache object
1049 *
1050 ******************************************************************************/
1051
1052acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -04001053acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache)
Robert Moore73459f72005-06-24 00:00:00 -04001054{
Len Brown4be44fc2005-08-05 00:44:28 -04001055 *cache = kmem_cache_create(name, size, 0, 0, NULL, NULL);
Bob Mooreb229cf92006-04-21 17:15:00 -04001056 if (cache == NULL)
1057 return AE_ERROR;
1058 else
1059 return AE_OK;
Robert Moore73459f72005-06-24 00:00:00 -04001060}
1061
1062/*******************************************************************************
1063 *
1064 * FUNCTION: acpi_os_purge_cache
1065 *
1066 * PARAMETERS: Cache - Handle to cache object
1067 *
1068 * RETURN: Status
1069 *
1070 * DESCRIPTION: Free all objects within the requested cache.
1071 *
1072 ******************************************************************************/
1073
Len Brown4be44fc2005-08-05 00:44:28 -04001074acpi_status acpi_os_purge_cache(acpi_cache_t * cache)
Robert Moore73459f72005-06-24 00:00:00 -04001075{
Len Brown4be44fc2005-08-05 00:44:28 -04001076 (void)kmem_cache_shrink(cache);
1077 return (AE_OK);
Robert Moore73459f72005-06-24 00:00:00 -04001078}
1079
1080/*******************************************************************************
1081 *
1082 * FUNCTION: acpi_os_delete_cache
1083 *
1084 * PARAMETERS: Cache - Handle to cache object
1085 *
1086 * RETURN: Status
1087 *
1088 * DESCRIPTION: Free all objects within the requested cache and delete the
1089 * cache object.
1090 *
1091 ******************************************************************************/
1092
Len Brown4be44fc2005-08-05 00:44:28 -04001093acpi_status acpi_os_delete_cache(acpi_cache_t * cache)
Robert Moore73459f72005-06-24 00:00:00 -04001094{
Len Brown4be44fc2005-08-05 00:44:28 -04001095 (void)kmem_cache_destroy(cache);
1096 return (AE_OK);
Robert Moore73459f72005-06-24 00:00:00 -04001097}
1098
1099/*******************************************************************************
1100 *
1101 * FUNCTION: acpi_os_release_object
1102 *
1103 * PARAMETERS: Cache - Handle to cache object
1104 * Object - The object to be released
1105 *
1106 * RETURN: None
1107 *
1108 * DESCRIPTION: Release an object to the specified cache. If cache is full,
1109 * the object is deleted.
1110 *
1111 ******************************************************************************/
1112
Len Brown4be44fc2005-08-05 00:44:28 -04001113acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
Robert Moore73459f72005-06-24 00:00:00 -04001114{
Len Brown4be44fc2005-08-05 00:44:28 -04001115 kmem_cache_free(cache, object);
1116 return (AE_OK);
Robert Moore73459f72005-06-24 00:00:00 -04001117}
1118
1119/*******************************************************************************
1120 *
1121 * FUNCTION: acpi_os_acquire_object
1122 *
1123 * PARAMETERS: Cache - Handle to cache object
1124 * ReturnObject - Where the object is returned
1125 *
1126 * RETURN: Status
1127 *
Bob Moore61686122006-03-17 16:44:00 -05001128 * DESCRIPTION: Return a zero-filled object.
Robert Moore73459f72005-06-24 00:00:00 -04001129 *
1130 ******************************************************************************/
1131
Len Brown4be44fc2005-08-05 00:44:28 -04001132void *acpi_os_acquire_object(acpi_cache_t * cache)
Robert Moore73459f72005-06-24 00:00:00 -04001133{
Bob Moore61686122006-03-17 16:44:00 -05001134 void *object = kmem_cache_zalloc(cache, GFP_KERNEL);
Len Brown4be44fc2005-08-05 00:44:28 -04001135 WARN_ON(!object);
1136 return object;
Robert Moore73459f72005-06-24 00:00:00 -04001137}
1138
Bob Mooreb229cf92006-04-21 17:15:00 -04001139/******************************************************************************
1140 *
1141 * FUNCTION: acpi_os_validate_interface
1142 *
1143 * PARAMETERS: interface - Requested interface to be validated
1144 *
1145 * RETURN: AE_OK if interface is supported, AE_SUPPORT otherwise
1146 *
1147 * DESCRIPTION: Match an interface string to the interfaces supported by the
1148 * host. Strings originate from an AML call to the _OSI method.
1149 *
1150 *****************************************************************************/
1151
1152acpi_status
1153acpi_os_validate_interface (char *interface)
1154{
1155
1156 return AE_SUPPORT;
1157}
1158
1159
1160/******************************************************************************
1161 *
1162 * FUNCTION: acpi_os_validate_address
1163 *
1164 * PARAMETERS: space_id - ACPI space ID
1165 * address - Physical address
1166 * length - Address length
1167 *
1168 * RETURN: AE_OK if address/length is valid for the space_id. Otherwise,
1169 * should return AE_AML_ILLEGAL_ADDRESS.
1170 *
1171 * DESCRIPTION: Validate a system address via the host OS. Used to validate
1172 * the addresses accessed by AML operation regions.
1173 *
1174 *****************************************************************************/
1175
1176acpi_status
1177acpi_os_validate_address (
1178 u8 space_id,
1179 acpi_physical_address address,
1180 acpi_size length)
1181{
1182
1183 return AE_OK;
1184}
1185
1186
Robert Moore73459f72005-06-24 00:00:00 -04001187#endif