blob: 0acd0e716ba4f9c2979a71e54a8757e65101de65 [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>
39#include <acpi/acpi.h>
40#include <asm/io.h>
41#include <acpi/acpi_bus.h>
42#include <acpi/processor.h>
43#include <asm/uaccess.h>
44
45#include <linux/efi.h>
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#define _COMPONENT ACPI_OS_SERVICES
Len Brown4be44fc2005-08-05 00:44:28 -040048ACPI_MODULE_NAME("osl")
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#define PREFIX "ACPI: "
Len Brown4be44fc2005-08-05 00:44:28 -040050struct acpi_os_dpc {
51 acpi_osd_exec_callback function;
52 void *context;
David Howells65f27f32006-11-22 14:55:48 +000053 struct work_struct work;
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
Bjorn Helgaas9a47cdb2007-01-18 16:42:55 -070078static void __init acpi_request_region (struct acpi_generic_address *addr,
79 unsigned int length, char *desc)
80{
81 struct resource *res;
82
83 if (!addr->address || !length)
84 return;
85
86 if (addr->address_space_id == ACPI_ADR_SPACE_SYSTEM_IO)
87 res = request_region(addr->address, length, desc);
88 else if (addr->address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
89 res = request_mem_region(addr->address, length, desc);
90}
91
92static int __init acpi_reserve_resources(void)
93{
94 acpi_request_region(&acpi_fadt.xpm1a_evt_blk, acpi_fadt.pm1_evt_len,
95 "ACPI PM1a_EVT_BLK");
96
97 acpi_request_region(&acpi_fadt.xpm1b_evt_blk, acpi_fadt.pm1_evt_len,
98 "ACPI PM1b_EVT_BLK");
99
100 acpi_request_region(&acpi_fadt.xpm1a_cnt_blk, acpi_fadt.pm1_cnt_len,
101 "ACPI PM1a_CNT_BLK");
102
103 acpi_request_region(&acpi_fadt.xpm1b_cnt_blk, acpi_fadt.pm1_cnt_len,
104 "ACPI PM1b_CNT_BLK");
105
106 if (acpi_fadt.pm_tm_len == 4)
107 acpi_request_region(&acpi_fadt.xpm_tmr_blk, 4, "ACPI PM_TMR");
108
109 acpi_request_region(&acpi_fadt.xpm2_cnt_blk, acpi_fadt.pm2_cnt_len,
110 "ACPI PM2_CNT_BLK");
111
112 /* Length of GPE blocks must be a non-negative multiple of 2 */
113
114 if (!(acpi_fadt.gpe0_blk_len & 0x1))
115 acpi_request_region(&acpi_fadt.xgpe0_blk,
116 acpi_fadt.gpe0_blk_len, "ACPI GPE0_BLK");
117
118 if (!(acpi_fadt.gpe1_blk_len & 0x1))
119 acpi_request_region(&acpi_fadt.xgpe1_blk,
120 acpi_fadt.gpe1_blk_len, "ACPI GPE1_BLK");
121
122 return 0;
123}
124device_initcall(acpi_reserve_resources);
125
Len Brown4be44fc2005-08-05 00:44:28 -0400126acpi_status acpi_os_initialize(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127{
128 return AE_OK;
129}
130
Len Brown4be44fc2005-08-05 00:44:28 -0400131acpi_status acpi_os_initialize1(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132{
133 /*
134 * Initialize PCI configuration space access, as we'll need to access
135 * it while walking the namespace (bus 0 and root bridges w/ _BBNs).
136 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 if (!raw_pci_ops) {
Len Brown4be44fc2005-08-05 00:44:28 -0400138 printk(KERN_ERR PREFIX
139 "Access to PCI configuration space unavailable\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 return AE_NULL_ENTRY;
141 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 kacpid_wq = create_singlethread_workqueue("kacpid");
143 BUG_ON(!kacpid_wq);
Linus Torvaldsb976fe12006-11-17 19:31:09 -0800144
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 return AE_OK;
146}
147
Len Brown4be44fc2005-08-05 00:44:28 -0400148acpi_status acpi_os_terminate(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149{
150 if (acpi_irq_handler) {
151 acpi_os_remove_interrupt_handler(acpi_irq_irq,
152 acpi_irq_handler);
153 }
154
155 destroy_workqueue(kacpid_wq);
156
157 return AE_OK;
158}
159
Len Brown4be44fc2005-08-05 00:44:28 -0400160void acpi_os_printf(const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161{
162 va_list args;
163 va_start(args, fmt);
164 acpi_os_vprintf(fmt, args);
165 va_end(args);
166}
Len Brown4be44fc2005-08-05 00:44:28 -0400167
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168EXPORT_SYMBOL(acpi_os_printf);
169
Len Brown4be44fc2005-08-05 00:44:28 -0400170void acpi_os_vprintf(const char *fmt, va_list args)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171{
172 static char buffer[512];
Len Brown4be44fc2005-08-05 00:44:28 -0400173
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 vsprintf(buffer, fmt, args);
175
176#ifdef ENABLE_DEBUGGER
177 if (acpi_in_debugger) {
178 kdb_printf("%s", buffer);
179 } else {
180 printk("%s", buffer);
181 }
182#else
183 printk("%s", buffer);
184#endif
185}
186
Len Brown4be44fc2005-08-05 00:44:28 -0400187acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188{
189 if (efi_enabled) {
190 addr->pointer_type = ACPI_PHYSICAL_POINTER;
Bjorn Helgaasb2c99e32006-03-26 01:37:08 -0800191 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
192 addr->pointer.physical = efi.acpi20;
193 else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
194 addr->pointer.physical = efi.acpi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 else {
Len Brown4be44fc2005-08-05 00:44:28 -0400196 printk(KERN_ERR PREFIX
197 "System description tables not found\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 return AE_NOT_FOUND;
199 }
200 } else {
201 if (ACPI_FAILURE(acpi_find_root_pointer(flags, addr))) {
Len Brown4be44fc2005-08-05 00:44:28 -0400202 printk(KERN_ERR PREFIX
203 "System description tables not found\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 return AE_NOT_FOUND;
205 }
206 }
207
208 return AE_OK;
209}
210
211acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400212acpi_os_map_memory(acpi_physical_address phys, acpi_size size,
213 void __iomem ** virt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214{
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800215 if (phys > ULONG_MAX) {
216 printk(KERN_ERR PREFIX "Cannot map memory that high\n");
217 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 }
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800219 /*
220 * ioremap checks to ensure this is in reserved space
221 */
222 *virt = ioremap((unsigned long)phys, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223
224 if (!*virt)
225 return AE_NO_MEMORY;
226
227 return AE_OK;
228}
Kylene Jo Hall55a82ab2006-01-08 01:03:15 -0800229EXPORT_SYMBOL_GPL(acpi_os_map_memory);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230
Len Brown4be44fc2005-08-05 00:44:28 -0400231void acpi_os_unmap_memory(void __iomem * virt, acpi_size size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232{
233 iounmap(virt);
234}
Kylene Jo Hall55a82ab2006-01-08 01:03:15 -0800235EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236
237#ifdef ACPI_FUTURE_USAGE
238acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400239acpi_os_get_physical_address(void *virt, acpi_physical_address * phys)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240{
Len Brown4be44fc2005-08-05 00:44:28 -0400241 if (!phys || !virt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 return AE_BAD_PARAMETER;
243
244 *phys = virt_to_phys(virt);
245
246 return AE_OK;
247}
248#endif
249
250#define ACPI_MAX_OVERRIDE_LEN 100
251
252static char acpi_os_name[ACPI_MAX_OVERRIDE_LEN];
253
254acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400255acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
256 acpi_string * new_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257{
258 if (!init_val || !new_val)
259 return AE_BAD_PARAMETER;
260
261 *new_val = NULL;
Len Brown4be44fc2005-08-05 00:44:28 -0400262 if (!memcmp(init_val->name, "_OS_", 4) && strlen(acpi_os_name)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 printk(KERN_INFO PREFIX "Overriding _OS definition to '%s'\n",
Len Brown4be44fc2005-08-05 00:44:28 -0400264 acpi_os_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 *new_val = acpi_os_name;
266 }
267
268 return AE_OK;
269}
270
271acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400272acpi_os_table_override(struct acpi_table_header * existing_table,
273 struct acpi_table_header ** new_table)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274{
275 if (!existing_table || !new_table)
276 return AE_BAD_PARAMETER;
277
278#ifdef CONFIG_ACPI_CUSTOM_DSDT
279 if (strncmp(existing_table->signature, "DSDT", 4) == 0)
Len Brown4be44fc2005-08-05 00:44:28 -0400280 *new_table = (struct acpi_table_header *)AmlCode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 else
282 *new_table = NULL;
283#else
284 *new_table = NULL;
285#endif
286 return AE_OK;
287}
288
David Howells7d12e782006-10-05 14:55:46 +0100289static irqreturn_t acpi_irq(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290{
Len Brown4be44fc2005-08-05 00:44:28 -0400291 return (*acpi_irq_handler) (acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292}
293
294acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400295acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
296 void *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297{
298 unsigned int irq;
299
300 /*
301 * Ignore the GSI from the core, and use the value in our copy of the
302 * FADT. It may not be the same if an interrupt source override exists
303 * for the SCI.
304 */
305 gsi = acpi_fadt.sci_int;
306 if (acpi_gsi_to_irq(gsi, &irq) < 0) {
307 printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n",
308 gsi);
309 return AE_OK;
310 }
311
312 acpi_irq_handler = handler;
313 acpi_irq_context = context;
Thomas Gleixnerdace1452006-07-01 19:29:38 -0700314 if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq);
316 return AE_NOT_ACQUIRED;
317 }
318 acpi_irq_irq = irq;
319
320 return AE_OK;
321}
322
Len Brown4be44fc2005-08-05 00:44:28 -0400323acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324{
325 if (irq) {
326 free_irq(irq, acpi_irq);
327 acpi_irq_handler = NULL;
328 acpi_irq_irq = 0;
329 }
330
331 return AE_OK;
332}
333
334/*
335 * Running in interpreter thread context, safe to sleep
336 */
337
Len Brown4be44fc2005-08-05 00:44:28 -0400338void acpi_os_sleep(acpi_integer ms)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339{
Nishanth Aravamudan01a527e2005-11-07 01:01:14 -0800340 schedule_timeout_interruptible(msecs_to_jiffies(ms));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341}
Len Brown4be44fc2005-08-05 00:44:28 -0400342
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343EXPORT_SYMBOL(acpi_os_sleep);
344
Len Brown4be44fc2005-08-05 00:44:28 -0400345void acpi_os_stall(u32 us)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346{
347 while (us) {
348 u32 delay = 1000;
349
350 if (delay > us)
351 delay = us;
352 udelay(delay);
353 touch_nmi_watchdog();
354 us -= delay;
355 }
356}
Len Brown4be44fc2005-08-05 00:44:28 -0400357
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358EXPORT_SYMBOL(acpi_os_stall);
359
360/*
361 * Support ACPI 3.0 AML Timer operand
362 * Returns 64-bit free-running, monotonically increasing timer
363 * with 100ns granularity
364 */
Len Brown4be44fc2005-08-05 00:44:28 -0400365u64 acpi_os_get_timer(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366{
367 static u64 t;
368
369#ifdef CONFIG_HPET
370 /* TBD: use HPET if available */
371#endif
372
373#ifdef CONFIG_X86_PM_TIMER
374 /* TBD: default to PM timer if HPET was not available */
375#endif
376 if (!t)
377 printk(KERN_ERR PREFIX "acpi_os_get_timer() TBD\n");
378
379 return ++t;
380}
381
Len Brown4be44fc2005-08-05 00:44:28 -0400382acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383{
384 u32 dummy;
385
386 if (!value)
387 value = &dummy;
388
Len Brown4be44fc2005-08-05 00:44:28 -0400389 switch (width) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 case 8:
Len Brown4be44fc2005-08-05 00:44:28 -0400391 *(u8 *) value = inb(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 break;
393 case 16:
Len Brown4be44fc2005-08-05 00:44:28 -0400394 *(u16 *) value = inw(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 break;
396 case 32:
Len Brown4be44fc2005-08-05 00:44:28 -0400397 *(u32 *) value = inl(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 break;
399 default:
400 BUG();
401 }
402
403 return AE_OK;
404}
Len Brown4be44fc2005-08-05 00:44:28 -0400405
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406EXPORT_SYMBOL(acpi_os_read_port);
407
Len Brown4be44fc2005-08-05 00:44:28 -0400408acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409{
Len Brown4be44fc2005-08-05 00:44:28 -0400410 switch (width) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 case 8:
412 outb(value, port);
413 break;
414 case 16:
415 outw(value, port);
416 break;
417 case 32:
418 outl(value, port);
419 break;
420 default:
421 BUG();
422 }
423
424 return AE_OK;
425}
Len Brown4be44fc2005-08-05 00:44:28 -0400426
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427EXPORT_SYMBOL(acpi_os_write_port);
428
429acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400430acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431{
Len Brown4be44fc2005-08-05 00:44:28 -0400432 u32 dummy;
433 void __iomem *virt_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800435 virt_addr = ioremap(phys_addr, width);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 if (!value)
437 value = &dummy;
438
439 switch (width) {
440 case 8:
Len Brown4be44fc2005-08-05 00:44:28 -0400441 *(u8 *) value = readb(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 break;
443 case 16:
Len Brown4be44fc2005-08-05 00:44:28 -0400444 *(u16 *) value = readw(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 break;
446 case 32:
Len Brown4be44fc2005-08-05 00:44:28 -0400447 *(u32 *) value = readl(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 break;
449 default:
450 BUG();
451 }
452
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800453 iounmap(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454
455 return AE_OK;
456}
457
458acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400459acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460{
Len Brown4be44fc2005-08-05 00:44:28 -0400461 void __iomem *virt_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800463 virt_addr = ioremap(phys_addr, width);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464
465 switch (width) {
466 case 8:
467 writeb(value, virt_addr);
468 break;
469 case 16:
470 writew(value, virt_addr);
471 break;
472 case 32:
473 writel(value, virt_addr);
474 break;
475 default:
476 BUG();
477 }
478
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800479 iounmap(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480
481 return AE_OK;
482}
483
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400485acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
486 void *value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487{
488 int result, size;
489
490 if (!value)
491 return AE_BAD_PARAMETER;
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->read(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}
Len Brown4be44fc2005-08-05 00:44:28 -0400515
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516EXPORT_SYMBOL(acpi_os_read_pci_configuration);
517
518acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400519acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
520 acpi_integer value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521{
522 int result, size;
523
524 switch (width) {
525 case 8:
526 size = 1;
527 break;
528 case 16:
529 size = 2;
530 break;
531 case 32:
532 size = 4;
533 break;
534 default:
535 return AE_ERROR;
536 }
537
538 BUG_ON(!raw_pci_ops);
539
540 result = raw_pci_ops->write(pci_id->segment, pci_id->bus,
Len Brown4be44fc2005-08-05 00:44:28 -0400541 PCI_DEVFN(pci_id->device, pci_id->function),
542 reg, size, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
544 return (result ? AE_ERROR : AE_OK);
545}
546
547/* TODO: Change code to take advantage of driver model more */
Len Brown4be44fc2005-08-05 00:44:28 -0400548static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */
549 acpi_handle chandle, /* current node */
550 struct acpi_pci_id **id,
551 int *is_bridge, u8 * bus_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552{
Len Brown4be44fc2005-08-05 00:44:28 -0400553 acpi_handle handle;
554 struct acpi_pci_id *pci_id = *id;
555 acpi_status status;
556 unsigned long temp;
557 acpi_object_type type;
558 u8 tu8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559
560 acpi_get_parent(chandle, &handle);
561 if (handle != rhandle) {
Len Brown4be44fc2005-08-05 00:44:28 -0400562 acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge,
563 bus_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564
565 status = acpi_get_type(handle, &type);
Len Brown4be44fc2005-08-05 00:44:28 -0400566 if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 return;
568
Len Brown4be44fc2005-08-05 00:44:28 -0400569 status =
570 acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
571 &temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 if (ACPI_SUCCESS(status)) {
Len Brown4be44fc2005-08-05 00:44:28 -0400573 pci_id->device = ACPI_HIWORD(ACPI_LODWORD(temp));
574 pci_id->function = ACPI_LOWORD(ACPI_LODWORD(temp));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575
576 if (*is_bridge)
577 pci_id->bus = *bus_number;
578
579 /* any nicer way to get bus number of bridge ? */
Len Brown4be44fc2005-08-05 00:44:28 -0400580 status =
581 acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8,
582 8);
583 if (ACPI_SUCCESS(status)
584 && ((tu8 & 0x7f) == 1 || (tu8 & 0x7f) == 2)) {
585 status =
586 acpi_os_read_pci_configuration(pci_id, 0x18,
587 &tu8, 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 if (!ACPI_SUCCESS(status)) {
589 /* Certainly broken... FIX ME */
590 return;
591 }
592 *is_bridge = 1;
593 pci_id->bus = tu8;
Len Brown4be44fc2005-08-05 00:44:28 -0400594 status =
595 acpi_os_read_pci_configuration(pci_id, 0x19,
596 &tu8, 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 if (ACPI_SUCCESS(status)) {
598 *bus_number = tu8;
599 }
600 } else
601 *is_bridge = 0;
602 }
603 }
604}
605
Len Brown4be44fc2005-08-05 00:44:28 -0400606void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */
607 acpi_handle chandle, /* current node */
608 struct acpi_pci_id **id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609{
610 int is_bridge = 1;
611 u8 bus_number = (*id)->bus;
612
613 acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number);
614}
615
David Howells65f27f32006-11-22 14:55:48 +0000616static void acpi_os_execute_deferred(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617{
David Howells65f27f32006-11-22 14:55:48 +0000618 struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 if (!dpc) {
Len Brown64684632006-06-26 23:41:38 -0400620 printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
Patrick Mocheld550d982006-06-27 00:41:40 -0400621 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 }
623
624 dpc->function(dpc->context);
625
626 kfree(dpc);
627
Patrick Mocheld550d982006-06-27 00:41:40 -0400628 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629}
630
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400631/*******************************************************************************
632 *
633 * FUNCTION: acpi_os_execute
634 *
635 * PARAMETERS: Type - Type of the callback
636 * Function - Function to be executed
637 * Context - Function parameters
638 *
639 * RETURN: Status
640 *
641 * DESCRIPTION: Depending on type, either queues function for deferred execution or
642 * immediately executes function on a separate thread.
643 *
644 ******************************************************************************/
645
646acpi_status acpi_os_execute(acpi_execute_type type,
Len Brown4be44fc2005-08-05 00:44:28 -0400647 acpi_osd_exec_callback function, void *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648{
Len Brown4be44fc2005-08-05 00:44:28 -0400649 acpi_status status = AE_OK;
650 struct acpi_os_dpc *dpc;
Len Brown72945b22006-07-12 22:46:42 -0400651
Linus Torvaldsb976fe12006-11-17 19:31:09 -0800652 ACPI_FUNCTION_TRACE("os_queue_for_execution");
653
Len Brown72945b22006-07-12 22:46:42 -0400654 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
655 "Scheduling function [%p(%p)] for deferred execution.\n",
656 function, context));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657
658 if (!function)
Linus Torvaldsb976fe12006-11-17 19:31:09 -0800659 return_ACPI_STATUS(AE_BAD_PARAMETER);
Len Brown72945b22006-07-12 22:46:42 -0400660
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 /*
662 * Allocate/initialize DPC structure. Note that this memory will be
David Howells65f27f32006-11-22 14:55:48 +0000663 * freed by the callee. The kernel handles the work_struct list in a
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 * way that allows us to also free its memory inside the callee.
665 * Because we may want to schedule several tasks with different
666 * parameters we can't use the approach some kernel code uses of
David Howells65f27f32006-11-22 14:55:48 +0000667 * having a static work_struct.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 */
Len Brown72945b22006-07-12 22:46:42 -0400669
David Howells65f27f32006-11-22 14:55:48 +0000670 dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 if (!dpc)
Linus Torvaldsb976fe12006-11-17 19:31:09 -0800672 return_ACPI_STATUS(AE_NO_MEMORY);
673
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 dpc->function = function;
675 dpc->context = context;
Linus Torvaldsb976fe12006-11-17 19:31:09 -0800676
David Howells65f27f32006-11-22 14:55:48 +0000677 INIT_WORK(&dpc->work, acpi_os_execute_deferred);
678 if (!queue_work(kacpid_wq, &dpc->work)) {
Linus Torvaldsb976fe12006-11-17 19:31:09 -0800679 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
680 "Call to queue_work() failed.\n"));
Alexey Y. Starikovskiy37605a62006-09-26 04:20:47 -0400681 kfree(dpc);
Linus Torvaldsb976fe12006-11-17 19:31:09 -0800682 status = AE_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 }
Linus Torvaldsb976fe12006-11-17 19:31:09 -0800684
685 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686}
Len Brown4be44fc2005-08-05 00:44:28 -0400687
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400688EXPORT_SYMBOL(acpi_os_execute);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689
Len Brown4be44fc2005-08-05 00:44:28 -0400690void acpi_os_wait_events_complete(void *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691{
692 flush_workqueue(kacpid_wq);
693}
Len Brown4be44fc2005-08-05 00:44:28 -0400694
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695EXPORT_SYMBOL(acpi_os_wait_events_complete);
696
697/*
698 * Allocate the memory for a spinlock and initialize it.
699 */
Bob Moore967440e2006-06-23 17:04:00 -0400700acpi_status acpi_os_create_lock(acpi_spinlock * handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701{
Bob Moore967440e2006-06-23 17:04:00 -0400702 spin_lock_init(*handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703
Patrick Mocheld550d982006-06-27 00:41:40 -0400704 return AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705}
706
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707/*
708 * Deallocate the memory for a spinlock.
709 */
Bob Moore967440e2006-06-23 17:04:00 -0400710void acpi_os_delete_lock(acpi_spinlock handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711{
Patrick Mocheld550d982006-06-27 00:41:40 -0400712 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713}
714
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400716acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717{
Len Brown4be44fc2005-08-05 00:44:28 -0400718 struct semaphore *sem = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720
721 sem = acpi_os_allocate(sizeof(struct semaphore));
722 if (!sem)
Patrick Mocheld550d982006-06-27 00:41:40 -0400723 return AE_NO_MEMORY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 memset(sem, 0, sizeof(struct semaphore));
725
726 sema_init(sem, initial_units);
727
Len Brown4be44fc2005-08-05 00:44:28 -0400728 *handle = (acpi_handle *) sem;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729
Len Brown4be44fc2005-08-05 00:44:28 -0400730 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Creating semaphore[%p|%d].\n",
731 *handle, initial_units));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732
Patrick Mocheld550d982006-06-27 00:41:40 -0400733 return AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735
Len Brown4be44fc2005-08-05 00:44:28 -0400736EXPORT_SYMBOL(acpi_os_create_semaphore);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
738/*
739 * TODO: A better way to delete semaphores? Linux doesn't have a
740 * 'delete_semaphore()' function -- may result in an invalid
741 * pointer dereference for non-synchronized consumers. Should
742 * we at least check for blocked threads and signal/cancel them?
743 */
744
Len Brown4be44fc2005-08-05 00:44:28 -0400745acpi_status acpi_os_delete_semaphore(acpi_handle handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746{
Len Brown4be44fc2005-08-05 00:44:28 -0400747 struct semaphore *sem = (struct semaphore *)handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749
750 if (!sem)
Patrick Mocheld550d982006-06-27 00:41:40 -0400751 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752
Len Brown4be44fc2005-08-05 00:44:28 -0400753 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
Len Brown02438d82006-06-30 03:19:10 -0400755 kfree(sem);
Len Brown4be44fc2005-08-05 00:44:28 -0400756 sem = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757
Patrick Mocheld550d982006-06-27 00:41:40 -0400758 return AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760
Len Brown4be44fc2005-08-05 00:44:28 -0400761EXPORT_SYMBOL(acpi_os_delete_semaphore);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762
763/*
764 * TODO: The kernel doesn't have a 'down_timeout' function -- had to
765 * improvise. The process is to sleep for one scheduler quantum
766 * until the semaphore becomes available. Downside is that this
767 * may result in starvation for timeout-based waits when there's
768 * lots of semaphore activity.
769 *
770 * TODO: Support for units > 1?
771 */
Len Brown4be44fc2005-08-05 00:44:28 -0400772acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773{
Len Brown4be44fc2005-08-05 00:44:28 -0400774 acpi_status status = AE_OK;
775 struct semaphore *sem = (struct semaphore *)handle;
776 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778
779 if (!sem || (units < 1))
Patrick Mocheld550d982006-06-27 00:41:40 -0400780 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781
782 if (units > 1)
Patrick Mocheld550d982006-06-27 00:41:40 -0400783 return AE_SUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784
Len Brown4be44fc2005-08-05 00:44:28 -0400785 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n",
786 handle, units, timeout));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787
Len Brownd68909f2006-08-16 19:16:58 -0400788 /*
789 * This can be called during resume with interrupts off.
790 * Like boot-time, we should be single threaded and will
791 * always get the lock if we try -- timeout or not.
792 * If this doesn't succeed, then we will oops courtesy of
793 * might_sleep() in down().
794 */
795 if (!down_trylock(sem))
796 return AE_OK;
797
Len Brown4be44fc2005-08-05 00:44:28 -0400798 switch (timeout) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 /*
800 * No Wait:
801 * --------
802 * A zero timeout value indicates that we shouldn't wait - just
803 * acquire the semaphore if available otherwise return AE_TIME
804 * (a.k.a. 'would block').
805 */
Len Brown4be44fc2005-08-05 00:44:28 -0400806 case 0:
807 if (down_trylock(sem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 status = AE_TIME;
809 break;
810
811 /*
812 * Wait Indefinitely:
813 * ------------------
814 */
Len Brown4be44fc2005-08-05 00:44:28 -0400815 case ACPI_WAIT_FOREVER:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 down(sem);
817 break;
818
819 /*
820 * Wait w/ Timeout:
821 * ----------------
822 */
Len Brown4be44fc2005-08-05 00:44:28 -0400823 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 // TODO: A better timeout algorithm?
825 {
826 int i = 0;
Len Brown4be44fc2005-08-05 00:44:28 -0400827 static const int quantum_ms = 1000 / HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828
829 ret = down_trylock(sem);
Yu Lumingdacd9b82005-12-31 01:45:00 -0500830 for (i = timeout; (i > 0 && ret != 0); i -= quantum_ms) {
Nishanth Aravamudan01a527e2005-11-07 01:01:14 -0800831 schedule_timeout_interruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 ret = down_trylock(sem);
833 }
Len Brown4be44fc2005-08-05 00:44:28 -0400834
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 if (ret != 0)
836 status = AE_TIME;
837 }
838 break;
839 }
840
841 if (ACPI_FAILURE(status)) {
Bjorn Helgaas9e7e2c02006-04-27 05:25:00 -0400842 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
Thomas Renningera6fc6722006-06-26 23:58:43 -0400843 "Failed to acquire semaphore[%p|%d|%d], %s",
Len Brown4be44fc2005-08-05 00:44:28 -0400844 handle, units, timeout,
845 acpi_format_exception(status)));
846 } else {
847 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
Thomas Renningera6fc6722006-06-26 23:58:43 -0400848 "Acquired semaphore[%p|%d|%d]", handle,
Len Brown4be44fc2005-08-05 00:44:28 -0400849 units, timeout));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 }
851
Patrick Mocheld550d982006-06-27 00:41:40 -0400852 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854
Len Brown4be44fc2005-08-05 00:44:28 -0400855EXPORT_SYMBOL(acpi_os_wait_semaphore);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856
857/*
858 * TODO: Support for units > 1?
859 */
Len Brown4be44fc2005-08-05 00:44:28 -0400860acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861{
Len Brown4be44fc2005-08-05 00:44:28 -0400862 struct semaphore *sem = (struct semaphore *)handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864
865 if (!sem || (units < 1))
Patrick Mocheld550d982006-06-27 00:41:40 -0400866 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867
868 if (units > 1)
Patrick Mocheld550d982006-06-27 00:41:40 -0400869 return AE_SUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870
Len Brown4be44fc2005-08-05 00:44:28 -0400871 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle,
872 units));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873
874 up(sem);
875
Patrick Mocheld550d982006-06-27 00:41:40 -0400876 return AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877}
Len Brown4be44fc2005-08-05 00:44:28 -0400878
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879EXPORT_SYMBOL(acpi_os_signal_semaphore);
880
881#ifdef ACPI_FUTURE_USAGE
Len Brown4be44fc2005-08-05 00:44:28 -0400882u32 acpi_os_get_line(char *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883{
884
885#ifdef ENABLE_DEBUGGER
886 if (acpi_in_debugger) {
887 u32 chars;
888
889 kdb_read(buffer, sizeof(line_buf));
890
891 /* remove the CR kdb includes */
892 chars = strlen(buffer) - 1;
893 buffer[chars] = '\0';
894 }
895#endif
896
897 return 0;
898}
Len Brown4be44fc2005-08-05 00:44:28 -0400899#endif /* ACPI_FUTURE_USAGE */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900
901/* Assumes no unreadable holes inbetween */
Len Brown4be44fc2005-08-05 00:44:28 -0400902u8 acpi_os_readable(void *ptr, acpi_size len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903{
Len Brown4be44fc2005-08-05 00:44:28 -0400904#if defined(__i386__) || defined(__x86_64__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 char tmp;
Len Brown4be44fc2005-08-05 00:44:28 -0400906 return !__get_user(tmp, (char __user *)ptr)
907 && !__get_user(tmp, (char __user *)ptr + len - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908#endif
909 return 1;
910}
911
912#ifdef ACPI_FUTURE_USAGE
Len Brown4be44fc2005-08-05 00:44:28 -0400913u8 acpi_os_writable(void *ptr, acpi_size len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914{
915 /* could do dummy write (racy) or a kernel page table lookup.
916 The later may be difficult at early boot when kmap doesn't work yet. */
917 return 1;
918}
919#endif
920
Len Brown4be44fc2005-08-05 00:44:28 -0400921acpi_status acpi_os_signal(u32 function, void *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922{
Len Brown4be44fc2005-08-05 00:44:28 -0400923 switch (function) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 case ACPI_SIGNAL_FATAL:
925 printk(KERN_ERR PREFIX "Fatal opcode executed\n");
926 break;
927 case ACPI_SIGNAL_BREAKPOINT:
928 /*
929 * AML Breakpoint
930 * ACPI spec. says to treat it as a NOP unless
931 * you are debugging. So if/when we integrate
932 * AML debugger into the kernel debugger its
933 * hook will go here. But until then it is
934 * not useful to print anything on breakpoints.
935 */
936 break;
937 default:
938 break;
939 }
940
941 return AE_OK;
942}
Len Brown4be44fc2005-08-05 00:44:28 -0400943
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944EXPORT_SYMBOL(acpi_os_signal);
945
Len Brown4be44fc2005-08-05 00:44:28 -0400946static int __init acpi_os_name_setup(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947{
948 char *p = acpi_os_name;
Len Brown4be44fc2005-08-05 00:44:28 -0400949 int count = ACPI_MAX_OVERRIDE_LEN - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950
951 if (!str || !*str)
952 return 0;
953
954 for (; count-- && str && *str; str++) {
955 if (isalnum(*str) || *str == ' ' || *str == ':')
956 *p++ = *str;
957 else if (*str == '\'' || *str == '"')
958 continue;
959 else
960 break;
961 }
962 *p = 0;
963
964 return 1;
Len Brown4be44fc2005-08-05 00:44:28 -0400965
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966}
967
968__setup("acpi_os_name=", acpi_os_name_setup);
969
970/*
971 * _OSI control
972 * empty string disables _OSI
973 * TBD additional string adds to _OSI
974 */
Len Brown4be44fc2005-08-05 00:44:28 -0400975static int __init acpi_osi_setup(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976{
977 if (str == NULL || *str == '\0') {
978 printk(KERN_INFO PREFIX "_OSI method disabled\n");
979 acpi_gbl_create_osi_method = FALSE;
Len Brown4be44fc2005-08-05 00:44:28 -0400980 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 /* TBD */
Len Brown4be44fc2005-08-05 00:44:28 -0400982 printk(KERN_ERR PREFIX "_OSI additional string ignored -- %s\n",
983 str);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 }
985
986 return 1;
987}
988
989__setup("acpi_osi=", acpi_osi_setup);
990
991/* enable serialization to combat AE_ALREADY_EXISTS errors */
Len Brown4be44fc2005-08-05 00:44:28 -0400992static int __init acpi_serialize_setup(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993{
994 printk(KERN_INFO PREFIX "serialize enabled\n");
995
996 acpi_gbl_all_methods_serialized = TRUE;
997
998 return 1;
999}
1000
1001__setup("acpi_serialize", acpi_serialize_setup);
1002
1003/*
1004 * Wake and Run-Time GPES are expected to be separate.
1005 * We disable wake-GPEs at run-time to prevent spurious
1006 * interrupts.
1007 *
1008 * However, if a system exists that shares Wake and
1009 * Run-time events on the same GPE this flag is available
1010 * to tell Linux to keep the wake-time GPEs enabled at run-time.
1011 */
Len Brown4be44fc2005-08-05 00:44:28 -04001012static int __init acpi_wake_gpes_always_on_setup(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013{
1014 printk(KERN_INFO PREFIX "wake GPEs not disabled\n");
1015
1016 acpi_gbl_leave_wake_gpes_disabled = FALSE;
1017
1018 return 1;
1019}
1020
1021__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
1022
Adrian Bunk8713cbe2005-09-02 17:16:48 -04001023static int __init acpi_hotkey_setup(char *str)
Luming Yufb9802f2005-03-18 18:03:45 -05001024{
Luming Yu30e332f2005-08-12 00:31:00 -04001025 acpi_specific_hotkey_enabled = FALSE;
Luming Yufb9802f2005-03-18 18:03:45 -05001026 return 1;
1027}
1028
Luming Yu30e332f2005-08-12 00:31:00 -04001029__setup("acpi_generic_hotkey", acpi_hotkey_setup);
Luming Yufb9802f2005-03-18 18:03:45 -05001030
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031/*
1032 * max_cstate is defined in the base kernel so modules can
1033 * change it w/o depending on the state of the processor module.
1034 */
1035unsigned int max_cstate = ACPI_PROCESSOR_MAX_POWER;
1036
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037EXPORT_SYMBOL(max_cstate);
Robert Moore73459f72005-06-24 00:00:00 -04001038
1039/*
1040 * Acquire a spinlock.
1041 *
1042 * handle is a pointer to the spinlock_t.
Robert Moore73459f72005-06-24 00:00:00 -04001043 */
1044
Bob Moore967440e2006-06-23 17:04:00 -04001045acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp)
Robert Moore73459f72005-06-24 00:00:00 -04001046{
Bob Mooreb8e4d892006-01-27 16:43:00 -05001047 acpi_cpu_flags flags;
Bob Moore967440e2006-06-23 17:04:00 -04001048 spin_lock_irqsave(lockp, flags);
Robert Moore73459f72005-06-24 00:00:00 -04001049 return flags;
1050}
1051
1052/*
1053 * Release a spinlock. See above.
1054 */
1055
Bob Moore967440e2006-06-23 17:04:00 -04001056void acpi_os_release_lock(acpi_spinlock lockp, acpi_cpu_flags flags)
Robert Moore73459f72005-06-24 00:00:00 -04001057{
Bob Moore967440e2006-06-23 17:04:00 -04001058 spin_unlock_irqrestore(lockp, flags);
Robert Moore73459f72005-06-24 00:00:00 -04001059}
1060
Robert Moore73459f72005-06-24 00:00:00 -04001061#ifndef ACPI_USE_LOCAL_CACHE
1062
1063/*******************************************************************************
1064 *
1065 * FUNCTION: acpi_os_create_cache
1066 *
Bob Mooreb229cf92006-04-21 17:15:00 -04001067 * PARAMETERS: name - Ascii name for the cache
1068 * size - Size of each cached object
1069 * depth - Maximum depth of the cache (in objects) <ignored>
1070 * cache - Where the new cache object is returned
Robert Moore73459f72005-06-24 00:00:00 -04001071 *
Bob Mooreb229cf92006-04-21 17:15:00 -04001072 * RETURN: status
Robert Moore73459f72005-06-24 00:00:00 -04001073 *
1074 * DESCRIPTION: Create a cache object
1075 *
1076 ******************************************************************************/
1077
1078acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -04001079acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache)
Robert Moore73459f72005-06-24 00:00:00 -04001080{
Len Brown4be44fc2005-08-05 00:44:28 -04001081 *cache = kmem_cache_create(name, size, 0, 0, NULL, NULL);
Bob Mooreb229cf92006-04-21 17:15:00 -04001082 if (cache == NULL)
1083 return AE_ERROR;
1084 else
1085 return AE_OK;
Robert Moore73459f72005-06-24 00:00:00 -04001086}
1087
1088/*******************************************************************************
1089 *
1090 * FUNCTION: acpi_os_purge_cache
1091 *
1092 * PARAMETERS: Cache - Handle to cache object
1093 *
1094 * RETURN: Status
1095 *
1096 * DESCRIPTION: Free all objects within the requested cache.
1097 *
1098 ******************************************************************************/
1099
Len Brown4be44fc2005-08-05 00:44:28 -04001100acpi_status acpi_os_purge_cache(acpi_cache_t * cache)
Robert Moore73459f72005-06-24 00:00:00 -04001101{
Len Brown4be44fc2005-08-05 00:44:28 -04001102 (void)kmem_cache_shrink(cache);
1103 return (AE_OK);
Robert Moore73459f72005-06-24 00:00:00 -04001104}
1105
1106/*******************************************************************************
1107 *
1108 * FUNCTION: acpi_os_delete_cache
1109 *
1110 * PARAMETERS: Cache - Handle to cache object
1111 *
1112 * RETURN: Status
1113 *
1114 * DESCRIPTION: Free all objects within the requested cache and delete the
1115 * cache object.
1116 *
1117 ******************************************************************************/
1118
Len Brown4be44fc2005-08-05 00:44:28 -04001119acpi_status acpi_os_delete_cache(acpi_cache_t * cache)
Robert Moore73459f72005-06-24 00:00:00 -04001120{
Alexey Dobriyan1a1d92c2006-09-27 01:49:40 -07001121 kmem_cache_destroy(cache);
Len Brown4be44fc2005-08-05 00:44:28 -04001122 return (AE_OK);
Robert Moore73459f72005-06-24 00:00:00 -04001123}
1124
1125/*******************************************************************************
1126 *
1127 * FUNCTION: acpi_os_release_object
1128 *
1129 * PARAMETERS: Cache - Handle to cache object
1130 * Object - The object to be released
1131 *
1132 * RETURN: None
1133 *
1134 * DESCRIPTION: Release an object to the specified cache. If cache is full,
1135 * the object is deleted.
1136 *
1137 ******************************************************************************/
1138
Len Brown4be44fc2005-08-05 00:44:28 -04001139acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
Robert Moore73459f72005-06-24 00:00:00 -04001140{
Len Brown4be44fc2005-08-05 00:44:28 -04001141 kmem_cache_free(cache, object);
1142 return (AE_OK);
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