ACPI: Delete Intel Customer Reference Board (CRB) from OSI(Linux) DMI list
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / acpi / osl.c
CommitLineData
1da177e4
LT
1/*
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
1da177e4
LT
28#include <linux/module.h>
29#include <linux/kernel.h>
30#include <linux/slab.h>
31#include <linux/mm.h>
32#include <linux/pci.h>
1da177e4
LT
33#include <linux/interrupt.h>
34#include <linux/kmod.h>
35#include <linux/delay.h>
f507654d 36#include <linux/dmi.h>
1da177e4
LT
37#include <linux/workqueue.h>
38#include <linux/nmi.h>
ad71860a 39#include <linux/acpi.h>
1da177e4
LT
40#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
1da177e4 48#define _COMPONENT ACPI_OS_SERVICES
f52fd66d 49ACPI_MODULE_NAME("osl");
1da177e4 50#define PREFIX "ACPI: "
4be44fcd
LB
51struct acpi_os_dpc {
52 acpi_osd_exec_callback function;
53 void *context;
65f27f38 54 struct work_struct work;
1da177e4
LT
55};
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];
4be44fcd 69#endif /*ENABLE_DEBUGGER */
1da177e4
LT
70
71static unsigned int acpi_irq_irq;
72static acpi_osd_handler acpi_irq_handler;
73static void *acpi_irq_context;
74static struct workqueue_struct *kacpid_wq;
88db5e14 75static struct workqueue_struct *kacpi_notify_wq;
1da177e4 76
ae00d812
LB
77#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */
78static char osi_additional_string[OSI_STRING_LENGTH_MAX];
79
3312111d 80static int osi_linux; /* disable _OSI(Linux) by default */
f507654d 81
9a47cdb1
BH
82static void __init acpi_request_region (struct acpi_generic_address *addr,
83 unsigned int length, char *desc)
84{
85 struct resource *res;
86
87 if (!addr->address || !length)
88 return;
89
eee3c859 90 if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_IO)
9a47cdb1 91 res = request_region(addr->address, length, desc);
eee3c859 92 else if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
9a47cdb1
BH
93 res = request_mem_region(addr->address, length, desc);
94}
95
96static int __init acpi_reserve_resources(void)
97{
eee3c859 98 acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length,
9a47cdb1
BH
99 "ACPI PM1a_EVT_BLK");
100
eee3c859 101 acpi_request_region(&acpi_gbl_FADT.xpm1b_event_block, acpi_gbl_FADT.pm1_event_length,
9a47cdb1
BH
102 "ACPI PM1b_EVT_BLK");
103
eee3c859 104 acpi_request_region(&acpi_gbl_FADT.xpm1a_control_block, acpi_gbl_FADT.pm1_control_length,
9a47cdb1
BH
105 "ACPI PM1a_CNT_BLK");
106
eee3c859 107 acpi_request_region(&acpi_gbl_FADT.xpm1b_control_block, acpi_gbl_FADT.pm1_control_length,
9a47cdb1
BH
108 "ACPI PM1b_CNT_BLK");
109
eee3c859
LB
110 if (acpi_gbl_FADT.pm_timer_length == 4)
111 acpi_request_region(&acpi_gbl_FADT.xpm_timer_block, 4, "ACPI PM_TMR");
9a47cdb1 112
eee3c859 113 acpi_request_region(&acpi_gbl_FADT.xpm2_control_block, acpi_gbl_FADT.pm2_control_length,
9a47cdb1
BH
114 "ACPI PM2_CNT_BLK");
115
116 /* Length of GPE blocks must be a non-negative multiple of 2 */
117
eee3c859
LB
118 if (!(acpi_gbl_FADT.gpe0_block_length & 0x1))
119 acpi_request_region(&acpi_gbl_FADT.xgpe0_block,
120 acpi_gbl_FADT.gpe0_block_length, "ACPI GPE0_BLK");
9a47cdb1 121
eee3c859
LB
122 if (!(acpi_gbl_FADT.gpe1_block_length & 0x1))
123 acpi_request_region(&acpi_gbl_FADT.xgpe1_block,
124 acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK");
9a47cdb1
BH
125
126 return 0;
127}
128device_initcall(acpi_reserve_resources);
129
dd272b57 130acpi_status __init acpi_os_initialize(void)
1da177e4
LT
131{
132 return AE_OK;
133}
134
4be44fcd 135acpi_status acpi_os_initialize1(void)
1da177e4
LT
136{
137 /*
138 * Initialize PCI configuration space access, as we'll need to access
139 * it while walking the namespace (bus 0 and root bridges w/ _BBNs).
140 */
1da177e4 141 if (!raw_pci_ops) {
4be44fcd
LB
142 printk(KERN_ERR PREFIX
143 "Access to PCI configuration space unavailable\n");
1da177e4
LT
144 return AE_NULL_ENTRY;
145 }
1da177e4 146 kacpid_wq = create_singlethread_workqueue("kacpid");
88db5e14 147 kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify");
1da177e4 148 BUG_ON(!kacpid_wq);
88db5e14 149 BUG_ON(!kacpi_notify_wq);
1da177e4
LT
150 return AE_OK;
151}
152
4be44fcd 153acpi_status acpi_os_terminate(void)
1da177e4
LT
154{
155 if (acpi_irq_handler) {
156 acpi_os_remove_interrupt_handler(acpi_irq_irq,
157 acpi_irq_handler);
158 }
159
160 destroy_workqueue(kacpid_wq);
88db5e14 161 destroy_workqueue(kacpi_notify_wq);
1da177e4
LT
162
163 return AE_OK;
164}
165
4be44fcd 166void acpi_os_printf(const char *fmt, ...)
1da177e4
LT
167{
168 va_list args;
169 va_start(args, fmt);
170 acpi_os_vprintf(fmt, args);
171 va_end(args);
172}
4be44fcd 173
1da177e4
LT
174EXPORT_SYMBOL(acpi_os_printf);
175
4be44fcd 176void acpi_os_vprintf(const char *fmt, va_list args)
1da177e4
LT
177{
178 static char buffer[512];
4be44fcd 179
1da177e4
LT
180 vsprintf(buffer, fmt, args);
181
182#ifdef ENABLE_DEBUGGER
183 if (acpi_in_debugger) {
184 kdb_printf("%s", buffer);
185 } else {
186 printk("%s", buffer);
187 }
188#else
189 printk("%s", buffer);
190#endif
191}
192
ad71860a 193acpi_physical_address __init acpi_os_get_root_pointer(void)
1da177e4
LT
194{
195 if (efi_enabled) {
b2c99e3c 196 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
ad71860a 197 return efi.acpi20;
b2c99e3c 198 else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
ad71860a 199 return efi.acpi;
1da177e4 200 else {
4be44fcd
LB
201 printk(KERN_ERR PREFIX
202 "System description tables not found\n");
ad71860a 203 return 0;
1da177e4 204 }
ad71860a
AS
205 } else
206 return acpi_find_rsdp();
1da177e4
LT
207}
208
ad71860a 209void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
1da177e4 210{
9f4fd61f
BH
211 if (phys > ULONG_MAX) {
212 printk(KERN_ERR PREFIX "Cannot map memory that high\n");
70c0846e 213 return NULL;
1da177e4 214 }
ad71860a
AS
215 if (acpi_gbl_permanent_mmap)
216 /*
217 * ioremap checks to ensure this is in reserved space
218 */
219 return ioremap((unsigned long)phys, size);
220 else
221 return __acpi_map_table((unsigned long)phys, size);
1da177e4 222}
55a82ab3 223EXPORT_SYMBOL_GPL(acpi_os_map_memory);
1da177e4 224
4be44fcd 225void acpi_os_unmap_memory(void __iomem * virt, acpi_size size)
1da177e4 226{
ad71860a
AS
227 if (acpi_gbl_permanent_mmap) {
228 iounmap(virt);
229 }
1da177e4 230}
55a82ab3 231EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
1da177e4
LT
232
233#ifdef ACPI_FUTURE_USAGE
234acpi_status
4be44fcd 235acpi_os_get_physical_address(void *virt, acpi_physical_address * phys)
1da177e4 236{
4be44fcd 237 if (!phys || !virt)
1da177e4
LT
238 return AE_BAD_PARAMETER;
239
240 *phys = virt_to_phys(virt);
241
242 return AE_OK;
243}
244#endif
245
246#define ACPI_MAX_OVERRIDE_LEN 100
247
248static char acpi_os_name[ACPI_MAX_OVERRIDE_LEN];
249
250acpi_status
4be44fcd
LB
251acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
252 acpi_string * new_val)
1da177e4
LT
253{
254 if (!init_val || !new_val)
255 return AE_BAD_PARAMETER;
256
257 *new_val = NULL;
4be44fcd 258 if (!memcmp(init_val->name, "_OS_", 4) && strlen(acpi_os_name)) {
1da177e4 259 printk(KERN_INFO PREFIX "Overriding _OS definition to '%s'\n",
4be44fcd 260 acpi_os_name);
1da177e4
LT
261 *new_val = acpi_os_name;
262 }
263
264 return AE_OK;
265}
266
267acpi_status
4be44fcd
LB
268acpi_os_table_override(struct acpi_table_header * existing_table,
269 struct acpi_table_header ** new_table)
1da177e4
LT
270{
271 if (!existing_table || !new_table)
272 return AE_BAD_PARAMETER;
273
274#ifdef CONFIG_ACPI_CUSTOM_DSDT
275 if (strncmp(existing_table->signature, "DSDT", 4) == 0)
4be44fcd 276 *new_table = (struct acpi_table_header *)AmlCode;
1da177e4
LT
277 else
278 *new_table = NULL;
279#else
280 *new_table = NULL;
281#endif
282 return AE_OK;
283}
284
7d12e780 285static irqreturn_t acpi_irq(int irq, void *dev_id)
1da177e4 286{
4be44fcd 287 return (*acpi_irq_handler) (acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE;
1da177e4
LT
288}
289
290acpi_status
4be44fcd
LB
291acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
292 void *context)
1da177e4
LT
293{
294 unsigned int irq;
295
296 /*
297 * Ignore the GSI from the core, and use the value in our copy of the
298 * FADT. It may not be the same if an interrupt source override exists
299 * for the SCI.
300 */
cee324b1 301 gsi = acpi_gbl_FADT.sci_interrupt;
1da177e4
LT
302 if (acpi_gsi_to_irq(gsi, &irq) < 0) {
303 printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n",
304 gsi);
305 return AE_OK;
306 }
307
308 acpi_irq_handler = handler;
309 acpi_irq_context = context;
dace1453 310 if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) {
1da177e4
LT
311 printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq);
312 return AE_NOT_ACQUIRED;
313 }
314 acpi_irq_irq = irq;
315
316 return AE_OK;
317}
318
4be44fcd 319acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
1da177e4
LT
320{
321 if (irq) {
322 free_irq(irq, acpi_irq);
323 acpi_irq_handler = NULL;
324 acpi_irq_irq = 0;
325 }
326
327 return AE_OK;
328}
329
330/*
331 * Running in interpreter thread context, safe to sleep
332 */
333
4be44fcd 334void acpi_os_sleep(acpi_integer ms)
1da177e4 335{
01a527ec 336 schedule_timeout_interruptible(msecs_to_jiffies(ms));
1da177e4 337}
4be44fcd 338
1da177e4
LT
339EXPORT_SYMBOL(acpi_os_sleep);
340
4be44fcd 341void acpi_os_stall(u32 us)
1da177e4
LT
342{
343 while (us) {
344 u32 delay = 1000;
345
346 if (delay > us)
347 delay = us;
348 udelay(delay);
349 touch_nmi_watchdog();
350 us -= delay;
351 }
352}
4be44fcd 353
1da177e4
LT
354EXPORT_SYMBOL(acpi_os_stall);
355
356/*
357 * Support ACPI 3.0 AML Timer operand
358 * Returns 64-bit free-running, monotonically increasing timer
359 * with 100ns granularity
360 */
4be44fcd 361u64 acpi_os_get_timer(void)
1da177e4
LT
362{
363 static u64 t;
364
365#ifdef CONFIG_HPET
366 /* TBD: use HPET if available */
367#endif
368
369#ifdef CONFIG_X86_PM_TIMER
370 /* TBD: default to PM timer if HPET was not available */
371#endif
372 if (!t)
373 printk(KERN_ERR PREFIX "acpi_os_get_timer() TBD\n");
374
375 return ++t;
376}
377
4be44fcd 378acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width)
1da177e4
LT
379{
380 u32 dummy;
381
382 if (!value)
383 value = &dummy;
384
49fbabf5
ZY
385 *value = 0;
386 if (width <= 8) {
4be44fcd 387 *(u8 *) value = inb(port);
49fbabf5 388 } else if (width <= 16) {
4be44fcd 389 *(u16 *) value = inw(port);
49fbabf5 390 } else if (width <= 32) {
4be44fcd 391 *(u32 *) value = inl(port);
49fbabf5 392 } else {
1da177e4
LT
393 BUG();
394 }
395
396 return AE_OK;
397}
4be44fcd 398
1da177e4
LT
399EXPORT_SYMBOL(acpi_os_read_port);
400
4be44fcd 401acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width)
1da177e4 402{
49fbabf5 403 if (width <= 8) {
1da177e4 404 outb(value, port);
49fbabf5 405 } else if (width <= 16) {
1da177e4 406 outw(value, port);
49fbabf5 407 } else if (width <= 32) {
1da177e4 408 outl(value, port);
49fbabf5 409 } else {
1da177e4
LT
410 BUG();
411 }
412
413 return AE_OK;
414}
4be44fcd 415
1da177e4
LT
416EXPORT_SYMBOL(acpi_os_write_port);
417
418acpi_status
4be44fcd 419acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
1da177e4 420{
4be44fcd
LB
421 u32 dummy;
422 void __iomem *virt_addr;
1da177e4 423
9f4fd61f 424 virt_addr = ioremap(phys_addr, width);
1da177e4
LT
425 if (!value)
426 value = &dummy;
427
428 switch (width) {
429 case 8:
4be44fcd 430 *(u8 *) value = readb(virt_addr);
1da177e4
LT
431 break;
432 case 16:
4be44fcd 433 *(u16 *) value = readw(virt_addr);
1da177e4
LT
434 break;
435 case 32:
4be44fcd 436 *(u32 *) value = readl(virt_addr);
1da177e4
LT
437 break;
438 default:
439 BUG();
440 }
441
9f4fd61f 442 iounmap(virt_addr);
1da177e4
LT
443
444 return AE_OK;
445}
446
447acpi_status
4be44fcd 448acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
1da177e4 449{
4be44fcd 450 void __iomem *virt_addr;
1da177e4 451
9f4fd61f 452 virt_addr = ioremap(phys_addr, width);
1da177e4
LT
453
454 switch (width) {
455 case 8:
456 writeb(value, virt_addr);
457 break;
458 case 16:
459 writew(value, virt_addr);
460 break;
461 case 32:
462 writel(value, virt_addr);
463 break;
464 default:
465 BUG();
466 }
467
9f4fd61f 468 iounmap(virt_addr);
1da177e4
LT
469
470 return AE_OK;
471}
472
1da177e4 473acpi_status
4be44fcd
LB
474acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
475 void *value, u32 width)
1da177e4
LT
476{
477 int result, size;
478
479 if (!value)
480 return AE_BAD_PARAMETER;
481
482 switch (width) {
483 case 8:
484 size = 1;
485 break;
486 case 16:
487 size = 2;
488 break;
489 case 32:
490 size = 4;
491 break;
492 default:
493 return AE_ERROR;
494 }
495
496 BUG_ON(!raw_pci_ops);
497
498 result = raw_pci_ops->read(pci_id->segment, pci_id->bus,
4be44fcd
LB
499 PCI_DEVFN(pci_id->device, pci_id->function),
500 reg, size, value);
1da177e4
LT
501
502 return (result ? AE_ERROR : AE_OK);
503}
4be44fcd 504
1da177e4
LT
505EXPORT_SYMBOL(acpi_os_read_pci_configuration);
506
507acpi_status
4be44fcd
LB
508acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
509 acpi_integer value, u32 width)
1da177e4
LT
510{
511 int result, size;
512
513 switch (width) {
514 case 8:
515 size = 1;
516 break;
517 case 16:
518 size = 2;
519 break;
520 case 32:
521 size = 4;
522 break;
523 default:
524 return AE_ERROR;
525 }
526
527 BUG_ON(!raw_pci_ops);
528
529 result = raw_pci_ops->write(pci_id->segment, pci_id->bus,
4be44fcd
LB
530 PCI_DEVFN(pci_id->device, pci_id->function),
531 reg, size, value);
1da177e4
LT
532
533 return (result ? AE_ERROR : AE_OK);
534}
535
536/* TODO: Change code to take advantage of driver model more */
4be44fcd
LB
537static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */
538 acpi_handle chandle, /* current node */
539 struct acpi_pci_id **id,
540 int *is_bridge, u8 * bus_number)
1da177e4 541{
4be44fcd
LB
542 acpi_handle handle;
543 struct acpi_pci_id *pci_id = *id;
544 acpi_status status;
545 unsigned long temp;
546 acpi_object_type type;
547 u8 tu8;
1da177e4
LT
548
549 acpi_get_parent(chandle, &handle);
550 if (handle != rhandle) {
4be44fcd
LB
551 acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge,
552 bus_number);
1da177e4
LT
553
554 status = acpi_get_type(handle, &type);
4be44fcd 555 if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE))
1da177e4
LT
556 return;
557
4be44fcd
LB
558 status =
559 acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
560 &temp);
1da177e4 561 if (ACPI_SUCCESS(status)) {
4be44fcd
LB
562 pci_id->device = ACPI_HIWORD(ACPI_LODWORD(temp));
563 pci_id->function = ACPI_LOWORD(ACPI_LODWORD(temp));
1da177e4
LT
564
565 if (*is_bridge)
566 pci_id->bus = *bus_number;
567
568 /* any nicer way to get bus number of bridge ? */
4be44fcd
LB
569 status =
570 acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8,
571 8);
572 if (ACPI_SUCCESS(status)
573 && ((tu8 & 0x7f) == 1 || (tu8 & 0x7f) == 2)) {
574 status =
575 acpi_os_read_pci_configuration(pci_id, 0x18,
576 &tu8, 8);
1da177e4
LT
577 if (!ACPI_SUCCESS(status)) {
578 /* Certainly broken... FIX ME */
579 return;
580 }
581 *is_bridge = 1;
582 pci_id->bus = tu8;
4be44fcd
LB
583 status =
584 acpi_os_read_pci_configuration(pci_id, 0x19,
585 &tu8, 8);
1da177e4
LT
586 if (ACPI_SUCCESS(status)) {
587 *bus_number = tu8;
588 }
589 } else
590 *is_bridge = 0;
591 }
592 }
593}
594
4be44fcd
LB
595void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */
596 acpi_handle chandle, /* current node */
597 struct acpi_pci_id **id)
1da177e4
LT
598{
599 int is_bridge = 1;
600 u8 bus_number = (*id)->bus;
601
602 acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number);
603}
604
65f27f38 605static void acpi_os_execute_deferred(struct work_struct *work)
88db5e14
AS
606{
607 struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
608 if (!dpc) {
609 printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
610 return;
611 }
612
613 dpc->function(dpc->context);
614 kfree(dpc);
615
616 /* Yield cpu to notify thread */
617 cond_resched();
618
619 return;
620}
621
622static void acpi_os_execute_notify(struct work_struct *work)
1da177e4 623{
65f27f38 624 struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
1da177e4 625
1da177e4 626 if (!dpc) {
6468463a 627 printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
d550d98d 628 return;
1da177e4
LT
629 }
630
631 dpc->function(dpc->context);
632
633 kfree(dpc);
634
d550d98d 635 return;
1da177e4
LT
636}
637
b8d35192
AS
638/*******************************************************************************
639 *
640 * FUNCTION: acpi_os_execute
641 *
642 * PARAMETERS: Type - Type of the callback
643 * Function - Function to be executed
644 * Context - Function parameters
645 *
646 * RETURN: Status
647 *
648 * DESCRIPTION: Depending on type, either queues function for deferred execution or
649 * immediately executes function on a separate thread.
650 *
651 ******************************************************************************/
652
653acpi_status acpi_os_execute(acpi_execute_type type,
4be44fcd 654 acpi_osd_exec_callback function, void *context)
1da177e4 655{
4be44fcd
LB
656 acpi_status status = AE_OK;
657 struct acpi_os_dpc *dpc;
72945b2b 658
72945b2b
LB
659 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
660 "Scheduling function [%p(%p)] for deferred execution.\n",
661 function, context));
1da177e4
LT
662
663 if (!function)
88db5e14 664 return AE_BAD_PARAMETER;
72945b2b 665
1da177e4
LT
666 /*
667 * Allocate/initialize DPC structure. Note that this memory will be
65f27f38 668 * freed by the callee. The kernel handles the work_struct list in a
1da177e4
LT
669 * way that allows us to also free its memory inside the callee.
670 * Because we may want to schedule several tasks with different
671 * parameters we can't use the approach some kernel code uses of
65f27f38 672 * having a static work_struct.
1da177e4 673 */
72945b2b 674
65f27f38 675 dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_ATOMIC);
1da177e4 676 if (!dpc)
b976fe19
LT
677 return_ACPI_STATUS(AE_NO_MEMORY);
678
1da177e4
LT
679 dpc->function = function;
680 dpc->context = context;
b976fe19 681
88db5e14
AS
682 if (type == OSL_NOTIFY_HANDLER) {
683 INIT_WORK(&dpc->work, acpi_os_execute_notify);
684 if (!queue_work(kacpi_notify_wq, &dpc->work)) {
685 status = AE_ERROR;
686 kfree(dpc);
687 }
688 } else {
689 INIT_WORK(&dpc->work, acpi_os_execute_deferred);
690 if (!queue_work(kacpid_wq, &dpc->work)) {
691 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
b976fe19 692 "Call to queue_work() failed.\n"));
88db5e14
AS
693 status = AE_ERROR;
694 kfree(dpc);
695 }
1da177e4 696 }
b976fe19 697 return_ACPI_STATUS(status);
1da177e4 698}
4be44fcd 699
b8d35192 700EXPORT_SYMBOL(acpi_os_execute);
1da177e4 701
4be44fcd 702void acpi_os_wait_events_complete(void *context)
1da177e4
LT
703{
704 flush_workqueue(kacpid_wq);
705}
4be44fcd 706
1da177e4
LT
707EXPORT_SYMBOL(acpi_os_wait_events_complete);
708
709/*
710 * Allocate the memory for a spinlock and initialize it.
711 */
967440e3 712acpi_status acpi_os_create_lock(acpi_spinlock * handle)
1da177e4 713{
967440e3 714 spin_lock_init(*handle);
1da177e4 715
d550d98d 716 return AE_OK;
1da177e4
LT
717}
718
1da177e4
LT
719/*
720 * Deallocate the memory for a spinlock.
721 */
967440e3 722void acpi_os_delete_lock(acpi_spinlock handle)
1da177e4 723{
d550d98d 724 return;
1da177e4
LT
725}
726
1da177e4 727acpi_status
4be44fcd 728acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
1da177e4 729{
4be44fcd 730 struct semaphore *sem = NULL;
1da177e4 731
1da177e4
LT
732
733 sem = acpi_os_allocate(sizeof(struct semaphore));
734 if (!sem)
d550d98d 735 return AE_NO_MEMORY;
1da177e4
LT
736 memset(sem, 0, sizeof(struct semaphore));
737
738 sema_init(sem, initial_units);
739
4be44fcd 740 *handle = (acpi_handle *) sem;
1da177e4 741
4be44fcd
LB
742 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Creating semaphore[%p|%d].\n",
743 *handle, initial_units));
1da177e4 744
d550d98d 745 return AE_OK;
1da177e4 746}
1da177e4 747
4be44fcd 748EXPORT_SYMBOL(acpi_os_create_semaphore);
1da177e4
LT
749
750/*
751 * TODO: A better way to delete semaphores? Linux doesn't have a
752 * 'delete_semaphore()' function -- may result in an invalid
753 * pointer dereference for non-synchronized consumers. Should
754 * we at least check for blocked threads and signal/cancel them?
755 */
756
4be44fcd 757acpi_status acpi_os_delete_semaphore(acpi_handle handle)
1da177e4 758{
4be44fcd 759 struct semaphore *sem = (struct semaphore *)handle;
1da177e4 760
1da177e4
LT
761
762 if (!sem)
d550d98d 763 return AE_BAD_PARAMETER;
1da177e4 764
4be44fcd 765 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle));
1da177e4 766
02438d87 767 kfree(sem);
4be44fcd 768 sem = NULL;
1da177e4 769
d550d98d 770 return AE_OK;
1da177e4 771}
1da177e4 772
4be44fcd 773EXPORT_SYMBOL(acpi_os_delete_semaphore);
1da177e4
LT
774
775/*
776 * TODO: The kernel doesn't have a 'down_timeout' function -- had to
777 * improvise. The process is to sleep for one scheduler quantum
778 * until the semaphore becomes available. Downside is that this
779 * may result in starvation for timeout-based waits when there's
780 * lots of semaphore activity.
781 *
782 * TODO: Support for units > 1?
783 */
4be44fcd 784acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
1da177e4 785{
4be44fcd
LB
786 acpi_status status = AE_OK;
787 struct semaphore *sem = (struct semaphore *)handle;
788 int ret = 0;
1da177e4 789
1da177e4
LT
790
791 if (!sem || (units < 1))
d550d98d 792 return AE_BAD_PARAMETER;
1da177e4
LT
793
794 if (units > 1)
d550d98d 795 return AE_SUPPORT;
1da177e4 796
4be44fcd
LB
797 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n",
798 handle, units, timeout));
1da177e4 799
d68909f4
LB
800 /*
801 * This can be called during resume with interrupts off.
802 * Like boot-time, we should be single threaded and will
803 * always get the lock if we try -- timeout or not.
804 * If this doesn't succeed, then we will oops courtesy of
805 * might_sleep() in down().
806 */
807 if (!down_trylock(sem))
808 return AE_OK;
809
4be44fcd 810 switch (timeout) {
1da177e4
LT
811 /*
812 * No Wait:
813 * --------
814 * A zero timeout value indicates that we shouldn't wait - just
815 * acquire the semaphore if available otherwise return AE_TIME
816 * (a.k.a. 'would block').
817 */
4be44fcd
LB
818 case 0:
819 if (down_trylock(sem))
1da177e4
LT
820 status = AE_TIME;
821 break;
822
823 /*
824 * Wait Indefinitely:
825 * ------------------
826 */
4be44fcd 827 case ACPI_WAIT_FOREVER:
1da177e4
LT
828 down(sem);
829 break;
830
831 /*
832 * Wait w/ Timeout:
833 * ----------------
834 */
4be44fcd 835 default:
1da177e4
LT
836 // TODO: A better timeout algorithm?
837 {
838 int i = 0;
4be44fcd 839 static const int quantum_ms = 1000 / HZ;
1da177e4
LT
840
841 ret = down_trylock(sem);
dacd9b80 842 for (i = timeout; (i > 0 && ret != 0); i -= quantum_ms) {
01a527ec 843 schedule_timeout_interruptible(1);
1da177e4
LT
844 ret = down_trylock(sem);
845 }
4be44fcd 846
1da177e4
LT
847 if (ret != 0)
848 status = AE_TIME;
849 }
850 break;
851 }
852
853 if (ACPI_FAILURE(status)) {
9e7e2c04 854 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
a6fc6720 855 "Failed to acquire semaphore[%p|%d|%d], %s",
4be44fcd
LB
856 handle, units, timeout,
857 acpi_format_exception(status)));
858 } else {
859 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
a6fc6720 860 "Acquired semaphore[%p|%d|%d]", handle,
4be44fcd 861 units, timeout));
1da177e4
LT
862 }
863
d550d98d 864 return status;
1da177e4 865}
1da177e4 866
4be44fcd 867EXPORT_SYMBOL(acpi_os_wait_semaphore);
1da177e4
LT
868
869/*
870 * TODO: Support for units > 1?
871 */
4be44fcd 872acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units)
1da177e4 873{
4be44fcd 874 struct semaphore *sem = (struct semaphore *)handle;
1da177e4 875
1da177e4
LT
876
877 if (!sem || (units < 1))
d550d98d 878 return AE_BAD_PARAMETER;
1da177e4
LT
879
880 if (units > 1)
d550d98d 881 return AE_SUPPORT;
1da177e4 882
4be44fcd
LB
883 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle,
884 units));
1da177e4
LT
885
886 up(sem);
887
d550d98d 888 return AE_OK;
1da177e4 889}
4be44fcd 890
1da177e4
LT
891EXPORT_SYMBOL(acpi_os_signal_semaphore);
892
893#ifdef ACPI_FUTURE_USAGE
4be44fcd 894u32 acpi_os_get_line(char *buffer)
1da177e4
LT
895{
896
897#ifdef ENABLE_DEBUGGER
898 if (acpi_in_debugger) {
899 u32 chars;
900
901 kdb_read(buffer, sizeof(line_buf));
902
903 /* remove the CR kdb includes */
904 chars = strlen(buffer) - 1;
905 buffer[chars] = '\0';
906 }
907#endif
908
909 return 0;
910}
4be44fcd 911#endif /* ACPI_FUTURE_USAGE */
1da177e4 912
4be44fcd 913acpi_status acpi_os_signal(u32 function, void *info)
1da177e4 914{
4be44fcd 915 switch (function) {
1da177e4
LT
916 case ACPI_SIGNAL_FATAL:
917 printk(KERN_ERR PREFIX "Fatal opcode executed\n");
918 break;
919 case ACPI_SIGNAL_BREAKPOINT:
920 /*
921 * AML Breakpoint
922 * ACPI spec. says to treat it as a NOP unless
923 * you are debugging. So if/when we integrate
924 * AML debugger into the kernel debugger its
925 * hook will go here. But until then it is
926 * not useful to print anything on breakpoints.
927 */
928 break;
929 default:
930 break;
931 }
932
933 return AE_OK;
934}
4be44fcd 935
1da177e4
LT
936EXPORT_SYMBOL(acpi_os_signal);
937
4be44fcd 938static int __init acpi_os_name_setup(char *str)
1da177e4
LT
939{
940 char *p = acpi_os_name;
4be44fcd 941 int count = ACPI_MAX_OVERRIDE_LEN - 1;
1da177e4
LT
942
943 if (!str || !*str)
944 return 0;
945
946 for (; count-- && str && *str; str++) {
947 if (isalnum(*str) || *str == ' ' || *str == ':')
948 *p++ = *str;
949 else if (*str == '\'' || *str == '"')
950 continue;
951 else
952 break;
953 }
954 *p = 0;
955
956 return 1;
4be44fcd 957
1da177e4
LT
958}
959
960__setup("acpi_os_name=", acpi_os_name_setup);
961
f507654d
LB
962static void enable_osi_linux(int enable) {
963
964 if (osi_linux != enable)
965 printk(KERN_INFO PREFIX "%sabled _OSI(Linux)\n",
966 enable ? "En": "Dis");
967
968 osi_linux = enable;
969 return;
970}
971
1da177e4 972/*
ae00d812
LB
973 * Modify the list of "OS Interfaces" reported to BIOS via _OSI
974 *
1da177e4 975 * empty string disables _OSI
ae00d812
LB
976 * string starting with '!' disables that string
977 * otherwise string is added to list, augmenting built-in strings
1da177e4 978 */
4be44fcd 979static int __init acpi_osi_setup(char *str)
1da177e4
LT
980{
981 if (str == NULL || *str == '\0') {
982 printk(KERN_INFO PREFIX "_OSI method disabled\n");
983 acpi_gbl_create_osi_method = FALSE;
aa2e09da
LB
984 } else if (!strcmp("!Linux", str)) {
985 enable_osi_linux(0);
ae00d812
LB
986 } else if (*str == '!') {
987 if (acpi_osi_invalidate(++str) == AE_OK)
988 printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
f507654d
LB
989 } else if (!strcmp("Linux", str)) {
990 enable_osi_linux(1);
ae00d812
LB
991 } else if (*osi_additional_string == '\0') {
992 strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX);
993 printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
1da177e4
LT
994 }
995
996 return 1;
997}
998
999__setup("acpi_osi=", acpi_osi_setup);
1000
1001/* enable serialization to combat AE_ALREADY_EXISTS errors */
4be44fcd 1002static int __init acpi_serialize_setup(char *str)
1da177e4
LT
1003{
1004 printk(KERN_INFO PREFIX "serialize enabled\n");
1005
1006 acpi_gbl_all_methods_serialized = TRUE;
1007
1008 return 1;
1009}
1010
1011__setup("acpi_serialize", acpi_serialize_setup);
1012
1013/*
1014 * Wake and Run-Time GPES are expected to be separate.
1015 * We disable wake-GPEs at run-time to prevent spurious
1016 * interrupts.
1017 *
1018 * However, if a system exists that shares Wake and
1019 * Run-time events on the same GPE this flag is available
1020 * to tell Linux to keep the wake-time GPEs enabled at run-time.
1021 */
4be44fcd 1022static int __init acpi_wake_gpes_always_on_setup(char *str)
1da177e4
LT
1023{
1024 printk(KERN_INFO PREFIX "wake GPEs not disabled\n");
1025
1026 acpi_gbl_leave_wake_gpes_disabled = FALSE;
1027
1028 return 1;
1029}
1030
1031__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
1032
73459f73
RM
1033/*
1034 * Acquire a spinlock.
1035 *
1036 * handle is a pointer to the spinlock_t.
73459f73
RM
1037 */
1038
967440e3 1039acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp)
73459f73 1040{
b8e4d893 1041 acpi_cpu_flags flags;
967440e3 1042 spin_lock_irqsave(lockp, flags);
73459f73
RM
1043 return flags;
1044}
1045
1046/*
1047 * Release a spinlock. See above.
1048 */
1049
967440e3 1050void acpi_os_release_lock(acpi_spinlock lockp, acpi_cpu_flags flags)
73459f73 1051{
967440e3 1052 spin_unlock_irqrestore(lockp, flags);
73459f73
RM
1053}
1054
73459f73
RM
1055#ifndef ACPI_USE_LOCAL_CACHE
1056
1057/*******************************************************************************
1058 *
1059 * FUNCTION: acpi_os_create_cache
1060 *
b229cf92
BM
1061 * PARAMETERS: name - Ascii name for the cache
1062 * size - Size of each cached object
1063 * depth - Maximum depth of the cache (in objects) <ignored>
1064 * cache - Where the new cache object is returned
73459f73 1065 *
b229cf92 1066 * RETURN: status
73459f73
RM
1067 *
1068 * DESCRIPTION: Create a cache object
1069 *
1070 ******************************************************************************/
1071
1072acpi_status
4be44fcd 1073acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache)
73459f73 1074{
20c2df83 1075 *cache = kmem_cache_create(name, size, 0, 0, NULL);
a6fdbf90 1076 if (*cache == NULL)
b229cf92
BM
1077 return AE_ERROR;
1078 else
1079 return AE_OK;
73459f73
RM
1080}
1081
1082/*******************************************************************************
1083 *
1084 * FUNCTION: acpi_os_purge_cache
1085 *
1086 * PARAMETERS: Cache - Handle to cache object
1087 *
1088 * RETURN: Status
1089 *
1090 * DESCRIPTION: Free all objects within the requested cache.
1091 *
1092 ******************************************************************************/
1093
4be44fcd 1094acpi_status acpi_os_purge_cache(acpi_cache_t * cache)
73459f73 1095{
50dd0969 1096 kmem_cache_shrink(cache);
4be44fcd 1097 return (AE_OK);
73459f73
RM
1098}
1099
1100/*******************************************************************************
1101 *
1102 * FUNCTION: acpi_os_delete_cache
1103 *
1104 * PARAMETERS: Cache - Handle to cache object
1105 *
1106 * RETURN: Status
1107 *
1108 * DESCRIPTION: Free all objects within the requested cache and delete the
1109 * cache object.
1110 *
1111 ******************************************************************************/
1112
4be44fcd 1113acpi_status acpi_os_delete_cache(acpi_cache_t * cache)
73459f73 1114{
1a1d92c1 1115 kmem_cache_destroy(cache);
4be44fcd 1116 return (AE_OK);
73459f73
RM
1117}
1118
1119/*******************************************************************************
1120 *
1121 * FUNCTION: acpi_os_release_object
1122 *
1123 * PARAMETERS: Cache - Handle to cache object
1124 * Object - The object to be released
1125 *
1126 * RETURN: None
1127 *
1128 * DESCRIPTION: Release an object to the specified cache. If cache is full,
1129 * the object is deleted.
1130 *
1131 ******************************************************************************/
1132
4be44fcd 1133acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
73459f73 1134{
4be44fcd
LB
1135 kmem_cache_free(cache, object);
1136 return (AE_OK);
73459f73
RM
1137}
1138
5a4e1432
LB
1139/**
1140 * acpi_dmi_dump - dump DMI slots needed for blacklist entry
1141 *
1142 * Returns 0 on success
1143 */
1144int acpi_dmi_dump(void)
1145{
1146
1147 if (!dmi_available)
1148 return -1;
1149
1150 printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n",
1151 dmi_get_slot(DMI_SYS_VENDOR));
1152 printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n",
1153 dmi_get_slot(DMI_PRODUCT_NAME));
1154 printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n",
1155 dmi_get_slot(DMI_PRODUCT_VERSION));
1156 printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n",
1157 dmi_get_slot(DMI_BOARD_NAME));
1158 printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n",
1159 dmi_get_slot(DMI_BIOS_VENDOR));
1160 printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n",
1161 dmi_get_slot(DMI_BIOS_DATE));
1162
1163 return 0;
1164}
1165
1166
b229cf92
BM
1167/******************************************************************************
1168 *
1169 * FUNCTION: acpi_os_validate_interface
1170 *
1171 * PARAMETERS: interface - Requested interface to be validated
1172 *
1173 * RETURN: AE_OK if interface is supported, AE_SUPPORT otherwise
1174 *
1175 * DESCRIPTION: Match an interface string to the interfaces supported by the
1176 * host. Strings originate from an AML call to the _OSI method.
1177 *
1178 *****************************************************************************/
1179
1180acpi_status
1181acpi_os_validate_interface (char *interface)
1182{
ae00d812
LB
1183 if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX))
1184 return AE_OK;
f507654d
LB
1185 if (!strcmp("Linux", interface)) {
1186 printk(KERN_WARNING PREFIX
1187 "System BIOS is requesting _OSI(Linux)\n");
f40cd6fd
LB
1188 if (acpi_dmi_dump())
1189 printk(KERN_NOTICE PREFIX
1190 "[please extract dmidecode output]\n");
1191 printk(KERN_NOTICE PREFIX
1192 "Please send DMI info above to "
1193 "linux-acpi@vger.kernel.org\n");
1194 printk(KERN_NOTICE PREFIX
1195 "If \"acpi_osi=%sLinux\" works better, "
1196 "please notify linux-acpi@vger.kernel.org\n",
1197 osi_linux ? "!" : "");
f507654d
LB
1198 if(osi_linux)
1199 return AE_OK;
1200 }
ae00d812 1201 return AE_SUPPORT;
b229cf92
BM
1202}
1203
b229cf92
BM
1204/******************************************************************************
1205 *
1206 * FUNCTION: acpi_os_validate_address
1207 *
1208 * PARAMETERS: space_id - ACPI space ID
1209 * address - Physical address
1210 * length - Address length
1211 *
1212 * RETURN: AE_OK if address/length is valid for the space_id. Otherwise,
1213 * should return AE_AML_ILLEGAL_ADDRESS.
1214 *
1215 * DESCRIPTION: Validate a system address via the host OS. Used to validate
1216 * the addresses accessed by AML operation regions.
1217 *
1218 *****************************************************************************/
1219
1220acpi_status
1221acpi_os_validate_address (
1222 u8 space_id,
1223 acpi_physical_address address,
1224 acpi_size length)
1225{
1226
1227 return AE_OK;
1228}
1229
73459f73 1230#endif