diff options
Diffstat (limited to 'drivers/acpi/ec.c')
-rw-r--r-- | drivers/acpi/ec.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index caf873c14bfb..e7e197e3a4ff 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -129,6 +129,7 @@ static struct acpi_ec { | |||
129 | struct mutex lock; | 129 | struct mutex lock; |
130 | wait_queue_head_t wait; | 130 | wait_queue_head_t wait; |
131 | struct list_head list; | 131 | struct list_head list; |
132 | atomic_t irq_count; | ||
132 | u8 handlers_installed; | 133 | u8 handlers_installed; |
133 | } *boot_ec, *first_ec; | 134 | } *boot_ec, *first_ec; |
134 | 135 | ||
@@ -181,6 +182,8 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) | |||
181 | { | 182 | { |
182 | int ret = 0; | 183 | int ret = 0; |
183 | 184 | ||
185 | atomic_set(&ec->irq_count, 0); | ||
186 | |||
184 | if (unlikely(event == ACPI_EC_EVENT_OBF_1 && | 187 | if (unlikely(event == ACPI_EC_EVENT_OBF_1 && |
185 | test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags))) | 188 | test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags))) |
186 | force_poll = 1; | 189 | force_poll = 1; |
@@ -227,6 +230,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) | |||
227 | while (time_before(jiffies, delay)) { | 230 | while (time_before(jiffies, delay)) { |
228 | if (acpi_ec_check_status(ec, event)) | 231 | if (acpi_ec_check_status(ec, event)) |
229 | goto end; | 232 | goto end; |
233 | msleep(5); | ||
230 | } | 234 | } |
231 | } | 235 | } |
232 | pr_err(PREFIX "acpi_ec_wait timeout," | 236 | pr_err(PREFIX "acpi_ec_wait timeout," |
@@ -529,6 +533,13 @@ static u32 acpi_ec_gpe_handler(void *data) | |||
529 | struct acpi_ec *ec = data; | 533 | struct acpi_ec *ec = data; |
530 | 534 | ||
531 | pr_debug(PREFIX "~~~> interrupt\n"); | 535 | pr_debug(PREFIX "~~~> interrupt\n"); |
536 | atomic_inc(&ec->irq_count); | ||
537 | if (atomic_read(&ec->irq_count) > 5) { | ||
538 | pr_err(PREFIX "GPE storm detected, disabling EC GPE\n"); | ||
539 | acpi_disable_gpe(NULL, ec->gpe, ACPI_ISR); | ||
540 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); | ||
541 | return ACPI_INTERRUPT_HANDLED; | ||
542 | } | ||
532 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); | 543 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); |
533 | if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) | 544 | if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) |
534 | wake_up(&ec->wait); | 545 | wake_up(&ec->wait); |
@@ -943,11 +954,7 @@ int __init acpi_ec_ecdt_probe(void) | |||
943 | boot_ec->command_addr = ecdt_ptr->control.address; | 954 | boot_ec->command_addr = ecdt_ptr->control.address; |
944 | boot_ec->data_addr = ecdt_ptr->data.address; | 955 | boot_ec->data_addr = ecdt_ptr->data.address; |
945 | boot_ec->gpe = ecdt_ptr->gpe; | 956 | boot_ec->gpe = ecdt_ptr->gpe; |
946 | if (ACPI_FAILURE(acpi_get_handle(NULL, ecdt_ptr->id, | 957 | boot_ec->handle = ACPI_ROOT_OBJECT; |
947 | &boot_ec->handle))) { | ||
948 | pr_info("Failed to locate handle for boot EC\n"); | ||
949 | boot_ec->handle = ACPI_ROOT_OBJECT; | ||
950 | } | ||
951 | } else { | 958 | } else { |
952 | /* This workaround is needed only on some broken machines, | 959 | /* This workaround is needed only on some broken machines, |
953 | * which require early EC, but fail to provide ECDT */ | 960 | * which require early EC, but fail to provide ECDT */ |