Commit 0b7084ac authored by Alexey Starikovskiy's avatar Alexey Starikovskiy Committed by Len Brown

ACPICA: Use spinlock for acpi_{en|dis}able_gpe

Disabling gpe might interfere with gpe detection/handling,
thus producing "interrupt not handled" errors.
Ironically, disabling of GPE from interrupt context is already
under spinlock, so only userspace needs to start using it.
Signed-off-by: default avatarAlexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent a2f93aea
...@@ -479,7 +479,7 @@ static int acpi_button_add(struct acpi_device *device) ...@@ -479,7 +479,7 @@ static int acpi_button_add(struct acpi_device *device)
device->wakeup.gpe_number, device->wakeup.gpe_number,
ACPI_GPE_TYPE_WAKE_RUN); ACPI_GPE_TYPE_WAKE_RUN);
acpi_enable_gpe(device->wakeup.gpe_device, acpi_enable_gpe(device->wakeup.gpe_device,
device->wakeup.gpe_number, ACPI_NOT_ISR); device->wakeup.gpe_number);
device->wakeup.state.enabled = 1; device->wakeup.state.enabled = 1;
} }
......
...@@ -282,7 +282,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, ...@@ -282,7 +282,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
/* disable GPE during transaction if storm is detected */ /* disable GPE during transaction if storm is detected */
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); acpi_disable_gpe(NULL, ec->gpe);
} }
/* start transaction */ /* start transaction */
spin_lock_irqsave(&ec->curr_lock, tmp); spin_lock_irqsave(&ec->curr_lock, tmp);
...@@ -305,7 +305,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, ...@@ -305,7 +305,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
/* check if we received SCI during transaction */ /* check if we received SCI during transaction */
ec_check_sci(ec, acpi_ec_read_status(ec)); ec_check_sci(ec, acpi_ec_read_status(ec));
/* it is safe to enable GPE outside of transaction */ /* it is safe to enable GPE outside of transaction */
acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); acpi_enable_gpe(NULL, ec->gpe);
} else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
t->irq_count > ACPI_EC_STORM_THRESHOLD) { t->irq_count > ACPI_EC_STORM_THRESHOLD) {
pr_info(PREFIX "GPE storm detected, " pr_info(PREFIX "GPE storm detected, "
...@@ -897,7 +897,7 @@ static int ec_install_handlers(struct acpi_ec *ec) ...@@ -897,7 +897,7 @@ static int ec_install_handlers(struct acpi_ec *ec)
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
return -ENODEV; return -ENODEV;
acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); acpi_enable_gpe(NULL, ec->gpe);
status = acpi_install_address_space_handler(ec->handle, status = acpi_install_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC, ACPI_ADR_SPACE_EC,
&acpi_ec_space_handler, &acpi_ec_space_handler,
...@@ -1036,7 +1036,7 @@ static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state) ...@@ -1036,7 +1036,7 @@ static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state)
/* Stop using GPE */ /* Stop using GPE */
set_bit(EC_FLAGS_NO_GPE, &ec->flags); set_bit(EC_FLAGS_NO_GPE, &ec->flags);
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); acpi_disable_gpe(NULL, ec->gpe);
return 0; return 0;
} }
...@@ -1045,7 +1045,7 @@ static int acpi_ec_resume(struct acpi_device *device) ...@@ -1045,7 +1045,7 @@ static int acpi_ec_resume(struct acpi_device *device)
struct acpi_ec *ec = acpi_driver_data(device); struct acpi_ec *ec = acpi_driver_data(device);
/* Enable use of GPE back */ /* Enable use of GPE back */
clear_bit(EC_FLAGS_NO_GPE, &ec->flags); clear_bit(EC_FLAGS_NO_GPE, &ec->flags);
acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); acpi_enable_gpe(NULL, ec->gpe);
return 0; return 0;
} }
......
...@@ -248,21 +248,15 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe_type) ...@@ -248,21 +248,15 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe_type)
* DESCRIPTION: Enable an ACPI event (general purpose) * DESCRIPTION: Enable an ACPI event (general purpose)
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
acpi_cpu_flags flags;
struct acpi_gpe_event_info *gpe_event_info; struct acpi_gpe_event_info *gpe_event_info;
ACPI_FUNCTION_TRACE(acpi_enable_gpe); ACPI_FUNCTION_TRACE(acpi_enable_gpe);
/* Use semaphore lock if not executing at interrupt level */ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
if (flags & ACPI_NOT_ISR) {
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
/* Ensure that we have a valid GPE number */ /* Ensure that we have a valid GPE number */
...@@ -277,9 +271,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) ...@@ -277,9 +271,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
status = acpi_ev_enable_gpe(gpe_event_info, TRUE); status = acpi_ev_enable_gpe(gpe_event_info, TRUE);
unlock_and_exit: unlock_and_exit:
if (flags & ACPI_NOT_ISR) { acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
}
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
...@@ -299,22 +291,15 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe) ...@@ -299,22 +291,15 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
* DESCRIPTION: Disable an ACPI event (general purpose) * DESCRIPTION: Disable an ACPI event (general purpose)
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
acpi_cpu_flags flags;
struct acpi_gpe_event_info *gpe_event_info; struct acpi_gpe_event_info *gpe_event_info;
ACPI_FUNCTION_TRACE(acpi_disable_gpe); ACPI_FUNCTION_TRACE(acpi_disable_gpe);
/* Use semaphore lock if not executing at interrupt level */ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
if (flags & ACPI_NOT_ISR) {
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
/* Ensure that we have a valid GPE number */ /* Ensure that we have a valid GPE number */
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
...@@ -325,10 +310,8 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) ...@@ -325,10 +310,8 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
status = acpi_ev_disable_gpe(gpe_event_info); status = acpi_ev_disable_gpe(gpe_event_info);
unlock_and_exit: unlock_and_exit:
if (flags & ACPI_NOT_ISR) { acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
}
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
......
...@@ -88,7 +88,7 @@ void acpi_enable_wakeup_device(u8 sleep_state) ...@@ -88,7 +88,7 @@ void acpi_enable_wakeup_device(u8 sleep_state)
spin_unlock(&acpi_device_lock); spin_unlock(&acpi_device_lock);
if (!dev->wakeup.flags.run_wake) if (!dev->wakeup.flags.run_wake)
acpi_enable_gpe(dev->wakeup.gpe_device, acpi_enable_gpe(dev->wakeup.gpe_device,
dev->wakeup.gpe_number, ACPI_ISR); dev->wakeup.gpe_number);
spin_lock(&acpi_device_lock); spin_lock(&acpi_device_lock);
} }
spin_unlock(&acpi_device_lock); spin_unlock(&acpi_device_lock);
...@@ -122,7 +122,7 @@ void acpi_disable_wakeup_device(u8 sleep_state) ...@@ -122,7 +122,7 @@ void acpi_disable_wakeup_device(u8 sleep_state)
ACPI_GPE_TYPE_WAKE_RUN); ACPI_GPE_TYPE_WAKE_RUN);
/* Re-enable it, since set_gpe_type will disable it */ /* Re-enable it, since set_gpe_type will disable it */
acpi_enable_gpe(dev->wakeup.gpe_device, acpi_enable_gpe(dev->wakeup.gpe_device,
dev->wakeup.gpe_number, ACPI_NOT_ISR); dev->wakeup.gpe_number);
spin_lock(&acpi_device_lock); spin_lock(&acpi_device_lock);
} }
continue; continue;
...@@ -133,7 +133,7 @@ void acpi_disable_wakeup_device(u8 sleep_state) ...@@ -133,7 +133,7 @@ void acpi_disable_wakeup_device(u8 sleep_state)
/* Never disable run-wake GPE */ /* Never disable run-wake GPE */
if (!dev->wakeup.flags.run_wake) { if (!dev->wakeup.flags.run_wake) {
acpi_disable_gpe(dev->wakeup.gpe_device, acpi_disable_gpe(dev->wakeup.gpe_device,
dev->wakeup.gpe_number, ACPI_NOT_ISR); dev->wakeup.gpe_number);
acpi_clear_gpe(dev->wakeup.gpe_device, acpi_clear_gpe(dev->wakeup.gpe_device,
dev->wakeup.gpe_number, ACPI_NOT_ISR); dev->wakeup.gpe_number, ACPI_NOT_ISR);
} }
...@@ -162,7 +162,7 @@ static int __init acpi_wakeup_device_init(void) ...@@ -162,7 +162,7 @@ static int __init acpi_wakeup_device_init(void)
dev->wakeup.gpe_number, dev->wakeup.gpe_number,
ACPI_GPE_TYPE_WAKE_RUN); ACPI_GPE_TYPE_WAKE_RUN);
acpi_enable_gpe(dev->wakeup.gpe_device, acpi_enable_gpe(dev->wakeup.gpe_device,
dev->wakeup.gpe_number, ACPI_NOT_ISR); dev->wakeup.gpe_number);
dev->wakeup.state.enabled = 1; dev->wakeup.state.enabled = 1;
spin_lock(&acpi_device_lock); spin_lock(&acpi_device_lock);
} }
......
...@@ -394,10 +394,10 @@ static ssize_t counter_set(struct kobject *kobj, ...@@ -394,10 +394,10 @@ static ssize_t counter_set(struct kobject *kobj,
if (index < num_gpes) { if (index < num_gpes) {
if (!strcmp(buf, "disable\n") && if (!strcmp(buf, "disable\n") &&
(status & ACPI_EVENT_FLAG_ENABLED)) (status & ACPI_EVENT_FLAG_ENABLED))
result = acpi_disable_gpe(handle, index, ACPI_NOT_ISR); result = acpi_disable_gpe(handle, index);
else if (!strcmp(buf, "enable\n") && else if (!strcmp(buf, "enable\n") &&
!(status & ACPI_EVENT_FLAG_ENABLED)) !(status & ACPI_EVENT_FLAG_ENABLED))
result = acpi_enable_gpe(handle, index, ACPI_NOT_ISR); result = acpi_enable_gpe(handle, index);
else if (!strcmp(buf, "clear\n") && else if (!strcmp(buf, "clear\n") &&
(status & ACPI_EVENT_FLAG_SET)) (status & ACPI_EVENT_FLAG_SET))
result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR); result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR);
......
...@@ -252,9 +252,9 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status); ...@@ -252,9 +252,9 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status);
acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type); acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type);
acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags); acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number);
acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags); acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number);
acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags); acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment