diff options
author | Alexey Starikovskiy <astarikovskiy@suse.de> | 2008-10-25 13:48:46 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2008-11-11 18:35:42 -0500 |
commit | 0b7084ac67fb84f0cf2f8bc02d7e0dea8521dd2d (patch) | |
tree | 0a619ac7a700543e6ba69aa5a568e5678ec0603d | |
parent | a2f93aeadf97e870ff385030633a73e21146815d (diff) |
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: Alexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r-- | drivers/acpi/button.c | 2 | ||||
-rw-r--r-- | drivers/acpi/ec.c | 10 | ||||
-rw-r--r-- | drivers/acpi/events/evxfevnt.c | 35 | ||||
-rw-r--r-- | drivers/acpi/sleep/wakeup.c | 8 | ||||
-rw-r--r-- | drivers/acpi/system.c | 4 | ||||
-rw-r--r-- | include/acpi/acpixf.h | 4 |
6 files changed, 23 insertions, 40 deletions
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index cb046c3fc3f2..eb6bf3025f97 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
@@ -479,7 +479,7 @@ static int acpi_button_add(struct acpi_device *device) | |||
479 | device->wakeup.gpe_number, | 479 | device->wakeup.gpe_number, |
480 | ACPI_GPE_TYPE_WAKE_RUN); | 480 | ACPI_GPE_TYPE_WAKE_RUN); |
481 | acpi_enable_gpe(device->wakeup.gpe_device, | 481 | acpi_enable_gpe(device->wakeup.gpe_device, |
482 | device->wakeup.gpe_number, ACPI_NOT_ISR); | 482 | device->wakeup.gpe_number); |
483 | device->wakeup.state.enabled = 1; | 483 | device->wakeup.state.enabled = 1; |
484 | } | 484 | } |
485 | 485 | ||
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 34c67ca3bebe..89d6d2868e8c 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -282,7 +282,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
282 | /* disable GPE during transaction if storm is detected */ | 282 | /* disable GPE during transaction if storm is detected */ |
283 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { | 283 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { |
284 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); | 284 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); |
285 | acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | 285 | acpi_disable_gpe(NULL, ec->gpe); |
286 | } | 286 | } |
287 | /* start transaction */ | 287 | /* start transaction */ |
288 | spin_lock_irqsave(&ec->curr_lock, tmp); | 288 | spin_lock_irqsave(&ec->curr_lock, tmp); |
@@ -305,7 +305,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
305 | /* check if we received SCI during transaction */ | 305 | /* check if we received SCI during transaction */ |
306 | ec_check_sci(ec, acpi_ec_read_status(ec)); | 306 | ec_check_sci(ec, acpi_ec_read_status(ec)); |
307 | /* it is safe to enable GPE outside of transaction */ | 307 | /* it is safe to enable GPE outside of transaction */ |
308 | acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | 308 | acpi_enable_gpe(NULL, ec->gpe); |
309 | } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && | 309 | } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && |
310 | t->irq_count > ACPI_EC_STORM_THRESHOLD) { | 310 | t->irq_count > ACPI_EC_STORM_THRESHOLD) { |
311 | pr_info(PREFIX "GPE storm detected, " | 311 | pr_info(PREFIX "GPE storm detected, " |
@@ -897,7 +897,7 @@ static int ec_install_handlers(struct acpi_ec *ec) | |||
897 | if (ACPI_FAILURE(status)) | 897 | if (ACPI_FAILURE(status)) |
898 | return -ENODEV; | 898 | return -ENODEV; |
899 | acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); | 899 | acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); |
900 | acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | 900 | acpi_enable_gpe(NULL, ec->gpe); |
901 | status = acpi_install_address_space_handler(ec->handle, | 901 | status = acpi_install_address_space_handler(ec->handle, |
902 | ACPI_ADR_SPACE_EC, | 902 | ACPI_ADR_SPACE_EC, |
903 | &acpi_ec_space_handler, | 903 | &acpi_ec_space_handler, |
@@ -1036,7 +1036,7 @@ static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state) | |||
1036 | /* Stop using GPE */ | 1036 | /* Stop using GPE */ |
1037 | set_bit(EC_FLAGS_NO_GPE, &ec->flags); | 1037 | set_bit(EC_FLAGS_NO_GPE, &ec->flags); |
1038 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); | 1038 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); |
1039 | acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | 1039 | acpi_disable_gpe(NULL, ec->gpe); |
1040 | return 0; | 1040 | return 0; |
1041 | } | 1041 | } |
1042 | 1042 | ||
@@ -1045,7 +1045,7 @@ static int acpi_ec_resume(struct acpi_device *device) | |||
1045 | struct acpi_ec *ec = acpi_driver_data(device); | 1045 | struct acpi_ec *ec = acpi_driver_data(device); |
1046 | /* Enable use of GPE back */ | 1046 | /* Enable use of GPE back */ |
1047 | clear_bit(EC_FLAGS_NO_GPE, &ec->flags); | 1047 | clear_bit(EC_FLAGS_NO_GPE, &ec->flags); |
1048 | acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | 1048 | acpi_enable_gpe(NULL, ec->gpe); |
1049 | return 0; | 1049 | return 0; |
1050 | } | 1050 | } |
1051 | 1051 | ||
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c index 73bfd6bf962f..39db00874a22 100644 --- a/drivers/acpi/events/evxfevnt.c +++ b/drivers/acpi/events/evxfevnt.c | |||
@@ -248,21 +248,15 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe_type) | |||
248 | * DESCRIPTION: Enable an ACPI event (general purpose) | 248 | * DESCRIPTION: Enable an ACPI event (general purpose) |
249 | * | 249 | * |
250 | ******************************************************************************/ | 250 | ******************************************************************************/ |
251 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) | 251 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) |
252 | { | 252 | { |
253 | acpi_status status = AE_OK; | 253 | acpi_status status = AE_OK; |
254 | acpi_cpu_flags flags; | ||
254 | struct acpi_gpe_event_info *gpe_event_info; | 255 | struct acpi_gpe_event_info *gpe_event_info; |
255 | 256 | ||
256 | ACPI_FUNCTION_TRACE(acpi_enable_gpe); | 257 | ACPI_FUNCTION_TRACE(acpi_enable_gpe); |
257 | 258 | ||
258 | /* Use semaphore lock if not executing at interrupt level */ | 259 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
259 | |||
260 | if (flags & ACPI_NOT_ISR) { | ||
261 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
262 | if (ACPI_FAILURE(status)) { | ||
263 | return_ACPI_STATUS(status); | ||
264 | } | ||
265 | } | ||
266 | 260 | ||
267 | /* Ensure that we have a valid GPE number */ | 261 | /* Ensure that we have a valid GPE number */ |
268 | 262 | ||
@@ -277,9 +271,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) | |||
277 | status = acpi_ev_enable_gpe(gpe_event_info, TRUE); | 271 | status = acpi_ev_enable_gpe(gpe_event_info, TRUE); |
278 | 272 | ||
279 | unlock_and_exit: | 273 | unlock_and_exit: |
280 | if (flags & ACPI_NOT_ISR) { | 274 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); |
281 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
282 | } | ||
283 | return_ACPI_STATUS(status); | 275 | return_ACPI_STATUS(status); |
284 | } | 276 | } |
285 | 277 | ||
@@ -299,22 +291,15 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe) | |||
299 | * DESCRIPTION: Disable an ACPI event (general purpose) | 291 | * DESCRIPTION: Disable an ACPI event (general purpose) |
300 | * | 292 | * |
301 | ******************************************************************************/ | 293 | ******************************************************************************/ |
302 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) | 294 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) |
303 | { | 295 | { |
304 | acpi_status status = AE_OK; | 296 | acpi_status status = AE_OK; |
297 | acpi_cpu_flags flags; | ||
305 | struct acpi_gpe_event_info *gpe_event_info; | 298 | struct acpi_gpe_event_info *gpe_event_info; |
306 | 299 | ||
307 | ACPI_FUNCTION_TRACE(acpi_disable_gpe); | 300 | ACPI_FUNCTION_TRACE(acpi_disable_gpe); |
308 | 301 | ||
309 | /* Use semaphore lock if not executing at interrupt level */ | 302 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
310 | |||
311 | if (flags & ACPI_NOT_ISR) { | ||
312 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
313 | if (ACPI_FAILURE(status)) { | ||
314 | return_ACPI_STATUS(status); | ||
315 | } | ||
316 | } | ||
317 | |||
318 | /* Ensure that we have a valid GPE number */ | 303 | /* Ensure that we have a valid GPE number */ |
319 | 304 | ||
320 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | 305 | 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 | 310 | ||
326 | status = acpi_ev_disable_gpe(gpe_event_info); | 311 | status = acpi_ev_disable_gpe(gpe_event_info); |
327 | 312 | ||
328 | unlock_and_exit: | 313 | unlock_and_exit: |
329 | if (flags & ACPI_NOT_ISR) { | 314 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); |
330 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
331 | } | ||
332 | return_ACPI_STATUS(status); | 315 | return_ACPI_STATUS(status); |
333 | } | 316 | } |
334 | 317 | ||
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c index 38655eb132dc..dea4c23df764 100644 --- a/drivers/acpi/sleep/wakeup.c +++ b/drivers/acpi/sleep/wakeup.c | |||
@@ -88,7 +88,7 @@ void acpi_enable_wakeup_device(u8 sleep_state) | |||
88 | spin_unlock(&acpi_device_lock); | 88 | spin_unlock(&acpi_device_lock); |
89 | if (!dev->wakeup.flags.run_wake) | 89 | if (!dev->wakeup.flags.run_wake) |
90 | acpi_enable_gpe(dev->wakeup.gpe_device, | 90 | acpi_enable_gpe(dev->wakeup.gpe_device, |
91 | dev->wakeup.gpe_number, ACPI_ISR); | 91 | dev->wakeup.gpe_number); |
92 | spin_lock(&acpi_device_lock); | 92 | spin_lock(&acpi_device_lock); |
93 | } | 93 | } |
94 | spin_unlock(&acpi_device_lock); | 94 | spin_unlock(&acpi_device_lock); |
@@ -122,7 +122,7 @@ void acpi_disable_wakeup_device(u8 sleep_state) | |||
122 | ACPI_GPE_TYPE_WAKE_RUN); | 122 | ACPI_GPE_TYPE_WAKE_RUN); |
123 | /* Re-enable it, since set_gpe_type will disable it */ | 123 | /* Re-enable it, since set_gpe_type will disable it */ |
124 | acpi_enable_gpe(dev->wakeup.gpe_device, | 124 | acpi_enable_gpe(dev->wakeup.gpe_device, |
125 | dev->wakeup.gpe_number, ACPI_NOT_ISR); | 125 | dev->wakeup.gpe_number); |
126 | spin_lock(&acpi_device_lock); | 126 | spin_lock(&acpi_device_lock); |
127 | } | 127 | } |
128 | continue; | 128 | continue; |
@@ -133,7 +133,7 @@ void acpi_disable_wakeup_device(u8 sleep_state) | |||
133 | /* Never disable run-wake GPE */ | 133 | /* Never disable run-wake GPE */ |
134 | if (!dev->wakeup.flags.run_wake) { | 134 | if (!dev->wakeup.flags.run_wake) { |
135 | acpi_disable_gpe(dev->wakeup.gpe_device, | 135 | acpi_disable_gpe(dev->wakeup.gpe_device, |
136 | dev->wakeup.gpe_number, ACPI_NOT_ISR); | 136 | dev->wakeup.gpe_number); |
137 | acpi_clear_gpe(dev->wakeup.gpe_device, | 137 | acpi_clear_gpe(dev->wakeup.gpe_device, |
138 | dev->wakeup.gpe_number, ACPI_NOT_ISR); | 138 | dev->wakeup.gpe_number, ACPI_NOT_ISR); |
139 | } | 139 | } |
@@ -162,7 +162,7 @@ static int __init acpi_wakeup_device_init(void) | |||
162 | dev->wakeup.gpe_number, | 162 | dev->wakeup.gpe_number, |
163 | ACPI_GPE_TYPE_WAKE_RUN); | 163 | ACPI_GPE_TYPE_WAKE_RUN); |
164 | acpi_enable_gpe(dev->wakeup.gpe_device, | 164 | acpi_enable_gpe(dev->wakeup.gpe_device, |
165 | dev->wakeup.gpe_number, ACPI_NOT_ISR); | 165 | dev->wakeup.gpe_number); |
166 | dev->wakeup.state.enabled = 1; | 166 | dev->wakeup.state.enabled = 1; |
167 | spin_lock(&acpi_device_lock); | 167 | spin_lock(&acpi_device_lock); |
168 | } | 168 | } |
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 1d74171b7940..11995b612ad7 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c | |||
@@ -394,10 +394,10 @@ static ssize_t counter_set(struct kobject *kobj, | |||
394 | if (index < num_gpes) { | 394 | if (index < num_gpes) { |
395 | if (!strcmp(buf, "disable\n") && | 395 | if (!strcmp(buf, "disable\n") && |
396 | (status & ACPI_EVENT_FLAG_ENABLED)) | 396 | (status & ACPI_EVENT_FLAG_ENABLED)) |
397 | result = acpi_disable_gpe(handle, index, ACPI_NOT_ISR); | 397 | result = acpi_disable_gpe(handle, index); |
398 | else if (!strcmp(buf, "enable\n") && | 398 | else if (!strcmp(buf, "enable\n") && |
399 | !(status & ACPI_EVENT_FLAG_ENABLED)) | 399 | !(status & ACPI_EVENT_FLAG_ENABLED)) |
400 | result = acpi_enable_gpe(handle, index, ACPI_NOT_ISR); | 400 | result = acpi_enable_gpe(handle, index); |
401 | else if (!strcmp(buf, "clear\n") && | 401 | else if (!strcmp(buf, "clear\n") && |
402 | (status & ACPI_EVENT_FLAG_SET)) | 402 | (status & ACPI_EVENT_FLAG_SET)) |
403 | result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR); | 403 | result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR); |
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 94d94e126e9f..33bc0e3b1954 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h | |||
@@ -252,9 +252,9 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status); | |||
252 | 252 | ||
253 | acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type); | 253 | acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type); |
254 | 254 | ||
255 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags); | 255 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number); |
256 | 256 | ||
257 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags); | 257 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number); |
258 | 258 | ||
259 | acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags); | 259 | acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags); |
260 | 260 | ||