ACPI: ec: Rename gpe_bit to gpe
[pandora-kernel.git] / drivers / acpi / ec.c
index e6d4b08..722acaf 100644 (file)
@@ -46,6 +46,9 @@ ACPI_MODULE_NAME("acpi_ec")
 #define ACPI_EC_DEVICE_NAME            "Embedded Controller"
 #define ACPI_EC_FILE_INFO              "info"
 
+#undef PREFIX
+#define PREFIX                         "ACPI: EC: "
+
 /* EC status register */
 #define ACPI_EC_FLAG_OBF       0x01    /* Output buffer full */
 #define ACPI_EC_FLAG_IBF       0x02    /* Input buffer full */
@@ -65,10 +68,10 @@ enum {
        ACPI_EC_EVENT_IBF_0,            /* Input buffer empty */
 };
 
-#define ACPI_EC_DELAY          50      /* Wait 50ms max. during EC ops */
+#define ACPI_EC_DELAY          500     /* Wait 500ms max. during EC ops */
 #define ACPI_EC_UDELAY_GLK     1000    /* Wait 1ms max. to get global lock */
 #define ACPI_EC_UDELAY         100     /* Poll @ 100us increments */
-#define ACPI_EC_UDELAY_COUNT   1000    /* Wait 10ms max. during EC ops */
+#define ACPI_EC_UDELAY_COUNT   1000    /* Wait 100ms max. during EC ops */
 
 enum {
        EC_INTR = 1,    /* Output buffer full */
@@ -96,12 +99,12 @@ static struct acpi_driver acpi_ec_driver = {
 struct acpi_ec {
        acpi_handle handle;
        unsigned long uid;
-       unsigned long gpe_bit;
+       unsigned long gpe;
        unsigned long command_addr;
        unsigned long data_addr;
        unsigned long global_lock;
-       struct semaphore sem;
-       unsigned int expect_event;
+       struct mutex lock;
+       atomic_t query_pending;
        atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */
        wait_queue_head_t wait;
 } *ec_ecdt;
@@ -134,8 +137,9 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
        outb(data, ec->data_addr);
 }
 
-static int acpi_ec_check_status(u8 status, u8 event)
+static int acpi_ec_check_status(struct acpi_ec *ec, u8 event)
 {
+       u8 status = acpi_ec_read_status(ec);
        switch (event) {
        case ACPI_EC_EVENT_OBF_1:
                if (status & ACPI_EC_FLAG_OBF)
@@ -154,34 +158,25 @@ static int acpi_ec_check_status(u8 status, u8 event)
 
 static int acpi_ec_wait(struct acpi_ec *ec, u8 event)
 {
-       int i = (acpi_ec_mode == EC_POLL) ? ACPI_EC_UDELAY_COUNT : 0;
-       long time_left;
-
-       ec->expect_event = event;
-       if (acpi_ec_check_status(acpi_ec_read_status(ec), event)) {
-               ec->expect_event = 0;
-               return 0;
-       }
-
-       do {
-               if (acpi_ec_mode == EC_POLL) {
-                       udelay(ACPI_EC_UDELAY);
-               } else {
-                       time_left = wait_event_timeout(ec->wait,
-                                   !ec->expect_event,
-                                   msecs_to_jiffies(ACPI_EC_DELAY));
-                       if (time_left > 0) {
-                               ec->expect_event = 0;
+       if (acpi_ec_mode == EC_POLL) {
+               int i;
+               for (i = 0; i < ACPI_EC_UDELAY_COUNT; ++i) {
+                       if (acpi_ec_check_status(ec, event))
                                return 0;
-                       }
+                       udelay(ACPI_EC_UDELAY);
                }
-               if (acpi_ec_check_status(acpi_ec_read_status(ec), event)) {
-                       ec->expect_event = 0;
+       } else {
+               if (wait_event_timeout(ec->wait,
+                                      acpi_ec_check_status(ec, event),
+                                      msecs_to_jiffies(ACPI_EC_DELAY)) ||
+                   acpi_ec_check_status(ec, event)) {
                        return 0;
+               } else {
+                       printk(KERN_ERR PREFIX "acpi_ec_wait timeout,"
+                              " status = %d, expect_event = %d\n",
+                            acpi_ec_read_status(ec), event);
                }
-       } while (--i > 0);
-
-       ec->expect_event = 0;
+       }
 
        return -ETIME;
 }
@@ -242,32 +237,43 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
                                        const u8 *wdata, unsigned wdata_len,
                                        u8 *rdata, unsigned rdata_len)
 {
-       int result;
+       int result = 0;
 
        acpi_ec_write_cmd(ec, command);
 
        for (; wdata_len > 0; wdata_len --) {
                result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
-               if (result)
-                       return result;
+               if (result) {
+                       printk(KERN_ERR PREFIX "write_cmd timeout, command = %d\n",
+                            command);
+                       goto end;
+               }
                acpi_ec_write_data(ec, *(wdata++));
        }
 
-       if (command == ACPI_EC_COMMAND_WRITE) {
+       if (!rdata_len) {
                result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
-               if (result)
-                       return result;
+               if (result) {
+                       printk(KERN_ERR PREFIX "finish-write timeout, command = %d\n",
+                            command);
+                       goto end;
+               }
+       } else if (command == ACPI_EC_COMMAND_QUERY) {
+               atomic_set(&ec->query_pending, 0);
        }
 
        for (; rdata_len > 0; rdata_len --) {
                result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1);
-               if (result)
-                       return result;
+               if (result) {
+                       printk(KERN_ERR PREFIX "read timeout, command = %d\n",
+                            command);
+                       goto end;
+               }
 
                *(rdata++) = acpi_ec_read_data(ec);
        }
-
-       return 0;
+      end:
+       return result;
 }
 
 static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
@@ -288,7 +294,10 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
                if (ACPI_FAILURE(status))
                        return -ENODEV;
        }
-       down(&ec->sem);
+       mutex_lock(&ec->lock);
+
+       /* Make sure GPE is enabled before doing transaction */
+       acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
 
        status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
        if (status) {
@@ -301,7 +310,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
                                               rdata, rdata_len);
 
 end:
-       up(&ec->sem);
+       mutex_unlock(&ec->lock);
 
        if (ec->global_lock)
                acpi_release_global_lock(glk);
@@ -415,36 +424,20 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
                                 Event Management
    -------------------------------------------------------------------------- */
 
-struct acpi_ec_query_data {
-       acpi_handle handle;
-       u8 data;
-};
-
 static void acpi_ec_gpe_query(void *ec_cxt)
 {
        struct acpi_ec *ec = (struct acpi_ec *)ec_cxt;
        u8 value = 0;
-       static char object_name[8];
+       char object_name[8];
 
-       if (!ec)
-               goto end;
-
-       value = acpi_ec_read_status(ec);
-
-       if (!(value & ACPI_EC_FLAG_SCI))
-               goto end;
-
-       if (acpi_ec_query(ec, &value))
-               goto end;
+       if (!ec || acpi_ec_query(ec, &value))
+               return;
 
        snprintf(object_name, 8, "_Q%2.2X", value);
 
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name));
+       printk(KERN_INFO PREFIX "evaluating %s\n", object_name);
 
        acpi_evaluate_object(ec->handle, object_name, NULL, NULL);
-
-      end:
-       acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
 }
 
 static u32 acpi_ec_gpe_handler(void *data)
@@ -453,22 +446,17 @@ static u32 acpi_ec_gpe_handler(void *data)
        u8 value;
        struct acpi_ec *ec = (struct acpi_ec *)data;
 
-       acpi_clear_gpe(NULL, ec->gpe_bit, ACPI_ISR);
-       value = acpi_ec_read_status(ec);
 
        if (acpi_ec_mode == EC_INTR) {
-               if (acpi_ec_check_status(value, ec->expect_event)) {
-                       ec->expect_event = 0;
-                       wake_up(&ec->wait);
-               }
+               wake_up(&ec->wait);
        }
 
-       if (value & ACPI_EC_FLAG_SCI) {
+       value = acpi_ec_read_status(ec);
+       if ((value & ACPI_EC_FLAG_SCI) && !atomic_read(&ec->query_pending)) {
+               atomic_set(&ec->query_pending, 1);
                status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec);
-               return status == AE_OK ?
-                   ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
        }
-       acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_ISR);
+
        return status == AE_OK ?
            ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
 }
