X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Facpi%2Fosl.c;h=57ae1e5cde0a2400f8f060d88d7024dd89ba6ba1;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=433fdd7016071611186cc9c07f71041f5882d8a2;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 433fdd701..57ae1e5cd 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -25,7 +25,7 @@ * */ -#include +#include #include #include #include @@ -39,56 +39,65 @@ #include #include #include +#include #include #include - #define _COMPONENT ACPI_OS_SERVICES -ACPI_MODULE_NAME ("osl") - +ACPI_MODULE_NAME("osl") #define PREFIX "ACPI: " - -struct acpi_os_dpc -{ - OSD_EXECUTION_CALLBACK function; - void *context; +struct acpi_os_dpc { + acpi_osd_exec_callback function; + void *context; + struct work_struct work; }; +#ifdef CONFIG_ACPI_CUSTOM_DSDT +#include CONFIG_ACPI_CUSTOM_DSDT_FILE +#endif #ifdef ENABLE_DEBUGGER #include + /* stuff for debugger support */ int acpi_in_debugger; +EXPORT_SYMBOL(acpi_in_debugger); + extern char line_buf[80]; -#endif /*ENABLE_DEBUGGER*/ +#endif /*ENABLE_DEBUGGER */ + +int acpi_specific_hotkey_enabled = TRUE; +EXPORT_SYMBOL(acpi_specific_hotkey_enabled); static unsigned int acpi_irq_irq; -static OSD_HANDLER acpi_irq_handler; +static acpi_osd_handler acpi_irq_handler; static void *acpi_irq_context; static struct workqueue_struct *kacpid_wq; -acpi_status -acpi_os_initialize(void) +acpi_status acpi_os_initialize(void) +{ + return AE_OK; +} + +acpi_status acpi_os_initialize1(void) { /* * Initialize PCI configuration space access, as we'll need to access * it while walking the namespace (bus 0 and root bridges w/ _BBNs). */ -#ifdef CONFIG_ACPI_PCI if (!raw_pci_ops) { - printk(KERN_ERR PREFIX "Access to PCI configuration space unavailable\n"); + printk(KERN_ERR PREFIX + "Access to PCI configuration space unavailable\n"); return AE_NULL_ENTRY; } -#endif kacpid_wq = create_singlethread_workqueue("kacpid"); BUG_ON(!kacpid_wq); return AE_OK; } -acpi_status -acpi_os_terminate(void) +acpi_status acpi_os_terminate(void) { if (acpi_irq_handler) { acpi_os_remove_interrupt_handler(acpi_irq_irq, @@ -100,8 +109,7 @@ acpi_os_terminate(void) return AE_OK; } -void -acpi_os_printf(const char *fmt,...) +void acpi_os_printf(const char *fmt, ...) { va_list args; va_start(args, fmt); @@ -109,11 +117,12 @@ acpi_os_printf(const char *fmt,...) va_end(args); } -void -acpi_os_vprintf(const char *fmt, va_list args) +EXPORT_SYMBOL(acpi_os_printf); + +void acpi_os_vprintf(const char *fmt, va_list args) { static char buffer[512]; - + vsprintf(buffer, fmt, args); #ifdef ENABLE_DEBUGGER @@ -127,36 +136,23 @@ acpi_os_vprintf(const char *fmt, va_list args) #endif } -void * -acpi_os_allocate(acpi_size size) -{ - return kmalloc(size, GFP_KERNEL); -} - -void -acpi_os_free(void *ptr) -{ - kfree(ptr); -} - -acpi_status -acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr) +acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr) { 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) + addr->pointer.physical = efi.acpi20; + else if (efi.acpi != EFI_INVALID_TABLE_ADDR) + addr->pointer.physical = efi.acpi; else { - printk(KERN_ERR PREFIX "System description tables not found\n"); + printk(KERN_ERR PREFIX + "System description tables not found\n"); return AE_NOT_FOUND; } } else { if (ACPI_FAILURE(acpi_find_root_pointer(flags, addr))) { - printk(KERN_ERR PREFIX "System description tables not found\n"); + printk(KERN_ERR PREFIX + "System description tables not found\n"); return AE_NOT_FOUND; } } @@ -165,63 +161,59 @@ acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr) } acpi_status -acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void **virt) +acpi_os_map_memory(acpi_physical_address phys, acpi_size size, + void __iomem ** virt) { - if (efi_enabled) { - if (EFI_MEMORY_WB & efi_mem_attributes(phys)) { - *virt = 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 AE_BAD_PARAMETER; } + /* + * ioremap checks to ensure this is in reserved space + */ + *virt = ioremap((unsigned long)phys, size); if (!*virt) return AE_NO_MEMORY; return AE_OK; } +EXPORT_SYMBOL_GPL(acpi_os_map_memory); -void -acpi_os_unmap_memory(void *virt, acpi_size size) +void acpi_os_unmap_memory(void __iomem * virt, acpi_size size) { iounmap(virt); } +EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); +#ifdef ACPI_FUTURE_USAGE acpi_status -acpi_os_get_physical_address(void *virt, acpi_physical_address *phys) +acpi_os_get_physical_address(void *virt, acpi_physical_address * phys) { - if(!phys || !virt) + if (!phys || !virt) return AE_BAD_PARAMETER; *phys = virt_to_phys(virt); return AE_OK; } +#endif #define ACPI_MAX_OVERRIDE_LEN 100 static char acpi_os_name[ACPI_MAX_OVERRIDE_LEN]; acpi_status -acpi_os_predefined_override (const struct acpi_predefined_names *init_val, - acpi_string *new_val) +acpi_os_predefined_override(const struct acpi_predefined_names *init_val, + acpi_string * new_val) { if (!init_val || !new_val) return AE_BAD_PARAMETER; *new_val = NULL; - if (!memcmp (init_val->name, "_OS_", 4) && strlen(acpi_os_name)) { - printk(KERN_INFO PREFIX "Overriding _OS definition %s\n", - acpi_os_name); + if (!memcmp(init_val->name, "_OS_", 4) && strlen(acpi_os_name)) { + printk(KERN_INFO PREFIX "Overriding _OS definition to '%s'\n", + acpi_os_name); *new_val = acpi_os_name; } @@ -229,24 +221,31 @@ acpi_os_predefined_override (const struct acpi_predefined_names *init_val, } acpi_status -acpi_os_table_override (struct acpi_table_header *existing_table, - struct acpi_table_header **new_table) +acpi_os_table_override(struct acpi_table_header * existing_table, + struct acpi_table_header ** new_table) { if (!existing_table || !new_table) return AE_BAD_PARAMETER; +#ifdef CONFIG_ACPI_CUSTOM_DSDT + if (strncmp(existing_table->signature, "DSDT", 4) == 0) + *new_table = (struct acpi_table_header *)AmlCode; + else + *new_table = NULL; +#else *new_table = NULL; +#endif 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; + return (*acpi_irq_handler) (acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE; } acpi_status -acpi_os_install_interrupt_handler(u32 gsi, OSD_HANDLER handler, void *context) +acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, + void *context) { unsigned int irq; @@ -264,7 +263,7 @@ acpi_os_install_interrupt_handler(u32 gsi, OSD_HANDLER handler, void *context) 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; } @@ -273,8 +272,7 @@ acpi_os_install_interrupt_handler(u32 gsi, OSD_HANDLER handler, void *context) return AE_OK; } -acpi_status -acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler) +acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) { if (irq) { free_irq(irq, acpi_irq); @@ -289,15 +287,14 @@ acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler) * Running in interpreter thread context, safe to sleep */ -void -acpi_os_sleep(u32 sec, u32 ms) +void acpi_os_sleep(acpi_integer ms) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ * sec + (ms * HZ) / 1000); + schedule_timeout_interruptible(msecs_to_jiffies(ms)); } -void -acpi_os_stall(u32 us) +EXPORT_SYMBOL(acpi_os_sleep); + +void acpi_os_stall(u32 us) { while (us) { u32 delay = 1000; @@ -310,27 +307,46 @@ acpi_os_stall(u32 us) } } -acpi_status -acpi_os_read_port( - acpi_io_address port, - u32 *value, - u32 width) +EXPORT_SYMBOL(acpi_os_stall); + +/* + * Support ACPI 3.0 AML Timer operand + * Returns 64-bit free-running, monotonically increasing timer + * with 100ns granularity + */ +u64 acpi_os_get_timer(void) +{ + static u64 t; + +#ifdef CONFIG_HPET + /* TBD: use HPET if available */ +#endif + +#ifdef CONFIG_X86_PM_TIMER + /* TBD: default to PM timer if HPET was not available */ +#endif + if (!t) + printk(KERN_ERR PREFIX "acpi_os_get_timer() TBD\n"); + + return ++t; +} + +acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width) { u32 dummy; if (!value) value = &dummy; - switch (width) - { + switch (width) { case 8: - *(u8*) value = inb(port); + *(u8 *) value = inb(port); break; case 16: - *(u16*) value = inw(port); + *(u16 *) value = inw(port); break; case 32: - *(u32*) value = inl(port); + *(u32 *) value = inl(port); break; default: BUG(); @@ -339,14 +355,11 @@ acpi_os_read_port( return AE_OK; } -acpi_status -acpi_os_write_port( - acpi_io_address port, - u32 value, - u32 width) +EXPORT_SYMBOL(acpi_os_read_port); + +acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width) { - switch (width) - { + switch (width) { case 8: outb(value, port); break; @@ -363,93 +376,66 @@ acpi_os_write_port( return AE_OK; } +EXPORT_SYMBOL(acpi_os_write_port); + acpi_status -acpi_os_read_memory( - acpi_physical_address phys_addr, - u32 *value, - u32 width) +acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width) { - u32 dummy; - void *virt_addr; - int iomem = 0; + u32 dummy; + void __iomem *virt_addr; - if (efi_enabled) { - if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) { - virt_addr = phys_to_virt(phys_addr); - } else { - iomem = 1; - virt_addr = ioremap(phys_addr, width); - } - } else - virt_addr = phys_to_virt(phys_addr); + virt_addr = ioremap(phys_addr, width); if (!value) value = &dummy; switch (width) { case 8: - *(u8*) value = *(u8*) virt_addr; + *(u8 *) value = readb(virt_addr); break; case 16: - *(u16*) value = *(u16*) virt_addr; + *(u16 *) value = readw(virt_addr); break; case 32: - *(u32*) value = *(u32*) virt_addr; + *(u32 *) value = readl(virt_addr); break; default: BUG(); } - if (efi_enabled) { - if (iomem) - iounmap(virt_addr); - } + iounmap(virt_addr); return AE_OK; } acpi_status -acpi_os_write_memory( - acpi_physical_address phys_addr, - u32 value, - u32 width) +acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width) { - void *virt_addr; - int iomem = 0; + void __iomem *virt_addr; - if (efi_enabled) { - if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) { - virt_addr = phys_to_virt(phys_addr); - } else { - iomem = 1; - virt_addr = ioremap(phys_addr, width); - } - } else - virt_addr = phys_to_virt(phys_addr); + virt_addr = ioremap(phys_addr, width); switch (width) { case 8: - *(u8*) virt_addr = value; + writeb(value, virt_addr); break; case 16: - *(u16*) virt_addr = value; + writew(value, virt_addr); break; case 32: - *(u32*) virt_addr = value; + writel(value, virt_addr); break; default: BUG(); } - if (iomem) - iounmap(virt_addr); + iounmap(virt_addr); return AE_OK; } -#ifdef CONFIG_ACPI_PCI - acpi_status -acpi_os_read_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, void *value, u32 width) +acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, + void *value, u32 width) { int result, size; @@ -470,15 +456,20 @@ acpi_os_read_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, void *value return AE_ERROR; } + BUG_ON(!raw_pci_ops); + result = raw_pci_ops->read(pci_id->segment, pci_id->bus, - PCI_DEVFN(pci_id->device, pci_id->function), - reg, size, value); + PCI_DEVFN(pci_id->device, pci_id->function), + reg, size, value); return (result ? AE_ERROR : AE_OK); } +EXPORT_SYMBOL(acpi_os_read_pci_configuration); + acpi_status -acpi_os_write_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, acpi_integer value, u32 width) +acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, + acpi_integer value, u32 width) { int result, size; @@ -496,57 +487,65 @@ acpi_os_write_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, acpi_integ return AE_ERROR; } + BUG_ON(!raw_pci_ops); + result = raw_pci_ops->write(pci_id->segment, pci_id->bus, - PCI_DEVFN(pci_id->device, pci_id->function), - reg, size, value); + PCI_DEVFN(pci_id->device, pci_id->function), + reg, size, value); return (result ? AE_ERROR : AE_OK); } /* TODO: Change code to take advantage of driver model more */ -void -acpi_os_derive_pci_id_2 ( - acpi_handle rhandle, /* upper bound */ - acpi_handle chandle, /* current node */ - struct acpi_pci_id **id, - int *is_bridge, - u8 *bus_number) +static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */ + acpi_handle chandle, /* current node */ + struct acpi_pci_id **id, + int *is_bridge, u8 * bus_number) { - acpi_handle handle; - struct acpi_pci_id *pci_id = *id; - acpi_status status; - unsigned long temp; - acpi_object_type type; - u8 tu8; + acpi_handle handle; + struct acpi_pci_id *pci_id = *id; + acpi_status status; + unsigned long temp; + acpi_object_type type; + u8 tu8; acpi_get_parent(chandle, &handle); if (handle != rhandle) { - acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge, bus_number); + acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge, + bus_number); status = acpi_get_type(handle, &type); - if ( (ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE) ) + if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE)) return; - status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &temp); + status = + acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, + &temp); if (ACPI_SUCCESS(status)) { - pci_id->device = ACPI_HIWORD (ACPI_LODWORD (temp)); - pci_id->function = ACPI_LOWORD (ACPI_LODWORD (temp)); + pci_id->device = ACPI_HIWORD(ACPI_LODWORD(temp)); + pci_id->function = ACPI_LOWORD(ACPI_LODWORD(temp)); if (*is_bridge) pci_id->bus = *bus_number; /* any nicer way to get bus number of bridge ? */ - status = acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8, 8); - if (ACPI_SUCCESS(status) && - ((tu8 & 0x7f) == 1 || (tu8 & 0x7f) == 2)) { - status = acpi_os_read_pci_configuration(pci_id, 0x18, &tu8, 8); + status = + acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8, + 8); + if (ACPI_SUCCESS(status) + && ((tu8 & 0x7f) == 1 || (tu8 & 0x7f) == 2)) { + status = + acpi_os_read_pci_configuration(pci_id, 0x18, + &tu8, 8); if (!ACPI_SUCCESS(status)) { /* Certainly broken... FIX ME */ return; } *is_bridge = 1; pci_id->bus = tu8; - status = acpi_os_read_pci_configuration(pci_id, 0x19, &tu8, 8); + status = + acpi_os_read_pci_configuration(pci_id, 0x19, + &tu8, 8); if (ACPI_SUCCESS(status)) { *bus_number = tu8; } @@ -556,11 +555,9 @@ acpi_os_derive_pci_id_2 ( } } -void -acpi_os_derive_pci_id ( - acpi_handle rhandle, /* upper bound */ - acpi_handle chandle, /* current node */ - struct acpi_pci_id **id) +void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */ + acpi_handle chandle, /* current node */ + struct acpi_pci_id **id) { int is_bridge = 1; u8 bus_number = (*id)->bus; @@ -568,224 +565,128 @@ acpi_os_derive_pci_id ( acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number); } -#else /*!CONFIG_ACPI_PCI*/ - -acpi_status -acpi_os_write_pci_configuration ( - struct acpi_pci_id *pci_id, - u32 reg, - acpi_integer value, - u32 width) -{ - return (AE_SUPPORT); -} - -acpi_status -acpi_os_read_pci_configuration ( - struct acpi_pci_id *pci_id, - u32 reg, - void *value, - u32 width) -{ - return (AE_SUPPORT); -} - -void -acpi_os_derive_pci_id ( - acpi_handle rhandle, /* upper bound */ - acpi_handle chandle, /* current node */ - struct acpi_pci_id **id) -{ -} - -#endif /*CONFIG_ACPI_PCI*/ - -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); - ACPI_FUNCTION_TRACE ("os_execute_deferred"); - - 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, - OSD_EXECUTION_CALLBACK function, - void *context) +/******************************************************************************* + * + * 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_status status = AE_OK; + struct acpi_os_dpc *dpc; - ACPI_FUNCTION_TRACE ("os_queue_for_execution"); + ACPI_FUNCTION_TRACE("os_queue_for_execution"); - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); + 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_ACPI_STATUS(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); + 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, "Call to queue_work() failed.\n")); + 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; } - return_ACPI_STATUS (status); + return_ACPI_STATUS(status); } -void -acpi_os_wait_events_complete( - void *context) +EXPORT_SYMBOL(acpi_os_execute); + +void acpi_os_wait_events_complete(void *context) { flush_workqueue(kacpid_wq); } +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(lock_ptr); + spin_lock_init(*handle); - 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; } -/* - * 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. - */ -void -acpi_os_acquire_lock ( - acpi_handle handle, - u32 flags) -{ - ACPI_FUNCTION_TRACE ("os_acquire_lock"); - - ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Acquiring spinlock[%p] from %s level\n", handle, - ((flags & ACPI_NOT_ISR) ? "non-interrupt" : "interrupt"))); - - if (flags & ACPI_NOT_ISR) - ACPI_DISABLE_IRQS(); - - spin_lock((spinlock_t *)handle); - - return_VOID; -} - - -/* - * Release a spinlock. See above. - */ -void -acpi_os_release_lock ( - acpi_handle handle, - u32 flags) -{ - ACPI_FUNCTION_TRACE ("os_release_lock"); - - ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Releasing spinlock[%p] from %s level\n", handle, - ((flags & ACPI_NOT_ISR) ? "non-interrupt" : "interrupt"))); - - spin_unlock((spinlock_t *)handle); - - if (flags & ACPI_NOT_ISR) - ACPI_ENABLE_IRQS(); - - return_VOID; -} - - acpi_status -acpi_os_create_semaphore( - u32 max_units, - u32 initial_units, - acpi_handle *handle) +acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle) { - struct semaphore *sem = NULL; + 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); - *handle = (acpi_handle*)sem; + *handle = (acpi_handle *) sem; - ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Creating semaphore[%p|%d].\n", *handle, initial_units)); + 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); /* * TODO: A better way to delete semaphores? Linux doesn't have a @@ -794,24 +695,23 @@ acpi_os_create_semaphore( * we at least check for blocked threads and signal/cancel them? */ -acpi_status -acpi_os_delete_semaphore( - acpi_handle handle) +acpi_status acpi_os_delete_semaphore(acpi_handle handle) { - struct semaphore *sem = (struct semaphore*) 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_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle)); - acpi_os_free(sem); sem = NULL; + kfree(sem); + sem = NULL; - return_ACPI_STATUS (AE_OK); + return AE_OK; } +EXPORT_SYMBOL(acpi_os_delete_semaphore); /* * TODO: The kernel doesn't have a 'down_timeout' function -- had to @@ -822,31 +722,33 @@ acpi_os_delete_semaphore( * * TODO: Support for units > 1? */ -acpi_status -acpi_os_wait_semaphore( - acpi_handle handle, - u32 units, - u16 timeout) +acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) { - acpi_status status = AE_OK; - struct semaphore *sem = (struct semaphore*)handle; - int ret = 0; + acpi_status status = AE_OK; + 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)); + 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) - { + switch (timeout) { /* * No Wait: * -------- @@ -854,8 +756,8 @@ acpi_os_wait_semaphore( * acquire the semaphore if available otherwise return AE_TIME * (a.k.a. 'would block'). */ - case 0: - if(down_trylock(sem)) + case 0: + if (down_trylock(sem)) status = AE_TIME; break; @@ -863,7 +765,7 @@ acpi_os_wait_semaphore( * Wait Indefinitely: * ------------------ */ - case ACPI_WAIT_FOREVER: + case ACPI_WAIT_FOREVER: down(sem); break; @@ -871,19 +773,18 @@ acpi_os_wait_semaphore( * Wait w/ Timeout: * ---------------- */ - default: + default: // TODO: A better timeout algorithm? { int i = 0; - static const int quantum_ms = 1000/HZ; + static const int quantum_ms = 1000 / HZ; ret = down_trylock(sem); - for (i = timeout; (i > 0 && ret < 0); i -= quantum_ms) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); + for (i = timeout; (i > 0 && ret != 0); i -= quantum_ms) { + schedule_timeout_interruptible(1); ret = down_trylock(sem); } - + if (ret != 0) status = AE_TIME; } @@ -891,44 +792,47 @@ acpi_os_wait_semaphore( } if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Failed to acquire semaphore[%p|%d|%d], %s\n", - handle, units, timeout, acpi_format_exception(status))); - } - else { - ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Acquired semaphore[%p|%d|%d]\n", handle, units, timeout)); + 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]", handle, + units, timeout)); } - return_ACPI_STATUS (status); + return status; } +EXPORT_SYMBOL(acpi_os_wait_semaphore); /* * TODO: Support for units > 1? */ -acpi_status -acpi_os_signal_semaphore( - acpi_handle handle, - u32 units) +acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units) { - struct semaphore *sem = (struct semaphore *) handle; + 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)); + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle, + units)); up(sem); - return_ACPI_STATUS (AE_OK); + return AE_OK; } -u32 -acpi_os_get_line(char *buffer) +EXPORT_SYMBOL(acpi_os_signal_semaphore); + +#ifdef ACPI_FUTURE_USAGE +u32 acpi_os_get_line(char *buffer) { #ifdef ENABLE_DEBUGGER @@ -945,51 +849,44 @@ acpi_os_get_line(char *buffer) return 0; } +#endif /* ACPI_FUTURE_USAGE */ /* Assumes no unreadable holes inbetween */ -u8 -acpi_os_readable(void *ptr, acpi_size len) +u8 acpi_os_readable(void *ptr, acpi_size len) { -#if defined(__i386__) || defined(__x86_64__) +#if defined(__i386__) || defined(__x86_64__) char tmp; - return !__get_user(tmp, (char *)ptr) && !__get_user(tmp, (char *)ptr + len - 1); + return !__get_user(tmp, (char __user *)ptr) + && !__get_user(tmp, (char __user *)ptr + len - 1); #endif return 1; } -u8 -acpi_os_writable(void *ptr, acpi_size len) +#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) +acpi_status acpi_os_signal(u32 function, void *info) { - if (!in_atomic()) - return current->pid; - - return 0; -} - -acpi_status -acpi_os_signal ( - u32 function, - void *info) -{ - switch (function) - { + switch (function) { case ACPI_SIGNAL_FATAL: printk(KERN_ERR PREFIX "Fatal opcode executed\n"); break; case ACPI_SIGNAL_BREAKPOINT: - { - char *bp_info = (char*) info; - - printk(KERN_ERR "ACPI breakpoint: %s\n", bp_info); - } + /* + * AML Breakpoint + * ACPI spec. says to treat it as a NOP unless + * you are debugging. So if/when we integrate + * AML debugger into the kernel debugger its + * hook will go here. But until then it is + * not useful to print anything on breakpoints. + */ + break; default: break; } @@ -997,11 +894,12 @@ acpi_os_signal ( return AE_OK; } -int __init -acpi_os_name_setup(char *str) +EXPORT_SYMBOL(acpi_os_signal); + +static int __init acpi_os_name_setup(char *str) { char *p = acpi_os_name; - int count = ACPI_MAX_OVERRIDE_LEN-1; + int count = ACPI_MAX_OVERRIDE_LEN - 1; if (!str || !*str) return 0; @@ -1017,7 +915,7 @@ acpi_os_name_setup(char *str) *p = 0; return 1; - + } __setup("acpi_os_name=", acpi_os_name_setup); @@ -1027,16 +925,15 @@ __setup("acpi_os_name=", acpi_os_name_setup); * empty string disables _OSI * TBD additional string adds to _OSI */ -int __init -acpi_osi_setup(char *str) +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 - { + } else { /* TBD */ - printk(KERN_ERR PREFIX "_OSI additional string ignored -- %s\n", str); + printk(KERN_ERR PREFIX "_OSI additional string ignored -- %s\n", + str); } return 1; @@ -1045,8 +942,7 @@ acpi_osi_setup(char *str) __setup("acpi_osi=", acpi_osi_setup); /* enable serialization to combat AE_ALREADY_EXISTS errors */ -int __init -acpi_serialize_setup(char *str) +static int __init acpi_serialize_setup(char *str) { printk(KERN_INFO PREFIX "serialize enabled\n"); @@ -1066,15 +962,185 @@ __setup("acpi_serialize", acpi_serialize_setup); * Run-time events on the same GPE this flag is available * to tell Linux to keep the wake-time GPEs enabled at run-time. */ -static int __init -acpi_leave_gpes_disabled_setup(char *str) +static int __init acpi_wake_gpes_always_on_setup(char *str) { - printk(KERN_INFO PREFIX "leave wake GPEs disabled\n"); + printk(KERN_INFO PREFIX "wake GPEs not disabled\n"); + + acpi_gbl_leave_wake_gpes_disabled = FALSE; - acpi_gbl_leave_wake_gpes_disabled = TRUE; + return 1; +} +__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_leave_gpes_disabled", acpi_leave_gpes_disabled_setup); +__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. + */ +unsigned int max_cstate = ACPI_PROCESSOR_MAX_POWER; + +EXPORT_SYMBOL(max_cstate); + +/* + * Acquire a spinlock. + * + * handle is a pointer to the spinlock_t. + */ + +acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp) +{ + acpi_cpu_flags flags; + spin_lock_irqsave(lockp, flags); + return flags; +} + +/* + * Release a spinlock. See above. + */ + +void acpi_os_release_lock(acpi_spinlock lockp, acpi_cpu_flags flags) +{ + spin_unlock_irqrestore(lockp, flags); +} + +#ifndef ACPI_USE_LOCAL_CACHE + +/******************************************************************************* + * + * FUNCTION: acpi_os_create_cache + * + * 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 + * + * DESCRIPTION: Create a cache object + * + ******************************************************************************/ + +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); + if (*cache == NULL) + return AE_ERROR; + else + return AE_OK; +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_purge_cache + * + * PARAMETERS: Cache - Handle to cache object + * + * RETURN: Status + * + * DESCRIPTION: Free all objects within the requested cache. + * + ******************************************************************************/ + +acpi_status acpi_os_purge_cache(acpi_cache_t * cache) +{ + kmem_cache_shrink(cache); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_delete_cache + * + * PARAMETERS: Cache - Handle to cache object + * + * RETURN: Status + * + * DESCRIPTION: Free all objects within the requested cache and delete the + * cache object. + * + ******************************************************************************/ + +acpi_status acpi_os_delete_cache(acpi_cache_t * cache) +{ + kmem_cache_destroy(cache); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_release_object + * + * PARAMETERS: Cache - Handle to cache object + * Object - The object to be released + * + * RETURN: None + * + * DESCRIPTION: Release an object to the specified cache. If cache is full, + * the object is deleted. + * + ******************************************************************************/ + +acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object) +{ + kmem_cache_free(cache, object); + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_validate_interface + * + * PARAMETERS: interface - Requested interface to be validated + * + * RETURN: AE_OK if interface is supported, AE_SUPPORT otherwise + * + * 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) +{ + 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. + * + *****************************************************************************/ + +acpi_status +acpi_os_validate_address ( + u8 space_id, + acpi_physical_address address, + acpi_size length) +{ + + return AE_OK; +} + + +#endif