brintos

brintos / linux-shallow public Read only

0
0
Text · 23.8 KiB · 934b201 Raw
850 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: evgpe - General Purpose Event handling and dispatch5 *6 * Copyright (C) 2000 - 2023, Intel Corp.7 *8 *****************************************************************************/9 10#include <acpi/acpi.h>11#include "accommon.h"12#include "acevents.h"13#include "acnamesp.h"14 15#define _COMPONENT          ACPI_EVENTS16ACPI_MODULE_NAME("evgpe")17#if (!ACPI_REDUCED_HARDWARE)	/* Entire module */18/* Local prototypes */19static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context);20 21static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context);22 23/*******************************************************************************24 *25 * FUNCTION:    acpi_ev_update_gpe_enable_mask26 *27 * PARAMETERS:  gpe_event_info          - GPE to update28 *29 * RETURN:      Status30 *31 * DESCRIPTION: Updates GPE register enable mask based upon whether there are32 *              runtime references to this GPE33 *34 ******************************************************************************/35 36acpi_status37acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info)38{39	struct acpi_gpe_register_info *gpe_register_info;40	u32 register_bit;41 42	ACPI_FUNCTION_TRACE(ev_update_gpe_enable_mask);43 44	gpe_register_info = gpe_event_info->register_info;45	if (!gpe_register_info) {46		return_ACPI_STATUS(AE_NOT_EXIST);47	}48 49	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);50 51	/* Clear the run bit up front */52 53	ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);54 55	/* Set the mask bit only if there are references to this GPE */56 57	if (gpe_event_info->runtime_count) {58		ACPI_SET_BIT(gpe_register_info->enable_for_run,59			     (u8)register_bit);60	}61 62	gpe_register_info->enable_mask = gpe_register_info->enable_for_run;63	return_ACPI_STATUS(AE_OK);64}65 66/*******************************************************************************67 *68 * FUNCTION:    acpi_ev_enable_gpe69 *70 * PARAMETERS:  gpe_event_info          - GPE to enable71 *72 * RETURN:      Status73 *74 * DESCRIPTION: Enable a GPE.75 *76 ******************************************************************************/77 78acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)79{80	acpi_status status;81 82	ACPI_FUNCTION_TRACE(ev_enable_gpe);83 84	/* Enable the requested GPE */85 86	status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);87	return_ACPI_STATUS(status);88}89 90/*******************************************************************************91 *92 * FUNCTION:    acpi_ev_mask_gpe93 *94 * PARAMETERS:  gpe_event_info          - GPE to be blocked/unblocked95 *              is_masked               - Whether the GPE is masked or not96 *97 * RETURN:      Status98 *99 * DESCRIPTION: Unconditionally mask/unmask a GPE during runtime.100 *101 ******************************************************************************/102 103acpi_status104acpi_ev_mask_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 is_masked)105{106	struct acpi_gpe_register_info *gpe_register_info;107	u32 register_bit;108 109	ACPI_FUNCTION_TRACE(ev_mask_gpe);110 111	gpe_register_info = gpe_event_info->register_info;112	if (!gpe_register_info) {113		return_ACPI_STATUS(AE_NOT_EXIST);114	}115 116	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);117 118	/* Perform the action */119 120	if (is_masked) {121		if (register_bit & gpe_register_info->mask_for_run) {122			return_ACPI_STATUS(AE_BAD_PARAMETER);123		}124 125		(void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);126		ACPI_SET_BIT(gpe_register_info->mask_for_run, (u8)register_bit);127	} else {128		if (!(register_bit & gpe_register_info->mask_for_run)) {129			return_ACPI_STATUS(AE_BAD_PARAMETER);130		}131 132		ACPI_CLEAR_BIT(gpe_register_info->mask_for_run,133			       (u8)register_bit);134		if (gpe_event_info->runtime_count135		    && !gpe_event_info->disable_for_dispatch) {136			(void)acpi_hw_low_set_gpe(gpe_event_info,137						  ACPI_GPE_ENABLE);138		}139	}140 141	return_ACPI_STATUS(AE_OK);142}143 144/*******************************************************************************145 *146 * FUNCTION:    acpi_ev_add_gpe_reference147 *148 * PARAMETERS:  gpe_event_info          - Add a reference to this GPE149 *              clear_on_enable         - Clear GPE status before enabling it150 *151 * RETURN:      Status152 *153 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is154 *              hardware-enabled.155 *156 ******************************************************************************/157 158acpi_status159acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info,160			  u8 clear_on_enable)161{162	acpi_status status = AE_OK;163 164	ACPI_FUNCTION_TRACE(ev_add_gpe_reference);165 166	if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) {167		return_ACPI_STATUS(AE_LIMIT);168	}169 170	gpe_event_info->runtime_count++;171	if (gpe_event_info->runtime_count == 1) {172 173		/* Enable on first reference */174 175		if (clear_on_enable) {176			(void)acpi_hw_clear_gpe(gpe_event_info);177		}178 179		status = acpi_ev_update_gpe_enable_mask(gpe_event_info);180		if (ACPI_SUCCESS(status)) {181			status = acpi_ev_enable_gpe(gpe_event_info);182		}183 184		if (ACPI_FAILURE(status)) {185			gpe_event_info->runtime_count--;186		}187	}188 189	return_ACPI_STATUS(status);190}191 192/*******************************************************************************193 *194 * FUNCTION:    acpi_ev_remove_gpe_reference195 *196 * PARAMETERS:  gpe_event_info          - Remove a reference to this GPE197 *198 * RETURN:      Status199 *200 * DESCRIPTION: Remove a reference to a GPE. When the last reference is201 *              removed, the GPE is hardware-disabled.202 *203 ******************************************************************************/204 205acpi_status206acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)207{208	acpi_status status = AE_OK;209 210	ACPI_FUNCTION_TRACE(ev_remove_gpe_reference);211 212	if (!gpe_event_info->runtime_count) {213		return_ACPI_STATUS(AE_LIMIT);214	}215 216	gpe_event_info->runtime_count--;217	if (!gpe_event_info->runtime_count) {218 219		/* Disable on last reference */220 221		status = acpi_ev_update_gpe_enable_mask(gpe_event_info);222		if (ACPI_SUCCESS(status)) {223			status =224			    acpi_hw_low_set_gpe(gpe_event_info,225						ACPI_GPE_DISABLE);226		}227 228		if (ACPI_FAILURE(status)) {229			gpe_event_info->runtime_count++;230		}231	}232 233	return_ACPI_STATUS(status);234}235 236/*******************************************************************************237 *238 * FUNCTION:    acpi_ev_low_get_gpe_info239 *240 * PARAMETERS:  gpe_number          - Raw GPE number241 *              gpe_block           - A GPE info block242 *243 * RETURN:      A GPE event_info struct. NULL if not a valid GPE (The gpe_number244 *              is not within the specified GPE block)245 *246 * DESCRIPTION: Returns the event_info struct associated with this GPE. This is247 *              the low-level implementation of ev_get_gpe_event_info.248 *249 ******************************************************************************/250 251struct acpi_gpe_event_info *acpi_ev_low_get_gpe_info(u32 gpe_number,252						     struct acpi_gpe_block_info253						     *gpe_block)254{255	u32 gpe_index;256 257	/*258	 * Validate that the gpe_number is within the specified gpe_block.259	 * (Two steps)260	 */261	if (!gpe_block || (gpe_number < gpe_block->block_base_number)) {262		return (NULL);263	}264 265	gpe_index = gpe_number - gpe_block->block_base_number;266	if (gpe_index >= gpe_block->gpe_count) {267		return (NULL);268	}269 270	return (&gpe_block->event_info[gpe_index]);271}272 273 274/*******************************************************************************275 *276 * FUNCTION:    acpi_ev_get_gpe_event_info277 *278 * PARAMETERS:  gpe_device          - Device node. NULL for GPE0/GPE1279 *              gpe_number          - Raw GPE number280 *281 * RETURN:      A GPE event_info struct. NULL if not a valid GPE282 *283 * DESCRIPTION: Returns the event_info struct associated with this GPE.284 *              Validates the gpe_block and the gpe_number285 *286 *              Should be called only when the GPE lists are semaphore locked287 *              and not subject to change.288 *289 ******************************************************************************/290 291struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,292						       u32 gpe_number)293{294	union acpi_operand_object *obj_desc;295	struct acpi_gpe_event_info *gpe_info;296	u32 i;297 298	ACPI_FUNCTION_ENTRY();299 300	/* A NULL gpe_device means use the FADT-defined GPE block(s) */301 302	if (!gpe_device) {303 304		/* Examine GPE Block 0 and 1 (These blocks are permanent) */305 306		for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) {307			gpe_info = acpi_ev_low_get_gpe_info(gpe_number,308							    acpi_gbl_gpe_fadt_blocks309							    [i]);310			if (gpe_info) {311				return (gpe_info);312			}313		}314 315		/* The gpe_number was not in the range of either FADT GPE block */316 317		return (NULL);318	}319 320	/* A Non-NULL gpe_device means this is a GPE Block Device */321 322	obj_desc =323	    acpi_ns_get_attached_object((struct acpi_namespace_node *)324					       gpe_device);325	if (!obj_desc || !obj_desc->device.gpe_block) {326		return (NULL);327	}328 329	return (acpi_ev_low_get_gpe_info330		(gpe_number, obj_desc->device.gpe_block));331}332 333/*******************************************************************************334 *335 * FUNCTION:    acpi_ev_gpe_detect336 *337 * PARAMETERS:  gpe_xrupt_list      - Interrupt block for this interrupt.338 *                                    Can have multiple GPE blocks attached.339 *340 * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED341 *342 * DESCRIPTION: Detect if any GP events have occurred. This function is343 *              executed at interrupt level.344 *345 ******************************************************************************/346 347u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list)348{349	struct acpi_gpe_block_info *gpe_block;350	struct acpi_namespace_node *gpe_device;351	struct acpi_gpe_register_info *gpe_register_info;352	struct acpi_gpe_event_info *gpe_event_info;353	u32 gpe_number;354	u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;355	acpi_cpu_flags flags;356	u32 i;357	u32 j;358 359	ACPI_FUNCTION_NAME(ev_gpe_detect);360 361	/* Check for the case where there are no GPEs */362 363	if (!gpe_xrupt_list) {364		return (int_status);365	}366 367	/*368	 * We need to obtain the GPE lock for both the data structs and registers369	 * Note: Not necessary to obtain the hardware lock, since the GPE370	 * registers are owned by the gpe_lock.371	 */372	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);373 374	/* Examine all GPE blocks attached to this interrupt level */375 376	gpe_block = gpe_xrupt_list->gpe_block_list_head;377	while (gpe_block) {378		gpe_device = gpe_block->node;379 380		/*381		 * Read all of the 8-bit GPE status and enable registers in this GPE382		 * block, saving all of them. Find all currently active GP events.383		 */384		for (i = 0; i < gpe_block->register_count; i++) {385 386			/* Get the next status/enable pair */387 388			gpe_register_info = &gpe_block->register_info[i];389 390			/*391			 * Optimization: If there are no GPEs enabled within this392			 * register, we can safely ignore the entire register.393			 */394			if (!(gpe_register_info->enable_for_run |395			      gpe_register_info->enable_for_wake)) {396				ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,397						  "Ignore disabled registers for GPE %02X-%02X: "398						  "RunEnable=%02X, WakeEnable=%02X\n",399						  gpe_register_info->400						  base_gpe_number,401						  gpe_register_info->402						  base_gpe_number +403						  (ACPI_GPE_REGISTER_WIDTH - 1),404						  gpe_register_info->405						  enable_for_run,406						  gpe_register_info->407						  enable_for_wake));408				continue;409			}410 411			/* Now look at the individual GPEs in this byte register */412 413			for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {414 415				/* Detect and dispatch one GPE bit */416 417				gpe_event_info =418				    &gpe_block->419				    event_info[((acpi_size)i *420						ACPI_GPE_REGISTER_WIDTH) + j];421				gpe_number =422				    j + gpe_register_info->base_gpe_number;423				acpi_os_release_lock(acpi_gbl_gpe_lock, flags);424				int_status |=425				    acpi_ev_detect_gpe(gpe_device,426						       gpe_event_info,427						       gpe_number);428				flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);429			}430		}431 432		gpe_block = gpe_block->next;433	}434 435	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);436	return (int_status);437}438 439/*******************************************************************************440 *441 * FUNCTION:    acpi_ev_asynch_execute_gpe_method442 *443 * PARAMETERS:  Context (gpe_event_info) - Info for this GPE444 *445 * RETURN:      None446 *447 * DESCRIPTION: Perform the actual execution of a GPE control method. This448 *              function is called from an invocation of acpi_os_execute and449 *              therefore does NOT execute at interrupt level - so that450 *              the control method itself is not executed in the context of451 *              an interrupt handler.452 *453 ******************************************************************************/454 455static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)456{457	struct acpi_gpe_event_info *gpe_event_info = context;458	acpi_status status = AE_OK;459	struct acpi_evaluate_info *info;460	struct acpi_gpe_notify_info *notify;461 462	ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method);463 464	/* Do the correct dispatch - normal method or implicit notify */465 466	switch (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags)) {467	case ACPI_GPE_DISPATCH_NOTIFY:468		/*469		 * Implicit notify.470		 * Dispatch a DEVICE_WAKE notify to the appropriate handler.471		 * NOTE: the request is queued for execution after this method472		 * completes. The notify handlers are NOT invoked synchronously473		 * from this thread -- because handlers may in turn run other474		 * control methods.475		 *476		 * June 2012: Expand implicit notify mechanism to support477		 * notifies on multiple device objects.478		 */479		notify = gpe_event_info->dispatch.notify_list;480		while (ACPI_SUCCESS(status) && notify) {481			status =482			    acpi_ev_queue_notify_request(notify->device_node,483							 ACPI_NOTIFY_DEVICE_WAKE);484 485			notify = notify->next;486		}487 488		break;489 490	case ACPI_GPE_DISPATCH_METHOD:491 492		/* Allocate the evaluation information block */493 494		info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));495		if (!info) {496			status = AE_NO_MEMORY;497		} else {498			/*499			 * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the500			 * _Lxx/_Exx control method that corresponds to this GPE501			 */502			info->prefix_node =503			    gpe_event_info->dispatch.method_node;504			info->flags = ACPI_IGNORE_RETURN_VALUE;505 506			status = acpi_ns_evaluate(info);507			ACPI_FREE(info);508		}509 510		if (ACPI_FAILURE(status)) {511			ACPI_EXCEPTION((AE_INFO, status,512					"while evaluating GPE method [%4.4s]",513					acpi_ut_get_node_name(gpe_event_info->514							      dispatch.515							      method_node)));516		}517		break;518 519	default:520 521		goto error_exit;	/* Should never happen */522	}523 524	/* Defer enabling of GPE until all notify handlers are done */525 526	status = acpi_os_execute(OSL_NOTIFY_HANDLER,527				 acpi_ev_asynch_enable_gpe, gpe_event_info);528	if (ACPI_SUCCESS(status)) {529		return_VOID;530	}531 532error_exit:533	acpi_ev_asynch_enable_gpe(gpe_event_info);534	return_VOID;535}536 537 538/*******************************************************************************539 *540 * FUNCTION:    acpi_ev_asynch_enable_gpe541 *542 * PARAMETERS:  Context (gpe_event_info) - Info for this GPE543 *              Callback from acpi_os_execute544 *545 * RETURN:      None546 *547 * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to548 *              complete (i.e., finish execution of Notify)549 *550 ******************************************************************************/551 552static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context)553{554	struct acpi_gpe_event_info *gpe_event_info = context;555	acpi_cpu_flags flags;556 557	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);558	(void)acpi_ev_finish_gpe(gpe_event_info);559	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);560 561	return;562}563 564 565/*******************************************************************************566 *567 * FUNCTION:    acpi_ev_finish_gpe568 *569 * PARAMETERS:  gpe_event_info      - Info for this GPE570 *571 * RETURN:      Status572 *573 * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution574 *              of a GPE method or a synchronous or asynchronous GPE handler.575 *576 ******************************************************************************/577 578acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info)579{580	acpi_status status;581 582	if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==583	    ACPI_GPE_LEVEL_TRIGGERED) {584		/*585		 * GPE is level-triggered, we clear the GPE status bit after586		 * handling the event.587		 */588		status = acpi_hw_clear_gpe(gpe_event_info);589		if (ACPI_FAILURE(status)) {590			return (status);591		}592	}593 594	/*595	 * Enable this GPE, conditionally. This means that the GPE will596	 * only be physically enabled if the enable_mask bit is set597	 * in the event_info.598	 */599	(void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE);600	gpe_event_info->disable_for_dispatch = FALSE;601	return (AE_OK);602}603 604 605/*******************************************************************************606 *607 * FUNCTION:    acpi_ev_detect_gpe608 *609 * PARAMETERS:  gpe_device          - Device node. NULL for GPE0/GPE1610 *              gpe_event_info      - Info for this GPE611 *              gpe_number          - Number relative to the parent GPE block612 *613 * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED614 *615 * DESCRIPTION: Detect and dispatch a General Purpose Event to either a function616 *              (e.g. EC) or method (e.g. _Lxx/_Exx) handler.617 * NOTE:        GPE is W1C, so it is possible to handle a single GPE from both618 *              task and irq context in parallel as long as the process to619 *              detect and mask the GPE is atomic.620 *              However the atomicity of ACPI_GPE_DISPATCH_RAW_HANDLER is621 *              dependent on the raw handler itself.622 *623 ******************************************************************************/624 625u32626acpi_ev_detect_gpe(struct acpi_namespace_node *gpe_device,627		   struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)628{629	u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;630	u8 enabled_status_byte;631	u64 status_reg;632	u64 enable_reg;633	u32 register_bit;634	struct acpi_gpe_register_info *gpe_register_info;635	struct acpi_gpe_handler_info *gpe_handler_info;636	acpi_cpu_flags flags;637	acpi_status status;638 639	ACPI_FUNCTION_TRACE(ev_gpe_detect);640 641	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);642 643	if (!gpe_event_info) {644		gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);645		if (!gpe_event_info)646			goto error_exit;647	}648 649	/* Get the info block for the entire GPE register */650 651	gpe_register_info = gpe_event_info->register_info;652 653	/* Get the register bitmask for this GPE */654 655	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);656 657	/* GPE currently enabled (enable bit == 1)? */658 659	status = acpi_hw_gpe_read(&enable_reg, &gpe_register_info->enable_address);660	if (ACPI_FAILURE(status)) {661		goto error_exit;662	}663 664	/* GPE currently active (status bit == 1)? */665 666	status = acpi_hw_gpe_read(&status_reg, &gpe_register_info->status_address);667	if (ACPI_FAILURE(status)) {668		goto error_exit;669	}670 671	/* Check if there is anything active at all in this GPE */672 673	ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,674			  "Read registers for GPE %02X: Status=%02X, Enable=%02X, "675			  "RunEnable=%02X, WakeEnable=%02X\n",676			  gpe_number,677			  (u32)(status_reg & register_bit),678			  (u32)(enable_reg & register_bit),679			  gpe_register_info->enable_for_run,680			  gpe_register_info->enable_for_wake));681 682	enabled_status_byte = (u8)(status_reg & enable_reg);683	if (!(enabled_status_byte & register_bit)) {684		goto error_exit;685	}686 687	/* Invoke global event handler if present */688 689	acpi_gpe_count++;690	if (acpi_gbl_global_event_handler) {691		acpi_gbl_global_event_handler(ACPI_EVENT_TYPE_GPE,692					      gpe_device, gpe_number,693					      acpi_gbl_global_event_handler_context);694	}695 696	/* Found an active GPE */697 698	if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==699	    ACPI_GPE_DISPATCH_RAW_HANDLER) {700 701		/* Dispatch the event to a raw handler */702 703		gpe_handler_info = gpe_event_info->dispatch.handler;704 705		/*706		 * There is no protection around the namespace node707		 * and the GPE handler to ensure a safe destruction708		 * because:709		 * 1. The namespace node is expected to always710		 *    exist after loading a table.711		 * 2. The GPE handler is expected to be flushed by712		 *    acpi_os_wait_events_complete() before the713		 *    destruction.714		 */715		acpi_os_release_lock(acpi_gbl_gpe_lock, flags);716		int_status |=717		    gpe_handler_info->address(gpe_device, gpe_number,718					      gpe_handler_info->context);719		flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);720	} else {721		/* Dispatch the event to a standard handler or method. */722 723		int_status |= acpi_ev_gpe_dispatch(gpe_device,724						   gpe_event_info, gpe_number);725	}726 727error_exit:728	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);729	return (int_status);730}731 732/*******************************************************************************733 *734 * FUNCTION:    acpi_ev_gpe_dispatch735 *736 * PARAMETERS:  gpe_device          - Device node. NULL for GPE0/GPE1737 *              gpe_event_info      - Info for this GPE738 *              gpe_number          - Number relative to the parent GPE block739 *740 * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED741 *742 * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)743 *              or method (e.g. _Lxx/_Exx) handler.744 *745 ******************************************************************************/746 747u32748acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,749		     struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)750{751	acpi_status status;752	u32 return_value;753 754	ACPI_FUNCTION_TRACE(ev_gpe_dispatch);755 756	/*757	 * Always disable the GPE so that it does not keep firing before758	 * any asynchronous activity completes (either from the execution759	 * of a GPE method or an asynchronous GPE handler.)760	 *761	 * If there is no handler or method to run, just disable the762	 * GPE and leave it disabled permanently to prevent further such763	 * pointless events from firing.764	 */765	status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);766	if (ACPI_FAILURE(status)) {767		ACPI_EXCEPTION((AE_INFO, status,768				"Unable to disable GPE %02X", gpe_number));769		return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);770	}771 772	/*773	 * If edge-triggered, clear the GPE status bit now. Note that774	 * level-triggered events are cleared after the GPE is serviced.775	 */776	if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==777	    ACPI_GPE_EDGE_TRIGGERED) {778		status = acpi_hw_clear_gpe(gpe_event_info);779		if (ACPI_FAILURE(status)) {780			ACPI_EXCEPTION((AE_INFO, status,781					"Unable to clear GPE %02X",782					gpe_number));783			(void)acpi_hw_low_set_gpe(gpe_event_info,784						  ACPI_GPE_CONDITIONAL_ENABLE);785			return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);786		}787	}788 789	gpe_event_info->disable_for_dispatch = TRUE;790 791	/*792	 * Dispatch the GPE to either an installed handler or the control793	 * method associated with this GPE (_Lxx or _Exx). If a handler794	 * exists, we invoke it and do not attempt to run the method.795	 * If there is neither a handler nor a method, leave the GPE796	 * disabled.797	 */798	switch (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags)) {799	case ACPI_GPE_DISPATCH_HANDLER:800 801		/* Invoke the installed handler (at interrupt level) */802 803		return_value =804		    gpe_event_info->dispatch.handler->address(gpe_device,805							      gpe_number,806							      gpe_event_info->807							      dispatch.handler->808							      context);809 810		/* If requested, clear (if level-triggered) and re-enable the GPE */811 812		if (return_value & ACPI_REENABLE_GPE) {813			(void)acpi_ev_finish_gpe(gpe_event_info);814		}815		break;816 817	case ACPI_GPE_DISPATCH_METHOD:818	case ACPI_GPE_DISPATCH_NOTIFY:819		/*820		 * Execute the method associated with the GPE821		 * NOTE: Level-triggered GPEs are cleared after the method completes.822		 */823		status = acpi_os_execute(OSL_GPE_HANDLER,824					 acpi_ev_asynch_execute_gpe_method,825					 gpe_event_info);826		if (ACPI_FAILURE(status)) {827			ACPI_EXCEPTION((AE_INFO, status,828					"Unable to queue handler for GPE %02X - event disabled",829					gpe_number));830		}831		break;832 833	default:834		/*835		 * No handler or method to run!836		 * 03/2010: This case should no longer be possible. We will not allow837		 * a GPE to be enabled if it has no handler or method.838		 */839		ACPI_ERROR((AE_INFO,840			    "No handler or method for GPE %02X, disabling event",841			    gpe_number));842 843		break;844	}845 846	return_UINT32(ACPI_INTERRUPT_HANDLED);847}848 849#endif				/* !ACPI_REDUCED_HARDWARE */850