@@ -575,14 +563,14 @@ static int acpi_ec_read_info(struct seq_file *seq, void *offset)
        if (!ec)
                goto end;
 
-       seq_printf(seq, "gpe bit:                 0x%02x\n",
-                  (u32) ec->gpe_bit);
+       seq_printf(seq, "gpe:                 0x%02x\n",
+                  (u32) ec->gpe);
        seq_printf(seq, "ports:                   0x%02x, 0x%02x\n",
                   (u32) ec->command_addr,
                   (u32) ec->data_addr);
        seq_printf(seq, "use global lock:         %s\n",
                   ec->global_lock ? "yes" : "no");
-       acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+       acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
 
       end:
        return 0;
@@ -659,7 +647,8 @@ static int acpi_ec_add(struct acpi_device *device)
 
        ec->handle = device->handle;
        ec->uid = -1;
-       init_MUTEX(&ec->sem);
+       mutex_init(&ec->lock);
+       atomic_set(&ec->query_pending, 0);
        if (acpi_ec_mode == EC_INTR) {
                atomic_set(&ec->leaving_burst, 1);
                init_waitqueue_head(&ec->wait);
@@ -679,7 +668,7 @@ static int acpi_ec_add(struct acpi_device *device)
                                                  ACPI_ADR_SPACE_EC,
                                                  &acpi_ec_space_handler);
 
