linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / acpi / osl.c
index 507f051..ac5bbae 100644 (file)
@@ -25,6 +25,7 @@
  *
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -135,14 +136,32 @@ 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)
 {
        if (efi_enabled) {
                addr->pointer_type = ACPI_PHYSICAL_POINTER;
-               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;
+               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);
                else {
                        printk(KERN_ERR PREFIX
                               "System description tables not found\n");
@@ -163,14 +182,22 @@ acpi_status
 acpi_os_map_memory(acpi_physical_address phys, acpi_size size,
                   void __iomem ** virt)
 {
-       if (phys > ULONG_MAX) {
-               printk(KERN_ERR PREFIX "Cannot map memory that high\n");
-               return AE_BAD_PARAMETER;
+       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);
        }
-       /*
-        * ioremap checks to ensure this is in reserved space
-        */
-       *virt = ioremap((unsigned long)phys, size);
 
        if (!*virt)
                return AE_NO_MEMORY;
@@ -262,7 +289,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, IRQF_SHARED, "acpi", acpi_irq)) {
+       if (request_irq(irq, acpi_irq, SA_SHIRQ, "acpi", acpi_irq)) {
                printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq);
                return AE_NOT_ACQUIRED;
        }
@@ -382,8 +409,18 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
 {
        u32 dummy;
        void __iomem *virt_addr;
+       int iomem = 0;
 
-       virt_addr = ioremap(phys_addr, width);
+       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);
        if (!value)
                value = &dummy;
 
@@ -401,7 +438,10 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
                BUG();
        }
 
-       iounmap(virt_addr);
+       if (efi_enabled) {
+               if (iomem)
+                       iounmap(virt_addr);
+       }
 
        return AE_OK;
 }
@@ -410,8 +450,18 @@ acpi_status
 acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
 {
        void __iomem *virt_addr;
+       int iomem = 0;
 
-       virt_addr = ioremap(phys_addr, width);
+       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);
 
        switch (width) {
        case 8:
@@ -427,7 +477,8 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
                BUG();
        }
 
-       iounmap(virt_addr);
+       if (iomem)
+               iounmap(virt_addr);
 
        return AE_OK;
 }
@@ -568,36 +619,23 @@ static void acpi_os_execute_deferred(void *context)
 {
        struct acpi_os_dpc *dpc = NULL;
 
+       ACPI_FUNCTION_TRACE("os_execute_deferred");
 
        dpc = (struct acpi_os_dpc *)context;
        if (!dpc) {
-               printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
-               return;
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid (NULL) context.\n"));
+               return_VOID;
        }
 
        dpc->function(dpc->context);
 
        kfree(dpc);
 
-       return;
+       return_VOID;
 }
 
-/*******************************************************************************
- *
- * 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_status
+acpi_os_queue_for_execution(u32 priority,
                            acpi_osd_exec_callback function, void *context)
 {
        acpi_status status = AE_OK;
@@ -646,7 +684,7 @@ acpi_status acpi_os_execute(acpi_execute_type type,
        return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_os_execute);
+EXPORT_SYMBOL(acpi_os_queue_for_execution);
 
 void acpi_os_wait_events_complete(void *context)
 {
@@ -658,19 +696,35 @@ EXPORT_SYMBOL(acpi_os_wait_events_complete);
 /*
  * Allocate the memory for a spinlock and initialize it.
  */
-acpi_status acpi_os_create_lock(acpi_spinlock * handle)
+acpi_status acpi_os_create_lock(acpi_handle * out_handle)
 {
-       spin_lock_init(*handle);
+       spinlock_t *lock_ptr;
 
-       return AE_OK;
+       ACPI_FUNCTION_TRACE("os_create_lock");
+
+       lock_ptr = acpi_os_allocate(sizeof(spinlock_t));
+
+       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);
 }
 
 /*
  * Deallocate the memory for a spinlock.
  */
-void acpi_os_delete_lock(acpi_spinlock handle)
+void acpi_os_delete_lock(acpi_handle handle)
 {
-       return;
+       ACPI_FUNCTION_TRACE("os_create_lock");
+
+       ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting spinlock[%p].\n", handle));
+
+       acpi_os_free(handle);
+
+       return_VOID;
 }
 
 acpi_status
@@ -678,10 +732,11 @@ 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 AE_NO_MEMORY;
+               return_ACPI_STATUS(AE_NO_MEMORY);
        memset(sem, 0, sizeof(struct semaphore));
 
        sema_init(sem, initial_units);
@@ -691,7 +746,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 AE_OK;
+       return_ACPI_STATUS(AE_OK);
 }
 
 EXPORT_SYMBOL(acpi_os_create_semaphore);
