aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica
diff options
context:
space:
mode:
authorLv Zheng <lv.zheng@intel.com>2015-02-05 03:27:09 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-02-05 09:34:51 -0500
commiteb3d80f729e07394685239ddd137fbee5c13a2ea (patch)
tree55c7193f2abc208f824b6909cd91fbc20bb77776 /drivers/acpi/acpica
parent0d0988af81ac809b30f818f0c0f065327ff6423b (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.c105
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
184ACPI_EXPORT_SYMBOL(acpi_disable_gpe) 184ACPI_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 ******************************************************************************/
205acpi_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
242unlock_and_exit:
243 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
244 return_ACPI_STATUS(status);
245}
246
247ACPI_EXPORT_SYMBOL(acpi_set_gpe)
186 248
187/******************************************************************************* 249/*******************************************************************************
188 * 250 *
@@ -530,6 +592,49 @@ unlock_and_exit:
530 592
531ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) 593ACPI_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 ******************************************************************************/
611acpi_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
631unlock_and_exit:
632 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
633 return_ACPI_STATUS(status);
634}
635
636ACPI_EXPORT_SYMBOL(acpi_finish_gpe)
637
533/****************************************************************************** 638/******************************************************************************
534 * 639 *
535 * FUNCTION: acpi_disable_all_gpes 640 * FUNCTION: acpi_disable_all_gpes