blob: 2a400e08e74ceda77489d92b180a12815e888546 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/interrupt.h>
34#include <linux/kmod.h>
35#include <linux/delay.h>
Len Brownf5076542007-05-30 00:10:38 -040036#include <linux/dmi.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/workqueue.h>
38#include <linux/nmi.h>
Alexey Starikovskiyad71860a2007-02-02 19:48:19 +030039#include <linux/acpi.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <acpi/acpi.h>
41#include <asm/io.h>
42#include <acpi/acpi_bus.h>
43#include <acpi/processor.h>
44#include <asm/uaccess.h>
45
46#include <linux/efi.h>
47
Linus Torvalds1da177e2005-04-16 15:20:36 -070048#define _COMPONENT ACPI_OS_SERVICES
Len Brownf52fd662007-02-12 22:42:12 -050049ACPI_MODULE_NAME("osl");
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#define PREFIX "ACPI: "
Len Brown4be44fc2005-08-05 00:44:28 -040051struct acpi_os_dpc {
52 acpi_osd_exec_callback function;
53 void *context;
David Howells65f27f32006-11-22 14:55:48 +000054 struct work_struct work;
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
71static unsigned int acpi_irq_irq;
72static acpi_osd_handler acpi_irq_handler;
73static void *acpi_irq_context;
74static struct workqueue_struct *kacpid_wq;
Alexey Starikovskiy88db5e12007-05-09 23:31:03 -040075static struct workqueue_struct *kacpi_notify_wq;
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
Len Brownae00d812007-05-29 18:43:33 -040077#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */
78static char osi_additional_string[OSI_STRING_LENGTH_MAX];
79
Éric Piel9cbc7962008-02-05 00:04:58 +010080#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
81static int acpi_no_initrd_override;
82#endif
83
Len Brownd4b7dc42008-01-23 20:50:56 -050084/*
85 * "Ode to _OSI(Linux)"
86 *
87 * osi_linux -- Control response to BIOS _OSI(Linux) query.
88 *
89 * As Linux evolves, the features that it supports change.
90 * So an OSI string such as "Linux" is not specific enough
91 * to be useful across multiple versions of Linux. It
92 * doesn't identify any particular feature, interface,
93 * or even any particular version of Linux...
94 *
95 * Unfortunately, Linux-2.6.22 and earlier responded "yes"
96 * to a BIOS _OSI(Linux) query. When
97 * a reference mobile BIOS started using it, its use
98 * started to spread to many vendor platforms.
99 * As it is not supportable, we need to halt that spread.
100 *
101 * Today, most BIOS references to _OSI(Linux) are noise --
102 * they have no functional effect and are just dead code
103 * carried over from the reference BIOS.
104 *
105 * The next most common case is that _OSI(Linux) harms Linux,
106 * usually by causing the BIOS to follow paths that are
107 * not tested during Windows validation.
108 *
109 * Finally, there is a short list of platforms
110 * where OSI(Linux) benefits Linux.
111 *
112 * In Linux-2.6.23, OSI(Linux) is first disabled by default.
113 * DMI is used to disable the dmesg warning about OSI(Linux)
114 * on platforms where it is known to have no effect.
115 * But a dmesg warning remains for systems where
116 * we do not know if OSI(Linux) is good or bad for the system.
117 * DMI is also used to enable OSI(Linux) for the machines
118 * that are known to need it.
119 *
120 * BIOS writers should NOT query _OSI(Linux) on future systems.
121 * It will be ignored by default, and to get Linux to
122 * not ignore it will require a kernel source update to
123 * add a DMI entry, or a boot-time "acpi_osi=Linux" invocation.
124 */
125#define OSI_LINUX_ENABLE 0
126
127struct osi_linux {
128 unsigned int enable:1;
129 unsigned int dmi:1;
130 unsigned int cmdline:1;
131 unsigned int known:1;
132} osi_linux = { OSI_LINUX_ENABLE, 0, 0, 0};
Len Brownf5076542007-05-30 00:10:38 -0400133
Bjorn Helgaas9a47cdb2007-01-18 16:42:55 -0700134static void __init acpi_request_region (struct acpi_generic_address *addr,
135 unsigned int length, char *desc)
136{
137 struct resource *res;
138
139 if (!addr->address || !length)
140 return;
141
Len Browneee3c852007-02-03 01:38:16 -0500142 if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_IO)
Bjorn Helgaas9a47cdb2007-01-18 16:42:55 -0700143 res = request_region(addr->address, length, desc);
Len Browneee3c852007-02-03 01:38:16 -0500144 else if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
Bjorn Helgaas9a47cdb2007-01-18 16:42:55 -0700145 res = request_mem_region(addr->address, length, desc);
146}
147
148static int __init acpi_reserve_resources(void)
149{
Len Browneee3c852007-02-03 01:38:16 -0500150 acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length,
Bjorn Helgaas9a47cdb2007-01-18 16:42:55 -0700151 "ACPI PM1a_EVT_BLK");
152
Len Browneee3c852007-02-03 01:38:16 -0500153 acpi_request_region(&acpi_gbl_FADT.xpm1b_event_block, acpi_gbl_FADT.pm1_event_length,
Bjorn Helgaas9a47cdb2007-01-18 16:42:55 -0700154 "ACPI PM1b_EVT_BLK");
155
Len Browneee3c852007-02-03 01:38:16 -0500156 acpi_request_region(&acpi_gbl_FADT.xpm1a_control_block, acpi_gbl_FADT.pm1_control_length,
Bjorn Helgaas9a47cdb2007-01-18 16:42:55 -0700157 "ACPI PM1a_CNT_BLK");
158
Len Browneee3c852007-02-03 01:38:16 -0500159 acpi_request_region(&acpi_gbl_FADT.xpm1b_control_block, acpi_gbl_FADT.pm1_control_length,
Bjorn Helgaas9a47cdb2007-01-18 16:42:55 -0700160 "ACPI PM1b_CNT_BLK");
161
Len Browneee3c852007-02-03 01:38:16 -0500162 if (acpi_gbl_FADT.pm_timer_length == 4)
163 acpi_request_region(&acpi_gbl_FADT.xpm_timer_block, 4, "ACPI PM_TMR");
Bjorn Helgaas9a47cdb2007-01-18 16:42:55 -0700164
Len Browneee3c852007-02-03 01:38:16 -0500165 acpi_request_region(&acpi_gbl_FADT.xpm2_control_block, acpi_gbl_FADT.pm2_control_length,
Bjorn Helgaas9a47cdb2007-01-18 16:42:55 -0700166 "ACPI PM2_CNT_BLK");
167
168 /* Length of GPE blocks must be a non-negative multiple of 2 */
169
Len Browneee3c852007-02-03 01:38:16 -0500170 if (!(acpi_gbl_FADT.gpe0_block_length & 0x1))
171 acpi_request_region(&acpi_gbl_FADT.xgpe0_block,
172 acpi_gbl_FADT.gpe0_block_length, "ACPI GPE0_BLK");
Bjorn Helgaas9a47cdb2007-01-18 16:42:55 -0700173
Len Browneee3c852007-02-03 01:38:16 -0500174 if (!(acpi_gbl_FADT.gpe1_block_length & 0x1))
175 acpi_request_region(&acpi_gbl_FADT.xgpe1_block,
176 acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK");
Bjorn Helgaas9a47cdb2007-01-18 16:42:55 -0700177
178 return 0;
179}
180device_initcall(acpi_reserve_resources);
181
Len Browndd272b52007-05-30 00:26:11 -0400182acpi_status __init acpi_os_initialize(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183{
184 return AE_OK;
185}
186
Len Brown4be44fc2005-08-05 00:44:28 -0400187acpi_status acpi_os_initialize1(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188{
189 /*
190 * Initialize PCI configuration space access, as we'll need to access
191 * it while walking the namespace (bus 0 and root bridges w/ _BBNs).
192 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 if (!raw_pci_ops) {
Len Brown4be44fc2005-08-05 00:44:28 -0400194 printk(KERN_ERR PREFIX
195 "Access to PCI configuration space unavailable\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 return AE_NULL_ENTRY;
197 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 kacpid_wq = create_singlethread_workqueue("kacpid");
Alexey Starikovskiy88db5e12007-05-09 23:31:03 -0400199 kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 BUG_ON(!kacpid_wq);
Alexey Starikovskiy88db5e12007-05-09 23:31:03 -0400201 BUG_ON(!kacpi_notify_wq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 return AE_OK;
203}
204
Len Brown4be44fc2005-08-05 00:44:28 -0400205acpi_status acpi_os_terminate(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206{
207 if (acpi_irq_handler) {
208 acpi_os_remove_interrupt_handler(acpi_irq_irq,
209 acpi_irq_handler);
210 }
211
212 destroy_workqueue(kacpid_wq);
Alexey Starikovskiy88db5e12007-05-09 23:31:03 -0400213 destroy_workqueue(kacpi_notify_wq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214
215 return AE_OK;
216}
217
Len Brown4be44fc2005-08-05 00:44:28 -0400218void acpi_os_printf(const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219{
220 va_list args;
221 va_start(args, fmt);
222 acpi_os_vprintf(fmt, args);
223 va_end(args);
224}
Len Brown4be44fc2005-08-05 00:44:28 -0400225
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226EXPORT_SYMBOL(acpi_os_printf);
227
Len Brown4be44fc2005-08-05 00:44:28 -0400228void acpi_os_vprintf(const char *fmt, va_list args)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229{
230 static char buffer[512];
Len Brown4be44fc2005-08-05 00:44:28 -0400231
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 vsprintf(buffer, fmt, args);
233
234#ifdef ENABLE_DEBUGGER
235 if (acpi_in_debugger) {
236 kdb_printf("%s", buffer);
237 } else {
238 printk("%s", buffer);
239 }
240#else
241 printk("%s", buffer);
242#endif
243}
244
Alexey Starikovskiyad71860a2007-02-02 19:48:19 +0300245acpi_physical_address __init acpi_os_get_root_pointer(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246{
247 if (efi_enabled) {
Bjorn Helgaasb2c99e32006-03-26 01:37:08 -0800248 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
Alexey Starikovskiyad71860a2007-02-02 19:48:19 +0300249 return efi.acpi20;
Bjorn Helgaasb2c99e32006-03-26 01:37:08 -0800250 else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
Alexey Starikovskiyad71860a2007-02-02 19:48:19 +0300251 return efi.acpi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 else {
Len Brown4be44fc2005-08-05 00:44:28 -0400253 printk(KERN_ERR PREFIX
254 "System description tables not found\n");
Alexey Starikovskiyad71860a2007-02-02 19:48:19 +0300255 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 }
Alexey Starikovskiyad71860a2007-02-02 19:48:19 +0300257 } else
258 return acpi_find_rsdp();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259}
260
Alexey Starikovskiyad71860a2007-02-02 19:48:19 +0300261void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262{
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800263 if (phys > ULONG_MAX) {
264 printk(KERN_ERR PREFIX "Cannot map memory that high\n");
Randy Dunlap70c08462007-02-13 16:11:36 -0800265 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 }
Alexey Starikovskiyad71860a2007-02-02 19:48:19 +0300267 if (acpi_gbl_permanent_mmap)
268 /*
269 * ioremap checks to ensure this is in reserved space
270 */
271 return ioremap((unsigned long)phys, size);
272 else
273 return __acpi_map_table((unsigned long)phys, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274}
Kylene Jo Hall55a82ab2006-01-08 01:03:15 -0800275EXPORT_SYMBOL_GPL(acpi_os_map_memory);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276
Len Brown4be44fc2005-08-05 00:44:28 -0400277void acpi_os_unmap_memory(void __iomem * virt, acpi_size size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278{
Alexey Starikovskiyad71860a2007-02-02 19:48:19 +0300279 if (acpi_gbl_permanent_mmap) {
280 iounmap(virt);
281 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282}
Kylene Jo Hall55a82ab2006-01-08 01:03:15 -0800283EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
285#ifdef ACPI_FUTURE_USAGE
286acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400287acpi_os_get_physical_address(void *virt, acpi_physical_address * phys)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288{
Len Brown4be44fc2005-08-05 00:44:28 -0400289 if (!phys || !virt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 return AE_BAD_PARAMETER;
291
292 *phys = virt_to_phys(virt);
293
294 return AE_OK;
295}
296#endif
297
298#define ACPI_MAX_OVERRIDE_LEN 100
299
300static char acpi_os_name[ACPI_MAX_OVERRIDE_LEN];
301
302acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400303acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
304 acpi_string * new_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305{
306 if (!init_val || !new_val)
307 return AE_BAD_PARAMETER;
308
309 *new_val = NULL;
Len Brown4be44fc2005-08-05 00:44:28 -0400310 if (!memcmp(init_val->name, "_OS_", 4) && strlen(acpi_os_name)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 printk(KERN_INFO PREFIX "Overriding _OS definition to '%s'\n",
Len Brown4be44fc2005-08-05 00:44:28 -0400312 acpi_os_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 *new_val = acpi_os_name;
314 }
315
316 return AE_OK;
317}
318
Markus Gaugusch71fc47a2008-02-05 00:04:06 +0100319#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
320struct acpi_table_header *acpi_find_dsdt_initrd(void)
321{
322 struct file *firmware_file;
323 mm_segment_t oldfs;
324 unsigned long len, len2;
325 struct acpi_table_header *dsdt_buffer, *ret = NULL;
326 struct kstat stat;
327 char *ramfs_dsdt_name = "/DSDT.aml";
328
Len Brown04d94882008-02-06 19:49:54 -0500329 printk(KERN_INFO PREFIX "Checking initramfs for custom DSDT");
Markus Gaugusch71fc47a2008-02-05 00:04:06 +0100330
331 /*
332 * Never do this at home, only the user-space is allowed to open a file.
Len Brown04d94882008-02-06 19:49:54 -0500333 * The clean way would be to use the firmware loader.
334 * But this code must be run before there is any userspace available.
335 * A static/init firmware infrastructure doesn't exist yet...
Markus Gaugusch71fc47a2008-02-05 00:04:06 +0100336 */
Len Brown04d94882008-02-06 19:49:54 -0500337 if (vfs_stat(ramfs_dsdt_name, &stat) < 0)
Markus Gaugusch71fc47a2008-02-05 00:04:06 +0100338 return ret;
Markus Gaugusch71fc47a2008-02-05 00:04:06 +0100339
340 len = stat.size;
341 /* check especially against empty files */
342 if (len <= 4) {
Len Brown04d94882008-02-06 19:49:54 -0500343 printk(KERN_ERR PREFIX "Failed: DSDT only %lu bytes.\n", len);
Markus Gaugusch71fc47a2008-02-05 00:04:06 +0100344 return ret;
345 }
346
347 firmware_file = filp_open(ramfs_dsdt_name, O_RDONLY, 0);
348 if (IS_ERR(firmware_file)) {
Len Brown04d94882008-02-06 19:49:54 -0500349 printk(KERN_ERR PREFIX "Failed to open %s.\n", ramfs_dsdt_name);
Markus Gaugusch71fc47a2008-02-05 00:04:06 +0100350 return ret;
351 }
352
Len Brown04d94882008-02-06 19:49:54 -0500353 dsdt_buffer = kmalloc(len, GFP_ATOMIC);
Markus Gaugusch71fc47a2008-02-05 00:04:06 +0100354 if (!dsdt_buffer) {
Len Brown04d94882008-02-06 19:49:54 -0500355 printk(KERN_ERR PREFIX "Failed to allocate %lu bytes.\n", len);
Markus Gaugusch71fc47a2008-02-05 00:04:06 +0100356 goto err;
357 }
358
359 oldfs = get_fs();
360 set_fs(KERNEL_DS);
Len Brown04d94882008-02-06 19:49:54 -0500361 len2 = vfs_read(firmware_file, (char __user *)dsdt_buffer, len,
362 &firmware_file->f_pos);
Markus Gaugusch71fc47a2008-02-05 00:04:06 +0100363 set_fs(oldfs);
364 if (len2 < len) {
Len Brown04d94882008-02-06 19:49:54 -0500365 printk(KERN_ERR PREFIX "Failed to read %lu bytes from %s.\n",
366 len, ramfs_dsdt_name);
Markus Gaugusch71fc47a2008-02-05 00:04:06 +0100367 ACPI_FREE(dsdt_buffer);
368 goto err;
369 }
370
Len Brown04d94882008-02-06 19:49:54 -0500371 printk(KERN_INFO PREFIX "Found %lu byte DSDT in %s.\n",
372 len, ramfs_dsdt_name);
Markus Gaugusch71fc47a2008-02-05 00:04:06 +0100373 ret = dsdt_buffer;
374err:
375 filp_close(firmware_file, NULL);
376 return ret;
377}
378#endif
379
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400381acpi_os_table_override(struct acpi_table_header * existing_table,
382 struct acpi_table_header ** new_table)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383{
384 if (!existing_table || !new_table)
385 return AE_BAD_PARAMETER;
386
Markus Gaugusch71fc47a2008-02-05 00:04:06 +0100387 *new_table = NULL;
388
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389#ifdef CONFIG_ACPI_CUSTOM_DSDT
390 if (strncmp(existing_table->signature, "DSDT", 4) == 0)
Len Brown4be44fc2005-08-05 00:44:28 -0400391 *new_table = (struct acpi_table_header *)AmlCode;
Markus Gaugusch71fc47a2008-02-05 00:04:06 +0100392#endif
393#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
Éric Piel9cbc7962008-02-05 00:04:58 +0100394 if ((strncmp(existing_table->signature, "DSDT", 4) == 0) &&
395 !acpi_no_initrd_override) {
Len Brown04d94882008-02-06 19:49:54 -0500396 struct acpi_table_header *initrd_table;
397
398 initrd_table = acpi_find_dsdt_initrd();
Markus Gaugusch71fc47a2008-02-05 00:04:06 +0100399 if (initrd_table)
400 *new_table = initrd_table;
401 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402#endif
Éric Piel6ed31e92008-02-05 00:04:50 +0100403 if (*new_table != NULL) {
404 printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], "
405 "this is unsafe: tainting kernel\n",
406 existing_table->signature,
407 existing_table->oem_table_id);
408 add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
409 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 return AE_OK;
411}
412
Éric Piel9cbc7962008-02-05 00:04:58 +0100413#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
414int __init acpi_no_initrd_override_setup(char *s)
415{
416 acpi_no_initrd_override = 1;
417 return 1;
418}
419__setup("acpi_no_initrd_override", acpi_no_initrd_override_setup);
420#endif
421
David Howells7d12e782006-10-05 14:55:46 +0100422static irqreturn_t acpi_irq(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423{
Len Brown4be44fc2005-08-05 00:44:28 -0400424 return (*acpi_irq_handler) (acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425}
426
427acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400428acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
429 void *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430{
431 unsigned int irq;
432
433 /*
434 * Ignore the GSI from the core, and use the value in our copy of the
435 * FADT. It may not be the same if an interrupt source override exists
436 * for the SCI.
437 */
Alexey Starikovskiycee324b2007-02-02 19:48:22 +0300438 gsi = acpi_gbl_FADT.sci_interrupt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 if (acpi_gsi_to_irq(gsi, &irq) < 0) {
440 printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n",
441 gsi);
442 return AE_OK;
443 }
444
445 acpi_irq_handler = handler;
446 acpi_irq_context = context;
Thomas Gleixnerdace1452006-07-01 19:29:38 -0700447 if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq);
449 return AE_NOT_ACQUIRED;
450 }
451 acpi_irq_irq = irq;
452
453 return AE_OK;
454}
455
Len Brown4be44fc2005-08-05 00:44:28 -0400456acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457{
458 if (irq) {
459 free_irq(irq, acpi_irq);
460 acpi_irq_handler = NULL;
461 acpi_irq_irq = 0;
462 }
463
464 return AE_OK;
465}
466
467/*
468 * Running in interpreter thread context, safe to sleep
469 */
470
Len Brown4be44fc2005-08-05 00:44:28 -0400471void acpi_os_sleep(acpi_integer ms)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472{
Nishanth Aravamudan01a527e2005-11-07 01:01:14 -0800473 schedule_timeout_interruptible(msecs_to_jiffies(ms));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474}
Len Brown4be44fc2005-08-05 00:44:28 -0400475
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476EXPORT_SYMBOL(acpi_os_sleep);
477
Len Brown4be44fc2005-08-05 00:44:28 -0400478void acpi_os_stall(u32 us)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479{
480 while (us) {
481 u32 delay = 1000;
482
483 if (delay > us)
484 delay = us;
485 udelay(delay);
486 touch_nmi_watchdog();
487 us -= delay;
488 }
489}
Len Brown4be44fc2005-08-05 00:44:28 -0400490
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491EXPORT_SYMBOL(acpi_os_stall);
492
493/*
494 * Support ACPI 3.0 AML Timer operand
495 * Returns 64-bit free-running, monotonically increasing timer
496 * with 100ns granularity
497 */
Len Brown4be44fc2005-08-05 00:44:28 -0400498u64 acpi_os_get_timer(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499{
500 static u64 t;
501
502#ifdef CONFIG_HPET
503 /* TBD: use HPET if available */
504#endif
505
506#ifdef CONFIG_X86_PM_TIMER
507 /* TBD: default to PM timer if HPET was not available */
508#endif
509 if (!t)
510 printk(KERN_ERR PREFIX "acpi_os_get_timer() TBD\n");
511
512 return ++t;
513}
514
Len Brown4be44fc2005-08-05 00:44:28 -0400515acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516{
517 u32 dummy;
518
519 if (!value)
520 value = &dummy;
521
Zhao Yakui49fbabf2007-11-15 17:01:06 +0800522 *value = 0;
523 if (width <= 8) {
Len Brown4be44fc2005-08-05 00:44:28 -0400524 *(u8 *) value = inb(port);
Zhao Yakui49fbabf2007-11-15 17:01:06 +0800525 } else if (width <= 16) {
Len Brown4be44fc2005-08-05 00:44:28 -0400526 *(u16 *) value = inw(port);
Zhao Yakui49fbabf2007-11-15 17:01:06 +0800527 } else if (width <= 32) {
Len Brown4be44fc2005-08-05 00:44:28 -0400528 *(u32 *) value = inl(port);
Zhao Yakui49fbabf2007-11-15 17:01:06 +0800529 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 BUG();
531 }
532
533 return AE_OK;
534}
Len Brown4be44fc2005-08-05 00:44:28 -0400535
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536EXPORT_SYMBOL(acpi_os_read_port);
537
Len Brown4be44fc2005-08-05 00:44:28 -0400538acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539{
Zhao Yakui49fbabf2007-11-15 17:01:06 +0800540 if (width <= 8) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 outb(value, port);
Zhao Yakui49fbabf2007-11-15 17:01:06 +0800542 } else if (width <= 16) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 outw(value, port);
Zhao Yakui49fbabf2007-11-15 17:01:06 +0800544 } else if (width <= 32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 outl(value, port);
Zhao Yakui49fbabf2007-11-15 17:01:06 +0800546 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 BUG();
548 }
549
550 return AE_OK;
551}
Len Brown4be44fc2005-08-05 00:44:28 -0400552
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553EXPORT_SYMBOL(acpi_os_write_port);
554
555acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400556acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557{
Len Brown4be44fc2005-08-05 00:44:28 -0400558 u32 dummy;
559 void __iomem *virt_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800561 virt_addr = ioremap(phys_addr, width);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 if (!value)
563 value = &dummy;
564
565 switch (width) {
566 case 8:
Len Brown4be44fc2005-08-05 00:44:28 -0400567 *(u8 *) value = readb(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 break;
569 case 16:
Len Brown4be44fc2005-08-05 00:44:28 -0400570 *(u16 *) value = readw(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 break;
572 case 32:
Len Brown4be44fc2005-08-05 00:44:28 -0400573 *(u32 *) value = readl(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 break;
575 default:
576 BUG();
577 }
578
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800579 iounmap(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580
581 return AE_OK;
582}
583
584acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400585acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586{
Len Brown4be44fc2005-08-05 00:44:28 -0400587 void __iomem *virt_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800589 virt_addr = ioremap(phys_addr, width);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590
591 switch (width) {
592 case 8:
593 writeb(value, virt_addr);
594 break;
595 case 16:
596 writew(value, virt_addr);
597 break;
598 case 32:
599 writel(value, virt_addr);
600 break;
601 default:
602 BUG();
603 }
604
Bjorn Helgaas9f4fd612006-03-26 01:37:10 -0800605 iounmap(virt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606
607 return AE_OK;
608}
609
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400611acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
612 void *value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613{
614 int result, size;
615
616 if (!value)
617 return AE_BAD_PARAMETER;
618
619 switch (width) {
620 case 8:
621 size = 1;
622 break;
623 case 16:
624 size = 2;
625 break;
626 case 32:
627 size = 4;
628 break;
629 default:
630 return AE_ERROR;
631 }
632
633 BUG_ON(!raw_pci_ops);
634
635 result = raw_pci_ops->read(pci_id->segment, pci_id->bus,
Len Brown4be44fc2005-08-05 00:44:28 -0400636 PCI_DEVFN(pci_id->device, pci_id->function),
637 reg, size, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638
639 return (result ? AE_ERROR : AE_OK);
640}
Len Brown4be44fc2005-08-05 00:44:28 -0400641
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642EXPORT_SYMBOL(acpi_os_read_pci_configuration);
643
644acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400645acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
646 acpi_integer value, u32 width)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647{
648 int result, size;
649
650 switch (width) {
651 case 8:
652 size = 1;
653 break;
654 case 16:
655 size = 2;
656 break;
657 case 32:
658 size = 4;
659 break;
660 default:
661 return AE_ERROR;
662 }
663
664 BUG_ON(!raw_pci_ops);
665
666 result = raw_pci_ops->write(pci_id->segment, pci_id->bus,
Len Brown4be44fc2005-08-05 00:44:28 -0400667 PCI_DEVFN(pci_id->device, pci_id->function),
668 reg, size, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669
670 return (result ? AE_ERROR : AE_OK);
671}
672
673/* TODO: Change code to take advantage of driver model more */
Len Brown4be44fc2005-08-05 00:44:28 -0400674static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */
675 acpi_handle chandle, /* current node */
676 struct acpi_pci_id **id,
677 int *is_bridge, u8 * bus_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678{
Len Brown4be44fc2005-08-05 00:44:28 -0400679 acpi_handle handle;
680 struct acpi_pci_id *pci_id = *id;
681 acpi_status status;
682 unsigned long temp;
683 acpi_object_type type;
684 u8 tu8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685
686 acpi_get_parent(chandle, &handle);
687 if (handle != rhandle) {
Len Brown4be44fc2005-08-05 00:44:28 -0400688 acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge,
689 bus_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690
691 status = acpi_get_type(handle, &type);
Len Brown4be44fc2005-08-05 00:44:28 -0400692 if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 return;
694
Len Brown4be44fc2005-08-05 00:44:28 -0400695 status =
696 acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
697 &temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 if (ACPI_SUCCESS(status)) {
Len Brown4be44fc2005-08-05 00:44:28 -0400699 pci_id->device = ACPI_HIWORD(ACPI_LODWORD(temp));
700 pci_id->function = ACPI_LOWORD(ACPI_LODWORD(temp));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701
702 if (*is_bridge)
703 pci_id->bus = *bus_number;
704
705 /* any nicer way to get bus number of bridge ? */
Len Brown4be44fc2005-08-05 00:44:28 -0400706 status =
707 acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8,
708 8);
709 if (ACPI_SUCCESS(status)
710 && ((tu8 & 0x7f) == 1 || (tu8 & 0x7f) == 2)) {
711 status =
712 acpi_os_read_pci_configuration(pci_id, 0x18,
713 &tu8, 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 if (!ACPI_SUCCESS(status)) {
715 /* Certainly broken... FIX ME */
716 return;
717 }
718 *is_bridge = 1;
719 pci_id->bus = tu8;
Len Brown4be44fc2005-08-05 00:44:28 -0400720 status =
721 acpi_os_read_pci_configuration(pci_id, 0x19,
722 &tu8, 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 if (ACPI_SUCCESS(status)) {
724 *bus_number = tu8;
725 }
726 } else
727 *is_bridge = 0;
728 }
729 }
730}
731
Len Brown4be44fc2005-08-05 00:44:28 -0400732void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */
733 acpi_handle chandle, /* current node */
734 struct acpi_pci_id **id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735{
736 int is_bridge = 1;
737 u8 bus_number = (*id)->bus;
738
739 acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number);
740}
741
David Howells65f27f32006-11-22 14:55:48 +0000742static void acpi_os_execute_deferred(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743{
David Howells65f27f32006-11-22 14:55:48 +0000744 struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
Alexey Starikovskiy88db5e12007-05-09 23:31:03 -0400745 if (!dpc) {
746 printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
747 return;
748 }
749
750 dpc->function(dpc->context);
751 kfree(dpc);
752
753 /* Yield cpu to notify thread */
754 cond_resched();
755
756 return;
757}
758
759static void acpi_os_execute_notify(struct work_struct *work)
760{
761 struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 if (!dpc) {
Len Brown64684632006-06-26 23:41:38 -0400764 printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
Patrick Mocheld550d982006-06-27 00:41:40 -0400765 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 }
767
768 dpc->function(dpc->context);
769
770 kfree(dpc);
771
Patrick Mocheld550d982006-06-27 00:41:40 -0400772 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773}
774
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400775/*******************************************************************************
776 *
777 * FUNCTION: acpi_os_execute
778 *
779 * PARAMETERS: Type - Type of the callback
780 * Function - Function to be executed
781 * Context - Function parameters
782 *
783 * RETURN: Status
784 *
785 * DESCRIPTION: Depending on type, either queues function for deferred execution or
786 * immediately executes function on a separate thread.
787 *
788 ******************************************************************************/
789
790acpi_status acpi_os_execute(acpi_execute_type type,
Len Brown4be44fc2005-08-05 00:44:28 -0400791 acpi_osd_exec_callback function, void *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792{
Len Brown4be44fc2005-08-05 00:44:28 -0400793 acpi_status status = AE_OK;
794 struct acpi_os_dpc *dpc;
Len Brown72945b22006-07-12 22:46:42 -0400795
Len Brown72945b22006-07-12 22:46:42 -0400796 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
797 "Scheduling function [%p(%p)] for deferred execution.\n",
798 function, context));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799
800 if (!function)
Alexey Starikovskiy88db5e12007-05-09 23:31:03 -0400801 return AE_BAD_PARAMETER;
Len Brown72945b22006-07-12 22:46:42 -0400802
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 /*
804 * Allocate/initialize DPC structure. Note that this memory will be
David Howells65f27f32006-11-22 14:55:48 +0000805 * freed by the callee. The kernel handles the work_struct list in a
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 * way that allows us to also free its memory inside the callee.
807 * Because we may want to schedule several tasks with different
808 * parameters we can't use the approach some kernel code uses of
David Howells65f27f32006-11-22 14:55:48 +0000809 * having a static work_struct.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 */
Len Brown72945b22006-07-12 22:46:42 -0400811
David Howells65f27f32006-11-22 14:55:48 +0000812 dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 if (!dpc)
Linus Torvaldsb976fe12006-11-17 19:31:09 -0800814 return_ACPI_STATUS(AE_NO_MEMORY);
815
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 dpc->function = function;
817 dpc->context = context;
Linus Torvaldsb976fe12006-11-17 19:31:09 -0800818
Alexey Starikovskiy88db5e12007-05-09 23:31:03 -0400819 if (type == OSL_NOTIFY_HANDLER) {
820 INIT_WORK(&dpc->work, acpi_os_execute_notify);
821 if (!queue_work(kacpi_notify_wq, &dpc->work)) {
822 status = AE_ERROR;
823 kfree(dpc);
824 }
825 } else {
826 INIT_WORK(&dpc->work, acpi_os_execute_deferred);
827 if (!queue_work(kacpid_wq, &dpc->work)) {
828 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
Linus Torvaldsb976fe12006-11-17 19:31:09 -0800829 "Call to queue_work() failed.\n"));
Alexey Starikovskiy88db5e12007-05-09 23:31:03 -0400830 status = AE_ERROR;
831 kfree(dpc);
832 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 }
Linus Torvaldsb976fe12006-11-17 19:31:09 -0800834 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835}
Len Brown4be44fc2005-08-05 00:44:28 -0400836
Alexey Starikovskiyb8d35192006-05-05 03:23:00 -0400837EXPORT_SYMBOL(acpi_os_execute);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838
Len Brown4be44fc2005-08-05 00:44:28 -0400839void acpi_os_wait_events_complete(void *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840{
841 flush_workqueue(kacpid_wq);
842}
Len Brown4be44fc2005-08-05 00:44:28 -0400843
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844EXPORT_SYMBOL(acpi_os_wait_events_complete);
845
846/*
847 * Allocate the memory for a spinlock and initialize it.
848 */
Bob Moore967440e32006-06-23 17:04:00 -0400849acpi_status acpi_os_create_lock(acpi_spinlock * handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850{
Bob Moore967440e32006-06-23 17:04:00 -0400851 spin_lock_init(*handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852
Patrick Mocheld550d982006-06-27 00:41:40 -0400853 return AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854}
855
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856/*
857 * Deallocate the memory for a spinlock.
858 */
Bob Moore967440e32006-06-23 17:04:00 -0400859void acpi_os_delete_lock(acpi_spinlock handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860{
Patrick Mocheld550d982006-06-27 00:41:40 -0400861 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862}
863
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400865acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866{
Len Brown4be44fc2005-08-05 00:44:28 -0400867 struct semaphore *sem = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869
870 sem = acpi_os_allocate(sizeof(struct semaphore));
871 if (!sem)
Patrick Mocheld550d982006-06-27 00:41:40 -0400872 return AE_NO_MEMORY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 memset(sem, 0, sizeof(struct semaphore));
874
875 sema_init(sem, initial_units);
876
Len Brown4be44fc2005-08-05 00:44:28 -0400877 *handle = (acpi_handle *) sem;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878
Len Brown4be44fc2005-08-05 00:44:28 -0400879 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Creating semaphore[%p|%d].\n",
880 *handle, initial_units));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881
Patrick Mocheld550d982006-06-27 00:41:40 -0400882 return AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884
Len Brown4be44fc2005-08-05 00:44:28 -0400885EXPORT_SYMBOL(acpi_os_create_semaphore);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
887/*
888 * TODO: A better way to delete semaphores? Linux doesn't have a
889 * 'delete_semaphore()' function -- may result in an invalid
890 * pointer dereference for non-synchronized consumers. Should
891 * we at least check for blocked threads and signal/cancel them?
892 */
893
Len Brown4be44fc2005-08-05 00:44:28 -0400894acpi_status acpi_os_delete_semaphore(acpi_handle handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895{
Len Brown4be44fc2005-08-05 00:44:28 -0400896 struct semaphore *sem = (struct semaphore *)handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898
899 if (!sem)
Patrick Mocheld550d982006-06-27 00:41:40 -0400900 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
Len Brown4be44fc2005-08-05 00:44:28 -0400902 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903
Len Brown02438d82006-06-30 03:19:10 -0400904 kfree(sem);
Len Brown4be44fc2005-08-05 00:44:28 -0400905 sem = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906
Patrick Mocheld550d982006-06-27 00:41:40 -0400907 return AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909
Len Brown4be44fc2005-08-05 00:44:28 -0400910EXPORT_SYMBOL(acpi_os_delete_semaphore);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911
912/*
913 * TODO: The kernel doesn't have a 'down_timeout' function -- had to
914 * improvise. The process is to sleep for one scheduler quantum
915 * until the semaphore becomes available. Downside is that this
916 * may result in starvation for timeout-based waits when there's
917 * lots of semaphore activity.
918 *
919 * TODO: Support for units > 1?
920 */
Len Brown4be44fc2005-08-05 00:44:28 -0400921acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922{
Len Brown4be44fc2005-08-05 00:44:28 -0400923 acpi_status status = AE_OK;
924 struct semaphore *sem = (struct semaphore *)handle;
925 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927
928 if (!sem || (units < 1))
Patrick Mocheld550d982006-06-27 00:41:40 -0400929 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930
931 if (units > 1)
Patrick Mocheld550d982006-06-27 00:41:40 -0400932 return AE_SUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933
Len Brown4be44fc2005-08-05 00:44:28 -0400934 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n",
935 handle, units, timeout));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936
Len Brownd68909f2006-08-16 19:16:58 -0400937 /*
938 * This can be called during resume with interrupts off.
939 * Like boot-time, we should be single threaded and will
940 * always get the lock if we try -- timeout or not.
941 * If this doesn't succeed, then we will oops courtesy of
942 * might_sleep() in down().
943 */
944 if (!down_trylock(sem))
945 return AE_OK;
946
Len Brown4be44fc2005-08-05 00:44:28 -0400947 switch (timeout) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 /*
949 * No Wait:
950 * --------
951 * A zero timeout value indicates that we shouldn't wait - just
952 * acquire the semaphore if available otherwise return AE_TIME
953 * (a.k.a. 'would block').
954 */
Len Brown4be44fc2005-08-05 00:44:28 -0400955 case 0:
956 if (down_trylock(sem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 status = AE_TIME;
958 break;
959
960 /*
961 * Wait Indefinitely:
962 * ------------------
963 */
Len Brown4be44fc2005-08-05 00:44:28 -0400964 case ACPI_WAIT_FOREVER:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 down(sem);
966 break;
967
968 /*
969 * Wait w/ Timeout:
970 * ----------------
971 */
Len Brown4be44fc2005-08-05 00:44:28 -0400972 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 // TODO: A better timeout algorithm?
974 {
975 int i = 0;
Len Brown4be44fc2005-08-05 00:44:28 -0400976 static const int quantum_ms = 1000 / HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977
978 ret = down_trylock(sem);
Yu Lumingdacd9b82005-12-31 01:45:00 -0500979 for (i = timeout; (i > 0 && ret != 0); i -= quantum_ms) {
Nishanth Aravamudan01a527e2005-11-07 01:01:14 -0800980 schedule_timeout_interruptible(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 ret = down_trylock(sem);
982 }
Len Brown4be44fc2005-08-05 00:44:28 -0400983
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 if (ret != 0)
985 status = AE_TIME;
986 }
987 break;
988 }
989
990 if (ACPI_FAILURE(status)) {
Bjorn Helgaas9e7e2c02006-04-27 05:25:00 -0400991 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
Thomas Renningera6fc6722006-06-26 23:58:43 -0400992 "Failed to acquire semaphore[%p|%d|%d], %s",
Len Brown4be44fc2005-08-05 00:44:28 -0400993 handle, units, timeout,
994 acpi_format_exception(status)));
995 } else {
996 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
Thomas Renningera6fc6722006-06-26 23:58:43 -0400997 "Acquired semaphore[%p|%d|%d]", handle,
Len Brown4be44fc2005-08-05 00:44:28 -0400998 units, timeout));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 }
1000
Patrick Mocheld550d982006-06-27 00:41:40 -04001001 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003
Len Brown4be44fc2005-08-05 00:44:28 -04001004EXPORT_SYMBOL(acpi_os_wait_semaphore);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005
1006/*
1007 * TODO: Support for units > 1?
1008 */
Len Brown4be44fc2005-08-05 00:44:28 -04001009acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010{
Len Brown4be44fc2005-08-05 00:44:28 -04001011 struct semaphore *sem = (struct semaphore *)handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013
1014 if (!sem || (units < 1))
Patrick Mocheld550d982006-06-27 00:41:40 -04001015 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016
1017 if (units > 1)
Patrick Mocheld550d982006-06-27 00:41:40 -04001018 return AE_SUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019
Len Brown4be44fc2005-08-05 00:44:28 -04001020 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle,
1021 units));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022
1023 up(sem);
1024
Patrick Mocheld550d982006-06-27 00:41:40 -04001025 return AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026}
Len Brown4be44fc2005-08-05 00:44:28 -04001027
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028EXPORT_SYMBOL(acpi_os_signal_semaphore);
1029
1030#ifdef ACPI_FUTURE_USAGE
Len Brown4be44fc2005-08-05 00:44:28 -04001031u32 acpi_os_get_line(char *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032{
1033
1034#ifdef ENABLE_DEBUGGER
1035 if (acpi_in_debugger) {
1036 u32 chars;
1037
1038 kdb_read(buffer, sizeof(line_buf));
1039
1040 /* remove the CR kdb includes */
1041 chars = strlen(buffer) - 1;
1042 buffer[chars] = '\0';
1043 }
1044#endif
1045
1046 return 0;
1047}
Len Brown4be44fc2005-08-05 00:44:28 -04001048#endif /* ACPI_FUTURE_USAGE */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049
Len Brown4be44fc2005-08-05 00:44:28 -04001050acpi_status acpi_os_signal(u32 function, void *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051{
Len Brown4be44fc2005-08-05 00:44:28 -04001052 switch (function) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 case ACPI_SIGNAL_FATAL:
1054 printk(KERN_ERR PREFIX "Fatal opcode executed\n");
1055 break;
1056 case ACPI_SIGNAL_BREAKPOINT:
1057 /*
1058 * AML Breakpoint
1059 * ACPI spec. says to treat it as a NOP unless
1060 * you are debugging. So if/when we integrate
1061 * AML debugger into the kernel debugger its
1062 * hook will go here. But until then it is
1063 * not useful to print anything on breakpoints.
1064 */
1065 break;
1066 default:
1067 break;
1068 }
1069
1070 return AE_OK;
1071}
Len Brown4be44fc2005-08-05 00:44:28 -04001072
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073EXPORT_SYMBOL(acpi_os_signal);
1074
Len Brown4be44fc2005-08-05 00:44:28 -04001075static int __init acpi_os_name_setup(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076{
1077 char *p = acpi_os_name;
Len Brown4be44fc2005-08-05 00:44:28 -04001078 int count = ACPI_MAX_OVERRIDE_LEN - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079
1080 if (!str || !*str)
1081 return 0;
1082
1083 for (; count-- && str && *str; str++) {
1084 if (isalnum(*str) || *str == ' ' || *str == ':')
1085 *p++ = *str;
1086 else if (*str == '\'' || *str == '"')
1087 continue;
1088 else
1089 break;
1090 }
1091 *p = 0;
1092
1093 return 1;
Len Brown4be44fc2005-08-05 00:44:28 -04001094
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095}
1096
1097__setup("acpi_os_name=", acpi_os_name_setup);
1098
Len Brownd4b7dc42008-01-23 20:50:56 -05001099static void __init set_osi_linux(unsigned int enable)
1100{
1101 if (osi_linux.enable != enable) {
1102 osi_linux.enable = enable;
1103 printk(KERN_NOTICE PREFIX "%sed _OSI(Linux)\n",
1104 enable ? "Add": "Delet");
1105 }
1106 return;
1107}
Len Brownf5076542007-05-30 00:10:38 -04001108
Len Brownd4b7dc42008-01-23 20:50:56 -05001109static void __init acpi_cmdline_osi_linux(unsigned int enable)
1110{
1111 osi_linux.cmdline = 1; /* cmdline set the default */
1112 set_osi_linux(enable);
Len Brownf5076542007-05-30 00:10:38 -04001113
Len Brownd4b7dc42008-01-23 20:50:56 -05001114 return;
1115}
1116
1117void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d)
1118{
1119 osi_linux.dmi = 1; /* DMI knows that this box asks OSI(Linux) */
1120
1121 printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
1122
1123 if (enable == -1)
1124 return;
1125
1126 osi_linux.known = 1; /* DMI knows which OSI(Linux) default needed */
1127
1128 set_osi_linux(enable);
1129
Len Brownf5076542007-05-30 00:10:38 -04001130 return;
1131}
1132
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133/*
Len Brownae00d812007-05-29 18:43:33 -04001134 * Modify the list of "OS Interfaces" reported to BIOS via _OSI
1135 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 * empty string disables _OSI
Len Brownae00d812007-05-29 18:43:33 -04001137 * string starting with '!' disables that string
1138 * otherwise string is added to list, augmenting built-in strings
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 */
Len Brown4be44fc2005-08-05 00:44:28 -04001140static int __init acpi_osi_setup(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141{
1142 if (str == NULL || *str == '\0') {
1143 printk(KERN_INFO PREFIX "_OSI method disabled\n");
1144 acpi_gbl_create_osi_method = FALSE;
Len Brownaa2e09d2007-07-02 23:57:45 -04001145 } else if (!strcmp("!Linux", str)) {
Len Brownd4b7dc42008-01-23 20:50:56 -05001146 acpi_cmdline_osi_linux(0); /* !enable */
Len Brownae00d812007-05-29 18:43:33 -04001147 } else if (*str == '!') {
1148 if (acpi_osi_invalidate(++str) == AE_OK)
1149 printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
Len Brownf5076542007-05-30 00:10:38 -04001150 } else if (!strcmp("Linux", str)) {
Len Brownd4b7dc42008-01-23 20:50:56 -05001151 acpi_cmdline_osi_linux(1); /* enable */
Len Brownae00d812007-05-29 18:43:33 -04001152 } else if (*osi_additional_string == '\0') {
1153 strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX);
1154 printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 }
1156
1157 return 1;
1158}
1159
1160__setup("acpi_osi=", acpi_osi_setup);
1161
1162/* enable serialization to combat AE_ALREADY_EXISTS errors */
Len Brown4be44fc2005-08-05 00:44:28 -04001163static int __init acpi_serialize_setup(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164{
1165 printk(KERN_INFO PREFIX "serialize enabled\n");
1166
1167 acpi_gbl_all_methods_serialized = TRUE;
1168
1169 return 1;
1170}
1171
1172__setup("acpi_serialize", acpi_serialize_setup);
1173
1174/*
1175 * Wake and Run-Time GPES are expected to be separate.
1176 * We disable wake-GPEs at run-time to prevent spurious
1177 * interrupts.
1178 *
1179 * However, if a system exists that shares Wake and
1180 * Run-time events on the same GPE this flag is available
1181 * to tell Linux to keep the wake-time GPEs enabled at run-time.
1182 */
Len Brown4be44fc2005-08-05 00:44:28 -04001183static int __init acpi_wake_gpes_always_on_setup(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184{
1185 printk(KERN_INFO PREFIX "wake GPEs not disabled\n");
1186
1187 acpi_gbl_leave_wake_gpes_disabled = FALSE;
1188
1189 return 1;
1190}
1191
1192__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
1193
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194/*
Robert Moore73459f72005-06-24 00:00:00 -04001195 * Acquire a spinlock.
1196 *
1197 * handle is a pointer to the spinlock_t.
Robert Moore73459f72005-06-24 00:00:00 -04001198 */
1199
Bob Moore967440e32006-06-23 17:04:00 -04001200acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp)
Robert Moore73459f72005-06-24 00:00:00 -04001201{
Bob Mooreb8e4d892006-01-27 16:43:00 -05001202 acpi_cpu_flags flags;
Bob Moore967440e32006-06-23 17:04:00 -04001203 spin_lock_irqsave(lockp, flags);
Robert Moore73459f72005-06-24 00:00:00 -04001204 return flags;
1205}
1206
1207/*
1208 * Release a spinlock. See above.
1209 */
1210
Bob Moore967440e32006-06-23 17:04:00 -04001211void acpi_os_release_lock(acpi_spinlock lockp, acpi_cpu_flags flags)
Robert Moore73459f72005-06-24 00:00:00 -04001212{
Bob Moore967440e32006-06-23 17:04:00 -04001213 spin_unlock_irqrestore(lockp, flags);
Robert Moore73459f72005-06-24 00:00:00 -04001214}
1215
Robert Moore73459f72005-06-24 00:00:00 -04001216#ifndef ACPI_USE_LOCAL_CACHE
1217
1218/*******************************************************************************
1219 *
1220 * FUNCTION: acpi_os_create_cache
1221 *
Bob Mooreb229cf92006-04-21 17:15:00 -04001222 * PARAMETERS: name - Ascii name for the cache
1223 * size - Size of each cached object
1224 * depth - Maximum depth of the cache (in objects) <ignored>
1225 * cache - Where the new cache object is returned
Robert Moore73459f72005-06-24 00:00:00 -04001226 *
Bob Mooreb229cf92006-04-21 17:15:00 -04001227 * RETURN: status
Robert Moore73459f72005-06-24 00:00:00 -04001228 *
1229 * DESCRIPTION: Create a cache object
1230 *
1231 ******************************************************************************/
1232
1233acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -04001234acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache)
Robert Moore73459f72005-06-24 00:00:00 -04001235{
Paul Mundt20c2df82007-07-20 10:11:58 +09001236 *cache = kmem_cache_create(name, size, 0, 0, NULL);
Adrian Bunka6fdbf92006-12-19 12:56:13 -08001237 if (*cache == NULL)
Bob Mooreb229cf92006-04-21 17:15:00 -04001238 return AE_ERROR;
1239 else
1240 return AE_OK;
Robert Moore73459f72005-06-24 00:00:00 -04001241}
1242
1243/*******************************************************************************
1244 *
1245 * FUNCTION: acpi_os_purge_cache
1246 *
1247 * PARAMETERS: Cache - Handle to cache object
1248 *
1249 * RETURN: Status
1250 *
1251 * DESCRIPTION: Free all objects within the requested cache.
1252 *
1253 ******************************************************************************/
1254
Len Brown4be44fc2005-08-05 00:44:28 -04001255acpi_status acpi_os_purge_cache(acpi_cache_t * cache)
Robert Moore73459f72005-06-24 00:00:00 -04001256{
Jan Engelhardt50dd0962006-10-01 00:28:50 +02001257 kmem_cache_shrink(cache);
Len Brown4be44fc2005-08-05 00:44:28 -04001258 return (AE_OK);
Robert Moore73459f72005-06-24 00:00:00 -04001259}
1260
1261/*******************************************************************************
1262 *
1263 * FUNCTION: acpi_os_delete_cache
1264 *
1265 * PARAMETERS: Cache - Handle to cache object
1266 *
1267 * RETURN: Status
1268 *
1269 * DESCRIPTION: Free all objects within the requested cache and delete the
1270 * cache object.
1271 *
1272 ******************************************************************************/
1273
Len Brown4be44fc2005-08-05 00:44:28 -04001274acpi_status acpi_os_delete_cache(acpi_cache_t * cache)
Robert Moore73459f72005-06-24 00:00:00 -04001275{
Alexey Dobriyan1a1d92c2006-09-27 01:49:40 -07001276 kmem_cache_destroy(cache);
Len Brown4be44fc2005-08-05 00:44:28 -04001277 return (AE_OK);
Robert Moore73459f72005-06-24 00:00:00 -04001278}
1279
1280/*******************************************************************************
1281 *
1282 * FUNCTION: acpi_os_release_object
1283 *
1284 * PARAMETERS: Cache - Handle to cache object
1285 * Object - The object to be released
1286 *
1287 * RETURN: None
1288 *
1289 * DESCRIPTION: Release an object to the specified cache. If cache is full,
1290 * the object is deleted.
1291 *
1292 ******************************************************************************/
1293
Len Brown4be44fc2005-08-05 00:44:28 -04001294acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
Robert Moore73459f72005-06-24 00:00:00 -04001295{
Len Brown4be44fc2005-08-05 00:44:28 -04001296 kmem_cache_free(cache, object);
1297 return (AE_OK);
Robert Moore73459f72005-06-24 00:00:00 -04001298}
1299
Len Brown5a4e1432008-01-23 20:01:22 -05001300/**
1301 * acpi_dmi_dump - dump DMI slots needed for blacklist entry
1302 *
1303 * Returns 0 on success
1304 */
1305int acpi_dmi_dump(void)
1306{
1307
1308 if (!dmi_available)
1309 return -1;
1310
1311 printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n",
1312 dmi_get_slot(DMI_SYS_VENDOR));
1313 printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n",
1314 dmi_get_slot(DMI_PRODUCT_NAME));
1315 printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n",
1316 dmi_get_slot(DMI_PRODUCT_VERSION));
1317 printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n",
1318 dmi_get_slot(DMI_BOARD_NAME));
1319 printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n",
1320 dmi_get_slot(DMI_BIOS_VENDOR));
1321 printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n",
1322 dmi_get_slot(DMI_BIOS_DATE));
1323
1324 return 0;
1325}
1326
1327
Bob Mooreb229cf92006-04-21 17:15:00 -04001328/******************************************************************************
1329 *
1330 * FUNCTION: acpi_os_validate_interface
1331 *
1332 * PARAMETERS: interface - Requested interface to be validated
1333 *
1334 * RETURN: AE_OK if interface is supported, AE_SUPPORT otherwise
1335 *
1336 * DESCRIPTION: Match an interface string to the interfaces supported by the
1337 * host. Strings originate from an AML call to the _OSI method.
1338 *
1339 *****************************************************************************/
1340
1341acpi_status
1342acpi_os_validate_interface (char *interface)
1343{
Len Brownae00d812007-05-29 18:43:33 -04001344 if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX))
1345 return AE_OK;
Len Brownf5076542007-05-30 00:10:38 -04001346 if (!strcmp("Linux", interface)) {
Len Brownd4b7dc42008-01-23 20:50:56 -05001347
1348 printk(KERN_NOTICE PREFIX
1349 "BIOS _OSI(Linux) query %s%s\n",
1350 osi_linux.enable ? "honored" : "ignored",
1351 osi_linux.cmdline ? " via cmdline" :
1352 osi_linux.dmi ? " via DMI" : "");
1353
1354 if (!osi_linux.dmi) {
1355 if (acpi_dmi_dump())
1356 printk(KERN_NOTICE PREFIX
1357 "[please extract dmidecode output]\n");
Len Brownf40cd6f2008-01-23 20:04:28 -05001358 printk(KERN_NOTICE PREFIX
Len Brownd4b7dc42008-01-23 20:50:56 -05001359 "Please send DMI info above to "
1360 "linux-acpi@vger.kernel.org\n");
1361 }
1362 if (!osi_linux.known && !osi_linux.cmdline) {
1363 printk(KERN_NOTICE PREFIX
1364 "If \"acpi_osi=%sLinux\" works better, "
1365 "please notify linux-acpi@vger.kernel.org\n",
1366 osi_linux.enable ? "!" : "");
1367 }
1368
1369 if (osi_linux.enable)
Len Brownf5076542007-05-30 00:10:38 -04001370 return AE_OK;
1371 }
Len Brownae00d812007-05-29 18:43:33 -04001372 return AE_SUPPORT;
Bob Mooreb229cf92006-04-21 17:15:00 -04001373}
1374
Bob Mooreb229cf92006-04-21 17:15:00 -04001375/******************************************************************************
1376 *
1377 * FUNCTION: acpi_os_validate_address
1378 *
1379 * PARAMETERS: space_id - ACPI space ID
1380 * address - Physical address
1381 * length - Address length
1382 *
1383 * RETURN: AE_OK if address/length is valid for the space_id. Otherwise,
1384 * should return AE_AML_ILLEGAL_ADDRESS.
1385 *
1386 * DESCRIPTION: Validate a system address via the host OS. Used to validate
1387 * the addresses accessed by AML operation regions.
1388 *
1389 *****************************************************************************/
1390
1391acpi_status
1392acpi_os_validate_address (
1393 u8 space_id,
1394 acpi_physical_address address,
1395 acpi_size length)
1396{
1397
1398 return AE_OK;
1399}
1400
Robert Moore73459f72005-06-24 00:00:00 -04001401#endif