diff options
author | Lv Zheng <lv.zheng@intel.com> | 2015-02-05 03:27:09 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-02-05 09:34:51 -0500 |
commit | eb3d80f729e07394685239ddd137fbee5c13a2ea (patch) | |
tree | 55c7193f2abc208f824b6909cd91fbc20bb77776 /drivers/acpi/acpica | |
parent | 0d0988af81ac809b30f818f0c0f065327ff6423b (diff) |
ACPICA: Events: Introduce acpi_set_gpe()/acpi_finish_gpe() to reduce divergences
This can help to reduce source code differences between Linux and ACPICA
upstream. Further driver cleanups also require these APIs to eliminate GPE
storms.
1. acpi_set_gpe(): An API that driver should invoke in the case it wants
to disable/enable IRQ without honoring the reference
count implemented in the acpi_disable_gpe() and
acpi_enable_gpe(). Note that this API should only be
invoked inside a acpi_enable_gpe()/acpi_disable_gpe()
pair.
2. acpi_finish_gpe(): Drivers returned ACPI_REENABLE_GPE unset from the
GPE handler should use this API instead of
invoking acpi_set_gpe()/acpi_enable_gpe() to
re-enable the GPE.
The GPE APIs can be invoked inside of a GPE handler or in the task context
with a driver provided lock held. This driver provided lock is safe to be
held in the GPE handler by the driver.
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/acpica')
-rw-r--r-- | drivers/acpi/acpica/evxfgpe.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index b8af53bce74b..caaeb1a7bf4b 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c | |||
@@ -183,6 +183,68 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) | |||
183 | 183 | ||
184 | ACPI_EXPORT_SYMBOL(acpi_disable_gpe) | 184 | ACPI_EXPORT_SYMBOL(acpi_disable_gpe) |
185 | 185 | ||
186 | /******************************************************************************* | ||
187 | * | ||
188 | * FUNCTION: acpi_set_gpe | ||
189 | * | ||
190 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | ||
191 | * gpe_number - GPE level within the GPE block | ||
192 | * action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE | ||
193 | * | ||
194 | * RETURN: Status | ||
195 | * | ||
196 | * DESCRIPTION: Enable or disable an individual GPE. This function bypasses | ||
197 | * the reference count mechanism used in the acpi_enable_gpe and | ||
198 | * acpi_disable_gpe interfaces -- and should be used with care. | ||
199 | * | ||
200 | * Note: Typically used to disable a runtime GPE for short period of time, | ||
201 | * then re-enable it, without disturbing the existing reference counts. This | ||
202 | * is useful, for example, in the Embedded Controller (EC) driver. | ||
203 | * | ||
204 | ******************************************************************************/ | ||
205 | acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action) | ||
206 | { | ||
207 | struct acpi_gpe_event_info *gpe_event_info; | ||
208 | acpi_status status; | ||
209 | acpi_cpu_flags flags; | ||
210 | |||
211 | ACPI_FUNCTION_TRACE(acpi_set_gpe); | ||
212 | |||
213 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
214 | |||
215 | /* Ensure that we have a valid GPE number */ | ||
216 | |||
217 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | ||
218 | if (!gpe_event_info) { | ||
219 | status = AE_BAD_PARAMETER; | ||
220 | goto unlock_and_exit; | ||
221 | } | ||
222 | |||
223 | /* Perform the action */ | ||
224 | |||
225 | switch (action) { | ||
226 | case ACPI_GPE_ENABLE: | ||
227 | |||
228 | status = acpi_ev_enable_gpe(gpe_event_info); | ||
229 | break; | ||
230 | |||
231 | case ACPI_GPE_DISABLE: | ||
232 | |||
233 | status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); | ||
234 | break; | ||
235 | |||
236 | default: | ||
237 | |||
238 | status = AE_BAD_PARAMETER; | ||
239 | break; | ||
240 | } | ||
241 | |||
242 | unlock_and_exit: | ||
243 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
244 | return_ACPI_STATUS(status); | ||
245 | } | ||
246 | |||
247 | ACPI_EXPORT_SYMBOL(acpi_set_gpe) | ||
186 | 248 | ||
187 | /******************************************************************************* | 249 | /******************************************************************************* |
188 | * | 250 | * |
@@ -530,6 +592,49 @@ unlock_and_exit: | |||
530 | 592 | ||
531 | ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) | 593 | ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) |
532 | 594 | ||
595 | /******************************************************************************* | ||
596 | * | ||
597 | * FUNCTION: acpi_finish_gpe | ||
598 | * | ||
599 | * PARAMETERS: gpe_device - Namespace node for the GPE Block | ||
600 | * (NULL for FADT defined GPEs) | ||
601 | * gpe_number - GPE level within the GPE block | ||
602 | * | ||
603 | * RETURN: Status | ||
604 | * | ||
605 | * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE | ||
606 | * processing. Intended for use by asynchronous host-installed | ||
607 | * GPE handlers. The GPE is only reenabled if the enable_for_run bit | ||
608 | * is set in the GPE info. | ||
609 | * | ||
610 | ******************************************************************************/ | ||
611 | acpi_status acpi_finish_gpe(acpi_handle gpe_device, u32 gpe_number) | ||
612 | { | ||
613 | struct acpi_gpe_event_info *gpe_event_info; | ||
614 | acpi_status status; | ||
615 | acpi_cpu_flags flags; | ||
616 | |||
617 | ACPI_FUNCTION_TRACE(acpi_finish_gpe); | ||
618 | |||
619 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
620 | |||
621 | /* Ensure that we have a valid GPE number */ | ||
622 | |||
623 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | ||
624 | if (!gpe_event_info) { | ||
625 | status = AE_BAD_PARAMETER; | ||
626 | goto unlock_and_exit; | ||
627 | } | ||
628 | |||
629 | status = acpi_ev_finish_gpe(gpe_event_info); | ||
630 | |||
631 | unlock_and_exit: | ||
632 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
633 | return_ACPI_STATUS(status); | ||
634 | } | ||
635 | |||
636 | ACPI_EXPORT_SYMBOL(acpi_finish_gpe) | ||
637 | |||
533 | /****************************************************************************** | 638 | /****************************************************************************** |
534 | * | 639 | * |
535 | * FUNCTION: acpi_disable_all_gpes | 640 | * FUNCTION: acpi_disable_all_gpes |