diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/ec.c | 171 |
1 files changed, 59 insertions, 112 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index b15f5ec81d05..7e1a445955bc 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -212,19 +212,29 @@ static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event) ec->burst.expect_event = event; smp_mb(); - result = wait_event_interruptible_timeout(ec->burst.wait, - !ec->burst.expect_event, - msecs_to_jiffies - (ACPI_EC_DELAY)); + switch (event) { + case ACPI_EC_EVENT_OBF: + if (acpi_ec_read_status(ec) & event) { + ec->burst.expect_event = 0; + return_VALUE(0); + } + break; + + case ACPI_EC_EVENT_IBE: + if (~acpi_ec_read_status(ec) & event) { + ec->burst.expect_event = 0; + return_VALUE(0); + } + break; + } + + result = wait_event_timeout(ec->burst.wait, + !ec->burst.expect_event, + msecs_to_jiffies(ACPI_EC_DELAY)); ec->burst.expect_event = 0; smp_mb(); - if (result < 0) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, " result = %d ", result)); - return_VALUE(result); - } - /* * Verify that the event in question has actually happened by * querying EC status. Do the check even if operation timed-out @@ -254,15 +264,15 @@ static int acpi_ec_enter_burst_mode(union acpi_ec *ec) status = acpi_ec_read_status(ec); if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) { + status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (status) + goto end; acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); - if (status) { - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); + if (status) return_VALUE(-EINVAL); - } acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if (tmp != 0x90) { /* Burst ACK byte */ return_VALUE(-EINVAL); } @@ -270,30 +280,17 @@ static int acpi_ec_enter_burst_mode(union acpi_ec *ec) atomic_set(&ec->burst.leaving_burst, 0); return_VALUE(0); + end: + printk("Error in acpi_ec_wait\n"); + return_VALUE(-1); } static int acpi_ec_leave_burst_mode(union acpi_ec *ec) { - int status = 0; ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode"); atomic_set(&ec->burst.leaving_burst, 1); - status = acpi_ec_read_status(ec); - if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)) { - acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, - &ec->common.command_addr); - status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF); - if (status) { - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "------->wait fail\n")); - return_VALUE(-EINVAL); - } - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); - status = acpi_ec_read_status(ec); - } - return_VALUE(0); } @@ -416,7 +413,6 @@ static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data) if (!ec || !data) return_VALUE(-EINVAL); - retry: *data = 0; if (ec->common.global_lock) { @@ -428,27 +424,26 @@ static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data) WARN_ON(in_interrupt()); down(&ec->burst.sem); - if (acpi_ec_enter_burst_mode(ec)) + acpi_ec_enter_burst_mode(ec); + status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (status) { + printk("read EC, IB not empty\n"); goto end; - + } acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if (status) { - goto end; + printk("read EC, IB not empty\n"); } acpi_hw_low_level_write(8, address, &ec->common.data_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (status) { - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); + printk("read EC, OB not full\n"); goto end; } - acpi_hw_low_level_read(8, data, &ec->common.data_addr); - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", *data, address)); @@ -459,15 +454,6 @@ static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data) if (ec->common.global_lock) acpi_release_global_lock(glk); - if (atomic_read(&ec->burst.leaving_burst) == 2) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aborted, retry ...\n")); - while (atomic_read(&ec->burst.pending_gpe)) { - msleep(1); - } - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); - goto retry; - } - return_VALUE(status); } @@ -475,13 +461,12 @@ static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data) { int status = 0; u32 glk; - u32 tmp; ACPI_FUNCTION_TRACE("acpi_ec_write"); if (!ec) return_VALUE(-EINVAL); - retry: + if (ec->common.global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) @@ -491,62 +476,36 @@ static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data) WARN_ON(in_interrupt()); down(&ec->burst.sem); - if (acpi_ec_enter_burst_mode(ec)) - goto end; + acpi_ec_enter_burst_mode(ec); - status = acpi_ec_read_status(ec); - if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) { - acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, - &ec->common.command_addr); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); - if (status) - goto end; - acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); - if (tmp != 0x90) /* Burst ACK byte */ - goto end; + status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (status) { + printk("write EC, IB not empty\n"); } - /*Now we are in burst mode */ - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if (status) { - goto end; + printk("write EC, IB not empty\n"); } acpi_hw_low_level_write(8, address, &ec->common.data_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (status) { - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); - goto end; + printk("write EC, IB not empty\n"); } acpi_hw_low_level_write(8, data, &ec->common.data_addr); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); - if (status) - goto end; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", data, address)); - end: acpi_ec_leave_burst_mode(ec); up(&ec->burst.sem); if (ec->common.global_lock) acpi_release_global_lock(glk); - if (atomic_read(&ec->burst.leaving_burst) == 2) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aborted, retry ...\n")); - while (atomic_read(&ec->burst.pending_gpe)) { - msleep(1); - } - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); - goto retry; - } - return_VALUE(status); } @@ -662,8 +621,12 @@ static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data) } down(&ec->burst.sem); - if (acpi_ec_enter_burst_mode(ec)) + + status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (status) { + printk("query EC, IB not empty\n"); goto end; + } /* * Query the EC to find out which _Qxx method we need to evaluate. * Note that successful completion of the query causes the ACPI_EC_SCI @@ -673,27 +636,20 @@ static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data) &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (status) { - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); + printk("query EC, OB not full\n"); goto end; } acpi_hw_low_level_read(8, data, &ec->common.data_addr); - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if (!*data) status = -ENODATA; end: - acpi_ec_leave_burst_mode(ec); up(&ec->burst.sem); if (ec->common.global_lock) acpi_release_global_lock(glk); - if (atomic_read(&ec->burst.leaving_burst) == 2) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aborted, retry ...\n")); - acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); - status = -ENODATA; - } return_VALUE(status); } @@ -818,31 +774,21 @@ static u32 acpi_ec_gpe_burst_handler(void *data) if (!ec) return ACPI_INTERRUPT_NOT_HANDLED; - acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); - + acpi_clear_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); value = acpi_ec_read_status(ec); - if ((value & ACPI_EC_FLAG_IBF) && - !(value & ACPI_EC_FLAG_BURST) && - (atomic_read(&ec->burst.leaving_burst) == 0)) { - /* - * the embedded controller disables - * burst mode for any reason other - * than the burst disable command - * to process critical event. - */ - atomic_set(&ec->burst.leaving_burst, 2); /* block current pending transaction - and retry */ + switch (ec->burst.expect_event) { + case ACPI_EC_EVENT_OBF: + if (!(value & ACPI_EC_FLAG_OBF)) + break; + case ACPI_EC_EVENT_IBE: + if ((value & ACPI_EC_FLAG_IBF)) + break; + ec->burst.expect_event = 0; wake_up(&ec->burst.wait); - } else { - if ((ec->burst.expect_event == ACPI_EC_EVENT_OBF && - (value & ACPI_EC_FLAG_OBF)) || - (ec->burst.expect_event == ACPI_EC_EVENT_IBE && - !(value & ACPI_EC_FLAG_IBF))) { - ec->burst.expect_event = 0; - wake_up(&ec->burst.wait); - return ACPI_INTERRUPT_HANDLED; - } + return ACPI_INTERRUPT_HANDLED; + default: + break; } if (value & ACPI_EC_FLAG_SCI) { @@ -1166,6 +1112,7 @@ static int acpi_ec_burst_add(struct acpi_device *device) if (result) goto end; + printk("burst-mode-ec-10-Aug\n"); printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", acpi_device_name(device), acpi_device_bid(device), (u32) ec->common.gpe_bit); |