X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Facpi%2Fosl.c;h=12c09fafce9a29de915966be172e96a94eef79a1;hb=53fdc5185c994ad6def3729a905ac4a47c477c9d;hp=20c9a37643c73110f0e18fd5efef989906d2bf14;hpb=55a82ab3181be039c6440d3f2f69260ad6fe2988;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 20c9a37..12c09fa 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -25,18 +25,18 @@ * */ -#include #include #include #include #include #include -#include #include #include #include +#include #include #include +#include #include #include #include @@ -46,11 +46,12 @@ #include #define _COMPONENT ACPI_OS_SERVICES -ACPI_MODULE_NAME("osl") +ACPI_MODULE_NAME("osl"); #define PREFIX "ACPI: " struct acpi_os_dpc { acpi_osd_exec_callback function; void *context; + struct work_struct work; }; #ifdef CONFIG_ACPI_CUSTOM_DSDT @@ -67,16 +68,72 @@ EXPORT_SYMBOL(acpi_in_debugger); extern char line_buf[80]; #endif /*ENABLE_DEBUGGER */ -int acpi_specific_hotkey_enabled = TRUE; -EXPORT_SYMBOL(acpi_specific_hotkey_enabled); - static unsigned int acpi_irq_irq; static acpi_osd_handler acpi_irq_handler; static void *acpi_irq_context; static struct workqueue_struct *kacpid_wq; +static struct workqueue_struct *kacpi_notify_wq; + +#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ +static char osi_additional_string[OSI_STRING_LENGTH_MAX]; + +static int osi_linux; /* disable _OSI(Linux) by default */ + +#ifdef CONFIG_DMI +static struct __initdata dmi_system_id acpi_osl_dmi_table[]; +#endif + +static void __init acpi_request_region (struct acpi_generic_address *addr, + unsigned int length, char *desc) +{ + struct resource *res; + + if (!addr->address || !length) + return; + + if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_IO) + res = request_region(addr->address, length, desc); + else if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) + res = request_mem_region(addr->address, length, desc); +} + +static int __init acpi_reserve_resources(void) +{ + acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length, + "ACPI PM1a_EVT_BLK"); + + acpi_request_region(&acpi_gbl_FADT.xpm1b_event_block, acpi_gbl_FADT.pm1_event_length, + "ACPI PM1b_EVT_BLK"); + + acpi_request_region(&acpi_gbl_FADT.xpm1a_control_block, acpi_gbl_FADT.pm1_control_length, + "ACPI PM1a_CNT_BLK"); + + acpi_request_region(&acpi_gbl_FADT.xpm1b_control_block, acpi_gbl_FADT.pm1_control_length, + "ACPI PM1b_CNT_BLK"); + + if (acpi_gbl_FADT.pm_timer_length == 4) + acpi_request_region(&acpi_gbl_FADT.xpm_timer_block, 4, "ACPI PM_TMR"); + + acpi_request_region(&acpi_gbl_FADT.xpm2_control_block, acpi_gbl_FADT.pm2_control_length, + "ACPI PM2_CNT_BLK"); + + /* Length of GPE blocks must be a non-negative multiple of 2 */ + + if (!(acpi_gbl_FADT.gpe0_block_length & 0x1)) + acpi_request_region(&acpi_gbl_FADT.xgpe0_block, + acpi_gbl_FADT.gpe0_block_length, "ACPI GPE0_BLK"); + + if (!(acpi_gbl_FADT.gpe1_block_length & 0x1)) + acpi_request_region(&acpi_gbl_FADT.xgpe1_block, + acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK"); + + return 0; +} +device_initcall(acpi_reserve_resources); -acpi_status acpi_os_initialize(void) +acpi_status __init acpi_os_initialize(void) { + dmi_check_system(acpi_osl_dmi_table); return AE_OK; } @@ -92,8 +149,9 @@ acpi_status acpi_os_initialize1(void) return AE_NULL_ENTRY; } kacpid_wq = create_singlethread_workqueue("kacpid"); + kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); BUG_ON(!kacpid_wq); - + BUG_ON(!kacpi_notify_wq); return AE_OK; } @@ -105,6 +163,7 @@ acpi_status acpi_os_terminate(void) } destroy_workqueue(kacpid_wq); + destroy_workqueue(kacpi_notify_wq); return AE_OK; } @@ -136,79 +195,43 @@ void acpi_os_vprintf(const char *fmt, va_list args) #endif } -extern int acpi_in_resume; -void *acpi_os_allocate(acpi_size size) -{ - if (acpi_in_resume) - return kmalloc(size, GFP_ATOMIC); - else - return kmalloc(size, GFP_KERNEL); -} - -void acpi_os_free(void *ptr) -{ - kfree(ptr); -} - -EXPORT_SYMBOL(acpi_os_free); - -acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr) +acpi_physical_address __init acpi_os_get_root_pointer(void) { if (efi_enabled) { - addr->pointer_type = ACPI_PHYSICAL_POINTER; - if (efi.acpi20) - addr->pointer.physical = - (acpi_physical_address) virt_to_phys(efi.acpi20); - else if (efi.acpi) - addr->pointer.physical = - (acpi_physical_address) virt_to_phys(efi.acpi); + if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) + return efi.acpi20; + else if (efi.acpi != EFI_INVALID_TABLE_ADDR) + return efi.acpi; else { printk(KERN_ERR PREFIX "System description tables not found\n"); - return AE_NOT_FOUND; + return 0; } - } else { - if (ACPI_FAILURE(acpi_find_root_pointer(flags, addr))) { - printk(KERN_ERR PREFIX - "System description tables not found\n"); - return AE_NOT_FOUND; - } - } - - return AE_OK; + } else + return acpi_find_rsdp(); } -acpi_status -acpi_os_map_memory(acpi_physical_address phys, acpi_size size, - void __iomem ** virt) +void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size) { - if (efi_enabled) { - if (EFI_MEMORY_WB & efi_mem_attributes(phys)) { - *virt = (void __iomem *)phys_to_virt(phys); - } else { - *virt = ioremap(phys, size); - } - } else { - if (phys > ULONG_MAX) { - printk(KERN_ERR PREFIX "Cannot map memory that high\n"); - return AE_BAD_PARAMETER; - } - /* - * ioremap checks to ensure this is in reserved space - */ - *virt = ioremap((unsigned long)phys, size); + if (phys > ULONG_MAX) { + printk(KERN_ERR PREFIX "Cannot map memory that high\n"); + return NULL; } - - if (!*virt) - return AE_NO_MEMORY; - - return AE_OK; + if (acpi_gbl_permanent_mmap) + /* + * ioremap checks to ensure this is in reserved space + */ + return ioremap((unsigned long)phys, size); + else + return __acpi_map_table((unsigned long)phys, size); } EXPORT_SYMBOL_GPL(acpi_os_map_memory); void acpi_os_unmap_memory(void __iomem * virt, acpi_size size) { - iounmap(virt); + if (acpi_gbl_permanent_mmap) { + iounmap(virt); + } } EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); @@ -264,7 +287,7 @@ acpi_os_table_override(struct acpi_table_header * existing_table, return AE_OK; } -static irqreturn_t acpi_irq(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t acpi_irq(int irq, void *dev_id) { return (*acpi_irq_handler) (acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE; } @@ -280,7 +303,7 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, * FADT. It may not be the same if an interrupt source override exists * for the SCI. */ - gsi = acpi_fadt.sci_int; + gsi = acpi_gbl_FADT.sci_interrupt; if (acpi_gsi_to_irq(gsi, &irq) < 0) { printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n", gsi); @@ -289,7 +312,7 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, acpi_irq_handler = handler; acpi_irq_context = context; - if (request_irq(irq, acpi_irq, SA_SHIRQ, "acpi", acpi_irq)) { + if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) { printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); return AE_NOT_ACQUIRED; } @@ -409,18 +432,8 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width) { u32 dummy; void __iomem *virt_addr; - int iomem = 0; - if (efi_enabled) { - if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) { - /* HACK ALERT! We can use readb/w/l on real memory too.. */ - virt_addr = (void __iomem *)phys_to_virt(phys_addr); - } else { - iomem = 1; - virt_addr = ioremap(phys_addr, width); - } - } else - virt_addr = (void __iomem *)phys_to_virt(phys_addr); + virt_addr = ioremap(phys_addr, width); if (!value) value = &dummy; @@ -438,10 +451,7 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width) BUG(); } - if (efi_enabled) { - if (iomem) - iounmap(virt_addr); - } + iounmap(virt_addr); return AE_OK; } @@ -450,18 +460,8 @@ acpi_status acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width) { void __iomem *virt_addr; - int iomem = 0; - if (efi_enabled) { - if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) { - /* HACK ALERT! We can use writeb/w/l on real memory too */ - virt_addr = (void __iomem *)phys_to_virt(phys_addr); - } else { - iomem = 1; - virt_addr = ioremap(phys_addr, width); - } - } else - virt_addr = (void __iomem *)phys_to_virt(phys_addr); + virt_addr = ioremap(phys_addr, width); switch (width) { case 8: @@ -477,8 +477,7 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width) BUG(); } - if (iomem) - iounmap(virt_addr); + iounmap(virt_addr); return AE_OK; } @@ -615,76 +614,102 @@ void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */ acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number); } -static void acpi_os_execute_deferred(void *context) +static void acpi_os_execute_deferred(struct work_struct *work) { - struct acpi_os_dpc *dpc = NULL; + struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); + if (!dpc) { + printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); + return; + } + + dpc->function(dpc->context); + kfree(dpc); + + /* Yield cpu to notify thread */ + cond_resched(); - ACPI_FUNCTION_TRACE("os_execute_deferred"); + return; +} + +static void acpi_os_execute_notify(struct work_struct *work) +{ + struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); - dpc = (struct acpi_os_dpc *)context; if (!dpc) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid (NULL) context.\n")); - return_VOID; + printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); + return; } dpc->function(dpc->context); kfree(dpc); - return_VOID; + return; } -acpi_status -acpi_os_queue_for_execution(u32 priority, +/******************************************************************************* + * + * FUNCTION: acpi_os_execute + * + * PARAMETERS: Type - Type of the callback + * Function - Function to be executed + * Context - Function parameters + * + * RETURN: Status + * + * DESCRIPTION: Depending on type, either queues function for deferred execution or + * immediately executes function on a separate thread. + * + ******************************************************************************/ + +acpi_status acpi_os_execute(acpi_execute_type type, acpi_osd_exec_callback function, void *context) { acpi_status status = AE_OK; struct acpi_os_dpc *dpc; - struct work_struct *task; - - ACPI_FUNCTION_TRACE("os_queue_for_execution"); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); if (!function) - return_ACPI_STATUS(AE_BAD_PARAMETER); + return AE_BAD_PARAMETER; /* * Allocate/initialize DPC structure. Note that this memory will be - * freed by the callee. The kernel handles the tq_struct list in a + * freed by the callee. The kernel handles the work_struct list in a * way that allows us to also free its memory inside the callee. * Because we may want to schedule several tasks with different * parameters we can't use the approach some kernel code uses of - * having a static tq_struct. - * We can save time and code by allocating the DPC and tq_structs - * from the same memory. + * having a static work_struct. */ - dpc = - kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct), - GFP_ATOMIC); + dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_ATOMIC); if (!dpc) return_ACPI_STATUS(AE_NO_MEMORY); dpc->function = function; dpc->context = context; - task = (void *)(dpc + 1); - INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc); - - if (!queue_work(kacpid_wq, task)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + if (type == OSL_NOTIFY_HANDLER) { + INIT_WORK(&dpc->work, acpi_os_execute_notify); + if (!queue_work(kacpi_notify_wq, &dpc->work)) { + status = AE_ERROR; + kfree(dpc); + } + } else { + INIT_WORK(&dpc->work, acpi_os_execute_deferred); + if (!queue_work(kacpid_wq, &dpc->work)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Call to queue_work() failed.\n")); - kfree(dpc); - status = AE_ERROR; + status = AE_ERROR; + kfree(dpc); + } } - return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_os_queue_for_execution); +EXPORT_SYMBOL(acpi_os_execute); void acpi_os_wait_events_complete(void *context) { @@ -696,35 +721,19 @@ EXPORT_SYMBOL(acpi_os_wait_events_complete); /* * Allocate the memory for a spinlock and initialize it. */ -acpi_status acpi_os_create_lock(acpi_handle * out_handle) +acpi_status acpi_os_create_lock(acpi_spinlock * handle) { - spinlock_t *lock_ptr; - - ACPI_FUNCTION_TRACE("os_create_lock"); - - lock_ptr = acpi_os_allocate(sizeof(spinlock_t)); + spin_lock_init(*handle); - spin_lock_init(lock_ptr); - - ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Creating spinlock[%p].\n", lock_ptr)); - - *out_handle = lock_ptr; - - return_ACPI_STATUS(AE_OK); + return AE_OK; } /* * Deallocate the memory for a spinlock. */ -void acpi_os_delete_lock(acpi_handle handle) +void acpi_os_delete_lock(acpi_spinlock handle) { - ACPI_FUNCTION_TRACE("os_create_lock"); - - ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting spinlock[%p].\n", handle)); - - acpi_os_free(handle); - - return_VOID; + return; } acpi_status @@ -732,11 +741,10 @@ acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle) { struct semaphore *sem = NULL; - ACPI_FUNCTION_TRACE("os_create_semaphore"); sem = acpi_os_allocate(sizeof(struct semaphore)); if (!sem) - return_ACPI_STATUS(AE_NO_MEMORY); + return AE_NO_MEMORY; memset(sem, 0, sizeof(struct semaphore)); sema_init(sem, initial_units); @@ -746,7 +754,7 @@ acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle) ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Creating semaphore[%p|%d].\n", *handle, initial_units)); - return_ACPI_STATUS(AE_OK); + return AE_OK; } EXPORT_SYMBOL(acpi_os_create_semaphore); @@ -762,17 +770,16 @@ acpi_status acpi_os_delete_semaphore(acpi_handle handle) { struct semaphore *sem = (struct semaphore *)handle; - ACPI_FUNCTION_TRACE("os_delete_semaphore"); if (!sem) - return_ACPI_STATUS(AE_BAD_PARAMETER); + return AE_BAD_PARAMETER; ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle)); - acpi_os_free(sem); + kfree(sem); sem = NULL; - return_ACPI_STATUS(AE_OK); + return AE_OK; } EXPORT_SYMBOL(acpi_os_delete_semaphore); @@ -792,19 +799,25 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) struct semaphore *sem = (struct semaphore *)handle; int ret = 0; - ACPI_FUNCTION_TRACE("os_wait_semaphore"); if (!sem || (units < 1)) - return_ACPI_STATUS(AE_BAD_PARAMETER); + return AE_BAD_PARAMETER; if (units > 1) - return_ACPI_STATUS(AE_SUPPORT); + return AE_SUPPORT; ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout)); - if (in_atomic()) - timeout = 0; + /* + * This can be called during resume with interrupts off. + * Like boot-time, we should be single threaded and will + * always get the lock if we try -- timeout or not. + * If this doesn't succeed, then we will oops courtesy of + * might_sleep() in down(). + */ + if (!down_trylock(sem)) + return AE_OK; switch (timeout) { /* @@ -838,7 +851,7 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) static const int quantum_ms = 1000 / HZ; ret = down_trylock(sem); - for (i = timeout; (i > 0 && ret < 0); i -= quantum_ms) { + for (i = timeout; (i > 0 && ret != 0); i -= quantum_ms) { schedule_timeout_interruptible(1); ret = down_trylock(sem); } @@ -850,17 +863,17 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) } if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Failed to acquire semaphore[%p|%d|%d], %s\n", + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, + "Failed to acquire semaphore[%p|%d|%d], %s", handle, units, timeout, acpi_format_exception(status))); } else { ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, - "Acquired semaphore[%p|%d|%d]\n", handle, + "Acquired semaphore[%p|%d|%d]", handle, units, timeout)); } - return_ACPI_STATUS(status); + return status; } EXPORT_SYMBOL(acpi_os_wait_semaphore); @@ -872,20 +885,19 @@ acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units) { struct semaphore *sem = (struct semaphore *)handle; - ACPI_FUNCTION_TRACE("os_signal_semaphore"); if (!sem || (units < 1)) - return_ACPI_STATUS(AE_BAD_PARAMETER); + return AE_BAD_PARAMETER; if (units > 1) - return_ACPI_STATUS(AE_SUPPORT); + return AE_SUPPORT; ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle, units)); up(sem); - return_ACPI_STATUS(AE_OK); + return AE_OK; } EXPORT_SYMBOL(acpi_os_signal_semaphore); @@ -910,34 +922,6 @@ u32 acpi_os_get_line(char *buffer) } #endif /* ACPI_FUTURE_USAGE */ -/* Assumes no unreadable holes inbetween */ -u8 acpi_os_readable(void *ptr, acpi_size len) -{ -#if defined(__i386__) || defined(__x86_64__) - char tmp; - return !__get_user(tmp, (char __user *)ptr) - && !__get_user(tmp, (char __user *)ptr + len - 1); -#endif - return 1; -} - -#ifdef ACPI_FUTURE_USAGE -u8 acpi_os_writable(void *ptr, acpi_size len) -{ - /* could do dummy write (racy) or a kernel page table lookup. - The later may be difficult at early boot when kmap doesn't work yet. */ - return 1; -} -#endif - -u32 acpi_os_get_thread_id(void) -{ - if (!in_atomic()) - return current->pid; - - return 0; -} - acpi_status acpi_os_signal(u32 function, void *info) { switch (function) { @@ -987,20 +971,38 @@ static int __init acpi_os_name_setup(char *str) __setup("acpi_os_name=", acpi_os_name_setup); +static void enable_osi_linux(int enable) { + + if (osi_linux != enable) + printk(KERN_INFO PREFIX "%sabled _OSI(Linux)\n", + enable ? "En": "Dis"); + + osi_linux = enable; + return; +} + /* - * _OSI control + * Modify the list of "OS Interfaces" reported to BIOS via _OSI + * * empty string disables _OSI - * TBD additional string adds to _OSI + * string starting with '!' disables that string + * otherwise string is added to list, augmenting built-in strings */ static int __init acpi_osi_setup(char *str) { if (str == NULL || *str == '\0') { printk(KERN_INFO PREFIX "_OSI method disabled\n"); acpi_gbl_create_osi_method = FALSE; - } else { - /* TBD */ - printk(KERN_ERR PREFIX "_OSI additional string ignored -- %s\n", - str); + } else if (!strcmp("!Linux", str)) { + enable_osi_linux(0); + } else if (*str == '!') { + if (acpi_osi_invalidate(++str) == AE_OK) + printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str); + } else if (!strcmp("Linux", str)) { + enable_osi_linux(1); + } else if (*osi_additional_string == '\0') { + strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX); + printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str); } return 1; @@ -1040,14 +1042,6 @@ static int __init acpi_wake_gpes_always_on_setup(char *str) __setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup); -static int __init acpi_hotkey_setup(char *str) -{ - acpi_specific_hotkey_enabled = FALSE; - return 1; -} - -__setup("acpi_generic_hotkey", acpi_hotkey_setup); - /* * max_cstate is defined in the base kernel so modules can * change it w/o depending on the state of the processor module. @@ -1060,14 +1054,12 @@ EXPORT_SYMBOL(max_cstate); * Acquire a spinlock. * * handle is a pointer to the spinlock_t. - * flags is *not* the result of save_flags - it is an ACPI-specific flag variable - * that indicates whether we are at interrupt level. */ -unsigned long acpi_os_acquire_lock(acpi_handle handle) +acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp) { - unsigned long flags; - spin_lock_irqsave((spinlock_t *) handle, flags); + acpi_cpu_flags flags; + spin_lock_irqsave(lockp, flags); return flags; } @@ -1075,9 +1067,9 @@ unsigned long acpi_os_acquire_lock(acpi_handle handle) * Release a spinlock. See above. */ -void acpi_os_release_lock(acpi_handle handle, unsigned long flags) +void acpi_os_release_lock(acpi_spinlock lockp, acpi_cpu_flags flags) { - spin_unlock_irqrestore((spinlock_t *) handle, flags); + spin_unlock_irqrestore(lockp, flags); } #ifndef ACPI_USE_LOCAL_CACHE @@ -1086,12 +1078,12 @@ void acpi_os_release_lock(acpi_handle handle, unsigned long flags) * * FUNCTION: acpi_os_create_cache * - * PARAMETERS: CacheName - Ascii name for the cache - * ObjectSize - Size of each cached object - * MaxDepth - Maximum depth of the cache (in objects) - * ReturnCache - Where the new cache object is returned + * PARAMETERS: name - Ascii name for the cache + * size - Size of each cached object + * depth - Maximum depth of the cache (in objects) + * cache - Where the new cache object is returned * - * RETURN: Status + * RETURN: status * * DESCRIPTION: Create a cache object * @@ -1100,8 +1092,11 @@ void acpi_os_release_lock(acpi_handle handle, unsigned long flags) acpi_status acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache) { - *cache = kmem_cache_create(name, size, 0, 0, NULL, NULL); - return AE_OK; + *cache = kmem_cache_create(name, size, 0, 0, NULL); + if (*cache == NULL) + return AE_ERROR; + else + return AE_OK; } /******************************************************************************* @@ -1118,7 +1113,7 @@ acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache) acpi_status acpi_os_purge_cache(acpi_cache_t * cache) { - (void)kmem_cache_shrink(cache); + kmem_cache_shrink(cache); return (AE_OK); } @@ -1137,7 +1132,7 @@ acpi_status acpi_os_purge_cache(acpi_cache_t * cache) acpi_status acpi_os_delete_cache(acpi_cache_t * cache) { - (void)kmem_cache_destroy(cache); + kmem_cache_destroy(cache); return (AE_OK); } @@ -1161,25 +1156,85 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object) return (AE_OK); } -/******************************************************************************* +/****************************************************************************** * - * FUNCTION: acpi_os_acquire_object + * FUNCTION: acpi_os_validate_interface * - * PARAMETERS: Cache - Handle to cache object - * ReturnObject - Where the object is returned + * PARAMETERS: interface - Requested interface to be validated * - * RETURN: Status + * RETURN: AE_OK if interface is supported, AE_SUPPORT otherwise * - * DESCRIPTION: Get an object from the specified cache. If cache is empty, - * the object is allocated. + * DESCRIPTION: Match an interface string to the interfaces supported by the + * host. Strings originate from an AML call to the _OSI method. * - ******************************************************************************/ + *****************************************************************************/ + +acpi_status +acpi_os_validate_interface (char *interface) +{ + if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX)) + return AE_OK; + if (!strcmp("Linux", interface)) { + printk(KERN_WARNING PREFIX + "System BIOS is requesting _OSI(Linux)\n"); + printk(KERN_WARNING PREFIX + "If \"acpi_osi=Linux\" works better,\n" + "Please send dmidecode " + "to linux-acpi@vger.kernel.org\n"); + if(osi_linux) + return AE_OK; + } + return AE_SUPPORT; +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_validate_address + * + * PARAMETERS: space_id - ACPI space ID + * address - Physical address + * length - Address length + * + * RETURN: AE_OK if address/length is valid for the space_id. Otherwise, + * should return AE_AML_ILLEGAL_ADDRESS. + * + * DESCRIPTION: Validate a system address via the host OS. Used to validate + * the addresses accessed by AML operation regions. + * + *****************************************************************************/ -void *acpi_os_acquire_object(acpi_cache_t * cache) +acpi_status +acpi_os_validate_address ( + u8 space_id, + acpi_physical_address address, + acpi_size length) +{ + + return AE_OK; +} + +#ifdef CONFIG_DMI +static int dmi_osi_linux(struct dmi_system_id *d) { - void *object = kmem_cache_alloc(cache, GFP_KERNEL); - WARN_ON(!object); - return object; + printk(KERN_NOTICE "%s detected: enabling _OSI(Linux)\n", d->ident); + enable_osi_linux(1); + return 0; } +static struct dmi_system_id acpi_osl_dmi_table[] __initdata = { + /* + * Boxes that need _OSI(Linux) + */ + { + .callback = dmi_osi_linux, + .ident = "Intel Napa CRB", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_BOARD_NAME, "MPAD-MSAE Customer Reference Boards"), + }, + }, + {} +}; +#endif /* CONFIG_DMI */ + #endif