aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-06-24 19:18:39 -0400
committerLen Brown <len.brown@intel.com>2010-07-06 22:34:26 -0400
commite8b6f970107cfc9c00cdcdb12ec6c7e135cf379f (patch)
tree20c66dfbc33bd5a0818a679ade11a32e267409ed /drivers/acpi
parentb76df673522d94e3eafcf16935b3d7e5dded3078 (diff)
ACPICA: Introduce acpi_gpe_wakeup()
ACPICA uses reference counters to avoid disabling GPEs too early in case they have been enabled for many times. This is done separately for runtime and for wakeup, but the wakeup GPE reference counter is not really necessary, because GPEs are only enabled to wake up the system at the hardware level by acpi_enter_sleep_state(). Thus it only is necessary to set the corresponding bits in the wakeup enable masks of these GPEs' registers right before the system enters a sleep state. Moreover, the GPE wakeup enable bits can only be set when the target sleep state of the system is known and they need to be cleared immediately after wakeup regardless of how many wakeup devices are associated with a given GPE. On the basis of the above observations, introduce function acpi_gpe_wakeup() to be used for setting or clearing the enable bit corresponding to a given GPE in its enable register's enable_for_wake mask. Modify the ACPI suspend and wakeup code the use acpi_gpe_wakeup() instead of acpi_{enable|disable}_gpe() to set and clear GPE enable bits in their registers' enable_for_wake masks during system transitions to a sleep state and back to the working state, respectively. [This will allow us to drop the third argument of acpi_{enable|disable}_gpe() and simplify the GPE handling code.] Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Len Brown <len.brown@intel.com> Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Lin Ming <ming.m.lin@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/acpica/evxfevnt.c67
-rw-r--r--drivers/acpi/sleep.c15
-rw-r--r--drivers/acpi/wakeup.c18
3 files changed, 81 insertions, 19 deletions
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index d97b8dce1668..d6a6d4a76592 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -308,6 +308,73 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe)
308 308
309/******************************************************************************* 309/*******************************************************************************
310 * 310 *
311 * FUNCTION: acpi_gpe_wakeup
312 *
313 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
314 * gpe_number - GPE level within the GPE block
315 * Action - Enable or Disable
316 *
317 * RETURN: Status
318 *
319 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit.
320 *
321 ******************************************************************************/
322acpi_status acpi_gpe_wakeup(acpi_handle gpe_device, u32 gpe_number, u8 action)
323{
324 acpi_status status = AE_OK;
325 struct acpi_gpe_event_info *gpe_event_info;
326 struct acpi_gpe_register_info *gpe_register_info;
327 acpi_cpu_flags flags;
328 u32 register_bit;
329
330 ACPI_FUNCTION_TRACE(acpi_gpe_wakeup);
331
332 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
333
334 /* Ensure that we have a valid GPE number */
335
336 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
337 if (!gpe_event_info) {
338 status = AE_BAD_PARAMETER;
339 goto unlock_and_exit;
340 }
341
342 gpe_register_info = gpe_event_info->register_info;
343 if (!gpe_register_info) {
344 status = AE_NOT_EXIST;
345 goto unlock_and_exit;
346 }
347
348 register_bit =
349 acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info);
350
351 /* Perform the action */
352
353 switch (action) {
354 case ACPI_GPE_ENABLE:
355 ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit);
356 break;
357
358 case ACPI_GPE_DISABLE:
359 ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
360 register_bit);
361 break;
362
363 default:
364 ACPI_ERROR((AE_INFO, "%u, Invalid action", action));
365 status = AE_BAD_PARAMETER;
366 break;
367 }
368
369unlock_and_exit:
370 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
371 return_ACPI_STATUS(status);
372}
373
374ACPI_EXPORT_SYMBOL(acpi_gpe_wakeup)
375
376/*******************************************************************************
377 *
311 * FUNCTION: acpi_enable_gpe 378 * FUNCTION: acpi_enable_gpe
312 * 379 *
313 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 380 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 5b7c52e4a00f..aaa1af55e280 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -664,18 +664,9 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
664 return -ENODEV; 664 return -ENODEV;
665 } 665 }
666 666
667 if (enable) { 667 error = enable ?
668 error = acpi_enable_wakeup_device_power(adev, 668 acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) :
669 acpi_target_sleep_state); 669 acpi_disable_wakeup_device_power(adev);
670 if (!error)
671 acpi_enable_gpe(adev->wakeup.gpe_device,
672 adev->wakeup.gpe_number,
673 ACPI_GPE_TYPE_WAKE);
674 } else {
675 acpi_disable_gpe(adev->wakeup.gpe_device, adev->wakeup.gpe_number,
676 ACPI_GPE_TYPE_WAKE);
677 error = acpi_disable_wakeup_device_power(adev);
678 }
679 if (!error) 670 if (!error)
680 dev_info(dev, "wake-up capability %s by ACPI\n", 671 dev_info(dev, "wake-up capability %s by ACPI\n",
681 enable ? "enabled" : "disabled"); 672 enable ? "enabled" : "disabled");
diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c
index 388747a7ef4f..c80537bc3234 100644
--- a/drivers/acpi/wakeup.c
+++ b/drivers/acpi/wakeup.c
@@ -64,13 +64,14 @@ void acpi_enable_wakeup_device(u8 sleep_state)
64 struct acpi_device *dev = 64 struct acpi_device *dev =
65 container_of(node, struct acpi_device, wakeup_list); 65 container_of(node, struct acpi_device, wakeup_list);
66 66
67 if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled 67 if (!dev->wakeup.flags.valid
68 || !(dev->wakeup.state.enabled || dev->wakeup.prepare_count)
68 || sleep_state > (u32) dev->wakeup.sleep_state) 69 || sleep_state > (u32) dev->wakeup.sleep_state)
69 continue; 70 continue;
70 71
71 /* The wake-up power should have been enabled already. */ 72 /* The wake-up power should have been enabled already. */
72 acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, 73 acpi_gpe_wakeup(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
73 ACPI_GPE_TYPE_WAKE); 74 ACPI_GPE_ENABLE);
74 } 75 }
75} 76}
76 77
@@ -89,13 +90,16 @@ void acpi_disable_wakeup_device(u8 sleep_state)
89 struct acpi_device *dev = 90 struct acpi_device *dev =
90 container_of(node, struct acpi_device, wakeup_list); 91 container_of(node, struct acpi_device, wakeup_list);
91 92
92 if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled 93 if (!dev->wakeup.flags.valid
94 || !(dev->wakeup.state.enabled || dev->wakeup.prepare_count)
93 || (sleep_state > (u32) dev->wakeup.sleep_state)) 95 || (sleep_state > (u32) dev->wakeup.sleep_state))
94 continue; 96 continue;
95 97
96 acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, 98 acpi_gpe_wakeup(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
97 ACPI_GPE_TYPE_WAKE); 99 ACPI_GPE_DISABLE);
98 acpi_disable_wakeup_device_power(dev); 100
101 if (dev->wakeup.state.enabled)
102 acpi_disable_wakeup_device_power(dev);
99 } 103 }
100} 104}
101 105