@@ -707,16 +762,17 @@ acpi_status acpi_os_delete_semaphore(acpi_handle handle)
 {
        struct semaphore *sem = (struct semaphore *)handle;
 
+       ACPI_FUNCTION_TRACE("os_delete_semaphore");
 
        if (!sem)
-               return AE_BAD_PARAMETER;
+               return_ACPI_STATUS(AE_BAD_PARAMETER);
 
        ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle));
 
-       kfree(sem);
+       acpi_os_free(sem);
        sem = NULL;
 
-       return AE_OK;
+       return_ACPI_STATUS(AE_OK);
 }
 
 EXPORT_SYMBOL(acpi_os_delete_semaphore);
@@ -736,25 +792,19 @@ 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 AE_BAD_PARAMETER;
+               return_ACPI_STATUS(AE_BAD_PARAMETER);
 
        if (units > 1)
-               return AE_SUPPORT;
+               return_ACPI_STATUS(AE_SUPPORT);
 
        ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n",
                          handle, units, timeout));
 
-       /*
-        * 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;
+       if (in_atomic())
+               timeout = 0;
 
        switch (timeout) {
                /*
@@ -800,17 +850,17 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
        }
 
        if (ACPI_FAILURE(status)) {
-               ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
-                                 "Failed to acquire semaphore[%p|%d|%d], %s",
+               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]", handle,
+                                 "Acquired semaphore[%p|%d|%d]\n", handle,
                                  units, timeout));
        }
 
-       return status;
+       return_ACPI_STATUS(status);
 }
 
 EXPORT_SYMBOL(acpi_os_wait_semaphore);
@@ -822,19 +872,20 @@ 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 AE_BAD_PARAMETER;
+               return_ACPI_STATUS(AE_BAD_PARAMETER);
 
        if (units > 1)
-               return AE_SUPPORT;
+               return_ACPI_STATUS(AE_SUPPORT);
 
        ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle,
                          units));
 
        up(sem);
 
-       return AE_OK;
+       return_ACPI_STATUS(AE_OK);
 }
 
 EXPORT_SYMBOL(acpi_os_signal_semaphore);
@@ -879,6 +930,14 @@ u8 acpi_os_writable(void *ptr, acpi_size len)
 }
 #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) {
@@ -1003,10 +1062,10 @@ EXPORT_SYMBOL(max_cstate);
  * handle is a pointer to the spinlock_t.
  */
 
-acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp)
+acpi_cpu_flags acpi_os_acquire_lock(acpi_handle handle)
 {
        acpi_cpu_flags flags;
-       spin_lock_irqsave(lockp, flags);
+       spin_lock_irqsave((spinlock_t *) handle, flags);
        return flags;
 }
 
@@ -1014,9 +1073,9 @@ acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp)
  * Release a spinlock. See above.
  */
 
-void acpi_os_release_lock(acpi_spinlock lockp, acpi_cpu_flags flags)
+void acpi_os_release_lock(acpi_handle handle, acpi_cpu_flags flags)
 {
-       spin_unlock_irqrestore(lockp, flags);
+       spin_unlock_irqrestore((spinlock_t *) handle, flags);
 }
 
 #ifndef ACPI_USE_LOCAL_CACHE
@@ -1025,12 +1084,12 @@ void acpi_os_release_lock(acpi_spinlock lockp, acpi_cpu_flags flags)
  *
  * 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) <ignored>
- *              cache     - Where the new cache object is returned
+ * 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
  *
- * RETURN:      status
+ * RETURN:      Status
  *
  * DESCRIPTION: Create a cache object
  *
@@ -1040,10 +1099,7 @@ 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;
+       return AE_OK;
 }
 
 /*******************************************************************************
@@ -1103,52 +1159,25 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *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
+ * FUNCTION:    acpi_os_acquire_object
  *
- * PARAMETERS:  space_id             - ACPI space ID
- *              address             - Physical address
- *              length              - Address length
+ * PARAMETERS:  Cache           - Handle to cache object
+ *              ReturnObject    - Where the object is returned
  *
- * RETURN:      AE_OK if address/length is valid for the space_id. Otherwise,
- *              should return AE_AML_ILLEGAL_ADDRESS.
+ * RETURN:      Status
  *
- * DESCRIPTION: Validate a system address via the host OS. Used to validate
- *              the addresses accessed by AML operation regions.
+ * DESCRIPTION: Get an object from the specified cache.  If cache is empty,
+ *              the object is allocated.
  *
- *****************************************************************************/
+ ******************************************************************************/
 
-acpi_status
-acpi_os_validate_address (
-    u8                   space_id,
-    acpi_physical_address   address,
-    acpi_size               length)
+void *acpi_os_acquire_object(acpi_cache_t * cache)
 {
-
-    return AE_OK;
+       void *object = kmem_cache_alloc(cache, GFP_KERNEL);
+       WARN_ON(!object);
+       return object;
 }
 
-
 #endif