Make selection of mode automatic. If EC sends confirmation interrupts -- switch to interrupt mode, otherwise poll it. If EC fails to send confirmation interrupt within a timeout, switch back to poll mode. Signed-off-by: Alexey Starikovskiy <astarikovskiy@xxxxxxx> --- drivers/acpi/ec.c | 42 +++++++++++++++--------------------------- 1 files changed, 15 insertions(+), 27 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index e9a8805..5183769 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -72,9 +72,9 @@ enum ec_event { #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ static enum ec_mode { - EC_INTR = 1, /* Output buffer full */ - EC_POLL, /* Input buffer empty */ -} acpi_ec_mode = EC_INTR; + EC_INTR = 1, /* EC sends GPE to complete transaction */ + EC_POLL, /* EC does not send anything */ +} acpi_ec_mode = EC_POLL; /* start with safer assumptions */ static int acpi_ec_remove(struct acpi_device *device, int type); static int acpi_ec_start(struct acpi_device *device); @@ -177,16 +177,18 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, } else { if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event, count), - msecs_to_jiffies(ACPI_EC_DELAY)) || - acpi_ec_check_status(ec, event, 0)) { + msecs_to_jiffies(ACPI_EC_DELAY))) + return 0; + if (acpi_ec_check_status(ec, event, 0)) { + printk(KERN_WARNING PREFIX "EC did not send confirm " + "interrupt, switch to poll mode\n"); + acpi_ec_mode = EC_POLL; return 0; - } else { - printk(KERN_ERR PREFIX "acpi_ec_wait timeout," - " status = %d, expect_event = %d\n", - acpi_ec_read_status(ec), event); } } - + printk(KERN_ERR PREFIX "acpi_ec_wait timeout," + " status = %d, expect_event = %d\n", + acpi_ec_read_status(ec), event); return -ETIME; } @@ -490,8 +492,10 @@ static u32 acpi_ec_gpe_handler(void *data) atomic_set(&ec->query_pending, 1); status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); + } else { + /* Non-query intterrupt from EC, must be confirmation */ + acpi_ec_mode = EC_INTR; } - return status == AE_OK ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; } @@ -925,19 +929,3 @@ static void __exit acpi_ec_exit(void) return; } #endif /* 0 */ - -static int __init acpi_ec_set_intr_mode(char *str) -{ - int intr; - - if (!get_option(&str, &intr)) - return 0; - - acpi_ec_mode = (intr) ? EC_INTR : EC_POLL; - - printk(KERN_NOTICE PREFIX "%s mode.\n", intr ? "interrupt" : "polling"); - - return 1; -} - -__setup("ec_intr=", acpi_ec_set_intr_mode); - To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html