-               acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit,
+               acpi_remove_gpe_handler(NULL, ec_ecdt->gpe,
                                        &acpi_ec_gpe_handler);
 
                kfree(ec_ecdt);
@@ -689,7 +678,7 @@ static int acpi_ec_add(struct acpi_device *device)
        /* TODO: Add support for _GPE returning a package */
        status =
            acpi_evaluate_integer(ec->handle, "_GPE", NULL,
-                                 &ec->gpe_bit);
+                                 &ec->gpe);
        if (ACPI_FAILURE(status)) {
                ACPI_EXCEPTION((AE_INFO, status, "Obtaining GPE bit assignment"));
                result = -ENODEV;
@@ -702,7 +691,7 @@ static int acpi_ec_add(struct acpi_device *device)
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s [%s] (gpe %d) interrupt mode.",
               acpi_device_name(device), acpi_device_bid(device),
-              (u32) ec->gpe_bit));
+              (u32) ec->gpe));
 
        if (!first_ec)
                first_ec = device;
@@ -782,26 +771,26 @@ static int acpi_ec_start(struct acpi_device *device)
        }
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx",
-                         ec->gpe_bit, ec->command_addr, ec->data_addr));
+                         ec->gpe, ec->command_addr, ec->data_addr));
 
        /*
         * Install GPE handler
         */
