aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-02-23 18:52:08 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-02-24 17:25:23 -0500
commitcbbc0de700e61d0cdc854d435dbc2ef148de0e00 (patch)
tree9a645bbdab91e1a00446680a95f2b86e741e0de4 /drivers/acpi
parent7bc5e3f2be32ae6fb0c74cd0f707f986b3a01a26 (diff)
ACPI: Use GPE reference counting to support shared GPEs
To fix a bug and address the reviewers' comments regarding the ACPI GPE refcounting patch, do the following additional changes: o Remove the second argument of acpi_ev_enable_gpe(), 'write_to_hardware', because it is not necessary any more. o Add the "bad parameter" test against 'type' in acpi_enable_gpe() and acpi_disable_gpe(). o Make acpi_enable_gpe() only check 'status' for runtime GPEs if acpi_ev_enable_gpe() was actually called. o Make acpi_disable_gpe() return 'status' returned by acpi_ev_disable_gpe() and fix a bug where ACPI_GPE_TYPE_WAKE and ACPI_GPE_TYPE_RUNTIME were exchanged by mistake. o Add comments explaining why acpi_set_gpe() is used by the ACPI EC driver. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/acpica/acevents.h4
-rw-r--r--drivers/acpi/acpica/evgpe.c10
-rw-r--r--drivers/acpi/acpica/evxfevnt.c24
-rw-r--r--drivers/acpi/ec.c14
4 files changed, 30 insertions, 22 deletions
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index 197aa4f39640..4ced54f7a5d9 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -78,9 +78,7 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node *node,
78acpi_status 78acpi_status
79acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info); 79acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info);
80 80
81acpi_status 81acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info);
82acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info,
83 u8 write_to_hardware);
84 82
85acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info); 83acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info);
86 84
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index 30ca3a30ef00..0b453467a5a0 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -98,8 +98,6 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
98 * FUNCTION: acpi_ev_enable_gpe 98 * FUNCTION: acpi_ev_enable_gpe
99 * 99 *
100 * PARAMETERS: gpe_event_info - GPE to enable 100 * PARAMETERS: gpe_event_info - GPE to enable
101 * write_to_hardware - Enable now, or just mark data structs
102 * (WAKE GPEs should be deferred)
103 * 101 *
104 * RETURN: Status 102 * RETURN: Status
105 * 103 *
@@ -107,9 +105,7 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
107 * 105 *
108 ******************************************************************************/ 106 ******************************************************************************/
109 107
110acpi_status 108acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
111acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info,
112 u8 write_to_hardware)
113{ 109{
114 acpi_status status; 110 acpi_status status;
115 111
@@ -123,7 +119,7 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info,
123 119
124 /* Mark wake-enabled or HW enable, or both */ 120 /* Mark wake-enabled or HW enable, or both */
125 121
126 if (gpe_event_info->runtime_count && write_to_hardware) { 122 if (gpe_event_info->runtime_count) {
127 /* Clear the GPE (of stale events), then enable it */ 123 /* Clear the GPE (of stale events), then enable it */
128 status = acpi_hw_clear_gpe(gpe_event_info); 124 status = acpi_hw_clear_gpe(gpe_event_info);
129 if (ACPI_FAILURE(status)) 125 if (ACPI_FAILURE(status))
@@ -400,7 +396,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
400 396
401 /* Set the GPE flags for return to enabled state */ 397 /* Set the GPE flags for return to enabled state */
402 398
403 (void)acpi_ev_enable_gpe(gpe_event_info, FALSE); 399 (void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
404 400
405 /* 401 /*
406 * Take a snapshot of the GPE info for this level - we copy the info to 402 * Take a snapshot of the GPE info for this level - we copy the info to
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index 1aea1a734159..124c157215bf 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -235,7 +235,7 @@ acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
235 235
236 switch (action) { 236 switch (action) {
237 case ACPI_GPE_ENABLE: 237 case ACPI_GPE_ENABLE:
238 status = acpi_ev_enable_gpe(gpe_event_info, TRUE); 238 status = acpi_ev_enable_gpe(gpe_event_info);
239 break; 239 break;
240 240
241 case ACPI_GPE_DISABLE: 241 case ACPI_GPE_DISABLE:
@@ -276,6 +276,9 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type)
276 276
277 ACPI_FUNCTION_TRACE(acpi_enable_gpe); 277 ACPI_FUNCTION_TRACE(acpi_enable_gpe);
278 278
279 if (type & ~ACPI_GPE_TYPE_WAKE_RUN)
280 return_ACPI_STATUS(AE_BAD_PARAMETER);
281
279 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 282 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
280 283
281 /* Ensure that we have a valid GPE number */ 284 /* Ensure that we have a valid GPE number */
@@ -287,11 +290,11 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type)
287 } 290 }
288 291
289 if (type & ACPI_GPE_TYPE_RUNTIME) { 292 if (type & ACPI_GPE_TYPE_RUNTIME) {
290 if (++gpe_event_info->runtime_count == 1) 293 if (++gpe_event_info->runtime_count == 1) {
291 status = acpi_ev_enable_gpe(gpe_event_info, TRUE); 294 status = acpi_ev_enable_gpe(gpe_event_info);
292 295 if (ACPI_FAILURE(status))
293 if (ACPI_FAILURE(status)) 296 gpe_event_info->runtime_count--;
294 gpe_event_info->runtime_count--; 297 }
295 } 298 }
296 299
297 if (type & ACPI_GPE_TYPE_WAKE) { 300 if (type & ACPI_GPE_TYPE_WAKE) {
@@ -335,6 +338,9 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type)
335 338
336 ACPI_FUNCTION_TRACE(acpi_disable_gpe); 339 ACPI_FUNCTION_TRACE(acpi_disable_gpe);
337 340
341 if (type & ~ACPI_GPE_TYPE_WAKE_RUN)
342 return_ACPI_STATUS(AE_BAD_PARAMETER);
343
338 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 344 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
339 /* Ensure that we have a valid GPE number */ 345 /* Ensure that we have a valid GPE number */
340 346
@@ -344,12 +350,12 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type)
344 goto unlock_and_exit; 350 goto unlock_and_exit;
345 } 351 }
346 352
347 if ((type & ACPI_GPE_TYPE_WAKE) && gpe_event_info->runtime_count) { 353 if ((type & ACPI_GPE_TYPE_RUNTIME) && gpe_event_info->runtime_count) {
348 if (--gpe_event_info->runtime_count == 0) 354 if (--gpe_event_info->runtime_count == 0)
349 acpi_ev_disable_gpe(gpe_event_info); 355 status = acpi_ev_disable_gpe(gpe_event_info);
350 } 356 }
351 357
352 if ((type & ACPI_GPE_TYPE_RUNTIME) && gpe_event_info->wakeup_count) { 358 if ((type & ACPI_GPE_TYPE_WAKE) && gpe_event_info->wakeup_count) {
353 /* 359 /*
354 * Wake-up GPEs are not enabled after leaving system sleep 360 * Wake-up GPEs are not enabled after leaving system sleep
355 * states, so we don't need to disable them here. 361 * states, so we don't need to disable them here.
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 0fa65a8210da..27e0b92b2e39 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -307,6 +307,10 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
307 pr_debug(PREFIX "transaction start\n"); 307 pr_debug(PREFIX "transaction start\n");
308 /* disable GPE during transaction if storm is detected */ 308 /* disable GPE during transaction if storm is detected */
309 if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { 309 if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
310 /*
311 * It has to be disabled at the hardware level regardless of the
312 * GPE reference counting, so that it doesn't trigger.
313 */
310 acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE); 314 acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE);
311 } 315 }
312 316
@@ -316,7 +320,11 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
316 ec_check_sci_sync(ec, acpi_ec_read_status(ec)); 320 ec_check_sci_sync(ec, acpi_ec_read_status(ec));
317 if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { 321 if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
318 msleep(1); 322 msleep(1);
319 /* it is safe to enable GPE outside of transaction */ 323 /*
324 * It is safe to enable the GPE outside of the transaction. Use
325 * acpi_set_gpe() for that, since we used it to disable the GPE
326 * above.
327 */
320 acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE); 328 acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE);
321 } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { 329 } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) {
322 pr_info(PREFIX "GPE storm detected, " 330 pr_info(PREFIX "GPE storm detected, "
@@ -1059,7 +1067,7 @@ error:
1059static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state) 1067static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state)
1060{ 1068{
1061 struct acpi_ec *ec = acpi_driver_data(device); 1069 struct acpi_ec *ec = acpi_driver_data(device);
1062 /* Stop using GPE */ 1070 /* Stop using the GPE, but keep it reference counted. */
1063 acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE); 1071 acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE);
1064 return 0; 1072 return 0;
1065} 1073}
@@ -1067,7 +1075,7 @@ static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state)
1067static int acpi_ec_resume(struct acpi_device *device) 1075static int acpi_ec_resume(struct acpi_device *device)
1068{ 1076{
1069 struct acpi_ec *ec = acpi_driver_data(device); 1077 struct acpi_ec *ec = acpi_driver_data(device);
1070 /* Enable use of GPE back */ 1078 /* Enable the GPE again, but don't reference count it once more. */
1071 acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE); 1079 acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE);
1072 return 0; 1080 return 0;
1073} 1081}