-       status = acpi_install_gpe_handler(NULL, ec->gpe_bit,
+       status = acpi_install_gpe_handler(NULL, ec->gpe,
                                          ACPI_GPE_EDGE_TRIGGERED,
                                          &acpi_ec_gpe_handler, ec);
        if (ACPI_FAILURE(status)) {
                return -ENODEV;
        }
-       acpi_set_gpe_type(NULL, ec->gpe_bit, ACPI_GPE_TYPE_RUNTIME);
-       acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+       acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
+       acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
 
        status = acpi_install_address_space_handler(ec->handle,
                                                    ACPI_ADR_SPACE_EC,
                                                    &acpi_ec_space_handler,
                                                    &acpi_ec_space_setup, ec);
        if (ACPI_FAILURE(status)) {
-               acpi_remove_gpe_handler(NULL, ec->gpe_bit,
+               acpi_remove_gpe_handler(NULL, ec->gpe,
                                        &acpi_ec_gpe_handler);
                return -ENODEV;
        }
@@ -827,7 +816,7 @@ static int acpi_ec_stop(struct acpi_device *device, int type)
                return -ENODEV;
 
        status =
-           acpi_remove_gpe_handler(NULL, ec->gpe_bit,
+           acpi_remove_gpe_handler(NULL, ec->gpe,
                                    &acpi_ec_gpe_handler);
        if (ACPI_FAILURE(status))
                return -ENODEV;
@@ -841,7 +830,7 @@ acpi_fake_ecdt_callback(acpi_handle handle,
 {
        acpi_status status;
 
-       init_MUTEX(&ec_ecdt->sem);
+       mutex_init(&ec_ecdt->lock);
        if (acpi_ec_mode == EC_INTR) {
                init_waitqueue_head(&ec_ecdt->wait);
        }
@@ -855,14 +844,14 @@ acpi_fake_ecdt_callback(acpi_handle handle,
 
        status =
            acpi_evaluate_integer(handle, "_GPE", NULL,
-                                 &ec_ecdt->gpe_bit);
+                                 &ec_ecdt->gpe);
        if (ACPI_FAILURE(status))
                return status;
        ec_ecdt->global_lock = TRUE;
        ec_ecdt->handle = handle;
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx",
-              ec_ecdt->gpe_bit, ec_ecdt->command_addr, ec_ecdt->data_addr));
+              ec_ecdt->gpe, ec_ecdt->command_addr, ec_ecdt->data_addr));
 
        return AE_CTRL_TERMINATE;
 }
@@ -926,13 +915,13 @@ static int __init acpi_ec_get_real_ecdt(void)
                return -ENOMEM;
        memset(ec_ecdt, 0, sizeof(struct acpi_ec));
 
-       init_MUTEX(&ec_ecdt->sem);
+       mutex_init(&ec_ecdt->lock);
        if (acpi_ec_mode == EC_INTR) {
                init_waitqueue_head(&ec_ecdt->wait);
        }
        ec_ecdt->command_addr = ecdt_ptr->ec_control.address;
        ec_ecdt->data_addr = ecdt_ptr->ec_data.address;
-       ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit;
+       ec_ecdt->gpe = ecdt_ptr->gpe_bit;
        /* use the GL just to be safe */
        ec_ecdt->global_lock = TRUE;
        ec_ecdt->uid = ecdt_ptr->uid;
@@ -970,14 +959,14 @@ int __init acpi_ec_ecdt_probe(void)
        /*
         * Install GPE handler
         */
-       status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe_bit,
+       status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe,
                                          ACPI_GPE_EDGE_TRIGGERED,
                                          &acpi_ec_gpe_handler, ec_ecdt);
        if (ACPI_FAILURE(status)) {
                goto error;
        }
-       acpi_set_gpe_type(NULL, ec_ecdt->gpe_bit, ACPI_GPE_TYPE_RUNTIME);
-       acpi_enable_gpe(NULL, ec_ecdt->gpe_bit, ACPI_NOT_ISR);
+       acpi_set_gpe_type(NULL, ec_ecdt->gpe, ACPI_GPE_TYPE_RUNTIME);
+       acpi_enable_gpe(NULL, ec_ecdt->gpe, ACPI_NOT_ISR);
 
        status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
                                                    ACPI_ADR_SPACE_EC,
@@ -985,7 +974,7 @@ int __init acpi_ec_ecdt_probe(void)
                                                    &acpi_ec_space_setup,
                                                    ec_ecdt);
        if (ACPI_FAILURE(status)) {
-               acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit,
+               acpi_remove_gpe_handler(NULL, ec_ecdt->gpe,
                                        &acpi_ec_gpe_handler);
                goto error;
        }