forked from mirrors/linux
		
	ACPICA: Implicit notify support
This feature provides an automatic device notification for wake devices when a wakeup GPE occurs and there is no corresponding GPE method or handler. Rather than ignoring such a GPE, an implicit AML Notify operation is performed on the parent device object. This feature is not part of the ACPI specification and is provided for Windows compatibility only. Signed-off-by: Lin Ming <ming.m.lin@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
This commit is contained in:
		
							parent
							
								
									5a284cd75d
								
							
						
					
					
						commit
						bba63a296f
					
				
					 10 changed files with 184 additions and 104 deletions
				
			
		| 
						 | 
					@ -91,6 +91,8 @@ struct acpi_gpe_event_info *acpi_ev_low_get_gpe_info(u32 gpe_number,
 | 
				
			||||||
						     struct acpi_gpe_block_info
 | 
											     struct acpi_gpe_block_info
 | 
				
			||||||
						     *gpe_block);
 | 
											     *gpe_block);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * evgpeblk - Upper-level GPE block support
 | 
					 * evgpeblk - Upper-level GPE block support
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -419,6 +419,7 @@ struct acpi_gpe_handler_info {
 | 
				
			||||||
union acpi_gpe_dispatch_info {
 | 
					union acpi_gpe_dispatch_info {
 | 
				
			||||||
	struct acpi_namespace_node *method_node;	/* Method node for this GPE level */
 | 
						struct acpi_namespace_node *method_node;	/* Method node for this GPE level */
 | 
				
			||||||
	struct acpi_gpe_handler_info *handler;  /* Installed GPE handler */
 | 
						struct acpi_gpe_handler_info *handler;  /* Installed GPE handler */
 | 
				
			||||||
 | 
						struct acpi_namespace_node *device_node;        /* Parent _PRW device for implicit notify */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -115,12 +115,13 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
 | 
				
			||||||
	ACPI_FUNCTION_TRACE(ev_enable_gpe);
 | 
						ACPI_FUNCTION_TRACE(ev_enable_gpe);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * We will only allow a GPE to be enabled if it has either an
 | 
						 * We will only allow a GPE to be enabled if it has either an associated
 | 
				
			||||||
	 * associated method (_Lxx/_Exx) or a handler. Otherwise, the
 | 
						 * method (_Lxx/_Exx) or a handler, or is using the implicit notify
 | 
				
			||||||
	 * GPE will be immediately disabled by acpi_ev_gpe_dispatch the
 | 
						 * feature. Otherwise, the GPE will be immediately disabled by
 | 
				
			||||||
	 * first time it fires.
 | 
						 * acpi_ev_gpe_dispatch the first time it fires.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
 | 
						if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
 | 
				
			||||||
 | 
						    ACPI_GPE_DISPATCH_NONE) {
 | 
				
			||||||
		return_ACPI_STATUS(AE_NO_HANDLER);
 | 
							return_ACPI_STATUS(AE_NO_HANDLER);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -486,12 +487,26 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
 | 
				
			||||||
		return_VOID;
 | 
							return_VOID;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Do the correct dispatch - normal method or implicit notify */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (local_gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) {
 | 
				
			||||||
 | 
						case ACPI_GPE_DISPATCH_NOTIFY:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
	 * Must check for control method type dispatch one more time to avoid a
 | 
							 * Implicit notify.
 | 
				
			||||||
	 * race with ev_gpe_install_handler
 | 
							 * Dispatch a DEVICE_WAKE notify to the appropriate handler.
 | 
				
			||||||
 | 
							 * NOTE: the request is queued for execution after this method
 | 
				
			||||||
 | 
							 * completes. The notify handlers are NOT invoked synchronously
 | 
				
			||||||
 | 
							 * from this thread -- because handlers may in turn run other
 | 
				
			||||||
 | 
							 * control methods.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
	if ((local_gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
 | 
							status =
 | 
				
			||||||
	    ACPI_GPE_DISPATCH_METHOD) {
 | 
							    acpi_ev_queue_notify_request(local_gpe_event_info->dispatch.
 | 
				
			||||||
 | 
											 device_node,
 | 
				
			||||||
 | 
											 ACPI_NOTIFY_DEVICE_WAKE);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case ACPI_GPE_DISPATCH_METHOD:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Allocate the evaluation information block */
 | 
							/* Allocate the evaluation information block */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -518,6 +533,11 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
 | 
				
			||||||
					(local_gpe_event_info->dispatch.
 | 
										(local_gpe_event_info->dispatch.
 | 
				
			||||||
					 method_node)));
 | 
										 method_node)));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return_VOID;    /* Should never happen */
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Defer enabling of GPE until all notify handlers are done */
 | 
						/* Defer enabling of GPE until all notify handlers are done */
 | 
				
			||||||
| 
						 | 
					@ -531,6 +551,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
 | 
				
			||||||
	return_VOID;
 | 
						return_VOID;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*******************************************************************************
 | 
					/*******************************************************************************
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * FUNCTION:    acpi_ev_asynch_enable_gpe
 | 
					 * FUNCTION:    acpi_ev_asynch_enable_gpe
 | 
				
			||||||
| 
						 | 
					@ -541,38 +562,60 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
 | 
				
			||||||
 * RETURN:      None
 | 
					 * RETURN:      None
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
 | 
					 * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
 | 
				
			||||||
 *              complete.
 | 
					 *              complete (i.e., finish execution of Notify)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 ******************************************************************************/
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context)
 | 
					static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct acpi_gpe_event_info *gpe_event_info = context;
 | 
						struct acpi_gpe_event_info *gpe_event_info = context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						(void)acpi_ev_finish_gpe(gpe_event_info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ACPI_FREE(gpe_event_info);
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * FUNCTION:    acpi_ev_finish_gpe
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * PARAMETERS:  gpe_event_info      - Info for this GPE
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * RETURN:      Status
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution
 | 
				
			||||||
 | 
					 *              of a GPE method or a synchronous or asynchronous GPE handler.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
	acpi_status status;
 | 
						acpi_status status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
 | 
						if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
 | 
				
			||||||
	    ACPI_GPE_LEVEL_TRIGGERED) {
 | 
						    ACPI_GPE_LEVEL_TRIGGERED) {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * GPE is level-triggered, we clear the GPE status bit after handling
 | 
							 * GPE is level-triggered, we clear the GPE status bit after
 | 
				
			||||||
		 * the event.
 | 
							 * handling the event.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		status = acpi_hw_clear_gpe(gpe_event_info);
 | 
							status = acpi_hw_clear_gpe(gpe_event_info);
 | 
				
			||||||
		if (ACPI_FAILURE(status)) {
 | 
							if (ACPI_FAILURE(status)) {
 | 
				
			||||||
			goto exit;
 | 
								return (status);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Enable this GPE, conditionally. This means that the GPE will only be
 | 
						 * Enable this GPE, conditionally. This means that the GPE will
 | 
				
			||||||
	 * physically enabled if the enable_for_run bit is set in the event_info
 | 
						 * only be physically enabled if the enable_for_run bit is set
 | 
				
			||||||
 | 
						 * in the event_info.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	(void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE);
 | 
						(void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE);
 | 
				
			||||||
 | 
						return (AE_OK);
 | 
				
			||||||
exit:
 | 
					 | 
				
			||||||
	ACPI_FREE(gpe_event_info);
 | 
					 | 
				
			||||||
	return;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*******************************************************************************
 | 
					/*******************************************************************************
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * FUNCTION:    acpi_ev_gpe_dispatch
 | 
					 * FUNCTION:    acpi_ev_gpe_dispatch
 | 
				
			||||||
| 
						 | 
					@ -595,6 +638,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
 | 
				
			||||||
		    struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
 | 
							    struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	acpi_status status;
 | 
						acpi_status status;
 | 
				
			||||||
 | 
						u32 return_value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ACPI_FUNCTION_TRACE(ev_gpe_dispatch);
 | 
						ACPI_FUNCTION_TRACE(ev_gpe_dispatch);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -616,55 +660,50 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Dispatch the GPE to either an installed handler, or the control method
 | 
						 * Always disable the GPE so that it does not keep firing before
 | 
				
			||||||
	 * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke
 | 
						 * any asynchronous activity completes (either from the execution
 | 
				
			||||||
	 * it and do not attempt to run the method. If there is neither a handler
 | 
						 * of a GPE method or an asynchronous GPE handler.)
 | 
				
			||||||
	 * nor a method, we disable this GPE to prevent further such pointless
 | 
						 *
 | 
				
			||||||
	 * events from firing.
 | 
						 * If there is no handler or method to run, just disable the
 | 
				
			||||||
	 */
 | 
						 * GPE and leave it disabled permanently to prevent further such
 | 
				
			||||||
	switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) {
 | 
						 * pointless events from firing.
 | 
				
			||||||
	case ACPI_GPE_DISPATCH_HANDLER:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * Invoke the installed handler (at interrupt level)
 | 
					 | 
				
			||||||
		 * Ignore return status for now.
 | 
					 | 
				
			||||||
		 * TBD: leave GPE disabled on error?
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		(void)gpe_event_info->dispatch.handler->address(gpe_device,
 | 
					 | 
				
			||||||
								gpe_number,
 | 
					 | 
				
			||||||
								gpe_event_info->
 | 
					 | 
				
			||||||
								dispatch.
 | 
					 | 
				
			||||||
								handler->
 | 
					 | 
				
			||||||
								context);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* It is now safe to clear level-triggered events. */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
 | 
					 | 
				
			||||||
		    ACPI_GPE_LEVEL_TRIGGERED) {
 | 
					 | 
				
			||||||
			status = acpi_hw_clear_gpe(gpe_event_info);
 | 
					 | 
				
			||||||
			if (ACPI_FAILURE(status)) {
 | 
					 | 
				
			||||||
				ACPI_EXCEPTION((AE_INFO, status,
 | 
					 | 
				
			||||||
					"Unable to clear GPE[0x%2X]",
 | 
					 | 
				
			||||||
						gpe_number));
 | 
					 | 
				
			||||||
				return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case ACPI_GPE_DISPATCH_METHOD:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * Disable the GPE, so it doesn't keep firing before the method has a
 | 
					 | 
				
			||||||
		 * chance to run (it runs asynchronously with interrupts enabled).
 | 
					 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
 | 
						status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
 | 
				
			||||||
	if (ACPI_FAILURE(status)) {
 | 
						if (ACPI_FAILURE(status)) {
 | 
				
			||||||
		ACPI_EXCEPTION((AE_INFO, status,
 | 
							ACPI_EXCEPTION((AE_INFO, status,
 | 
				
			||||||
					"Unable to disable GPE[0x%2X]",
 | 
									"Unable to disable GPE%02X", gpe_number));
 | 
				
			||||||
					gpe_number));
 | 
					 | 
				
			||||||
		return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
 | 
							return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Dispatch the GPE to either an installed handler or the control
 | 
				
			||||||
 | 
						 * method associated with this GPE (_Lxx or _Exx). If a handler
 | 
				
			||||||
 | 
						 * exists, we invoke it and do not attempt to run the method.
 | 
				
			||||||
 | 
						 * If there is neither a handler nor a method, leave the GPE
 | 
				
			||||||
 | 
						 * disabled.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) {
 | 
				
			||||||
 | 
						case ACPI_GPE_DISPATCH_HANDLER:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Invoke the installed handler (at interrupt level) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return_value =
 | 
				
			||||||
 | 
							    gpe_event_info->dispatch.handler->address(gpe_device,
 | 
				
			||||||
 | 
												      gpe_number,
 | 
				
			||||||
 | 
												      gpe_event_info->
 | 
				
			||||||
 | 
												      dispatch.handler->
 | 
				
			||||||
 | 
												      context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* If requested, clear (if level-triggered) and reenable the GPE */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (return_value & ACPI_REENABLE_GPE) {
 | 
				
			||||||
 | 
								(void)acpi_ev_finish_gpe(gpe_event_info);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case ACPI_GPE_DISPATCH_METHOD:
 | 
				
			||||||
 | 
						case ACPI_GPE_DISPATCH_NOTIFY:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Execute the method associated with the GPE
 | 
							 * Execute the method associated with the GPE
 | 
				
			||||||
		 * NOTE: Level-triggered GPEs are cleared after the method completes.
 | 
							 * NOTE: Level-triggered GPEs are cleared after the method completes.
 | 
				
			||||||
| 
						 | 
					@ -690,17 +729,6 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
 | 
				
			||||||
			    "No handler or method for GPE[0x%2X], disabling event",
 | 
								    "No handler or method for GPE[0x%2X], disabling event",
 | 
				
			||||||
			    gpe_number));
 | 
								    gpe_number));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * Disable the GPE. The GPE will remain disabled a handler
 | 
					 | 
				
			||||||
		 * is installed or ACPICA is restarted.
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
 | 
					 | 
				
			||||||
		if (ACPI_FAILURE(status)) {
 | 
					 | 
				
			||||||
			ACPI_EXCEPTION((AE_INFO, status,
 | 
					 | 
				
			||||||
					"Unable to disable GPE[0x%2X]",
 | 
					 | 
				
			||||||
					gpe_number));
 | 
					 | 
				
			||||||
			return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -472,9 +472,14 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 | 
				
			||||||
			gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
 | 
								gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
 | 
				
			||||||
			gpe_event_info = &gpe_block->event_info[gpe_index];
 | 
								gpe_event_info = &gpe_block->event_info[gpe_index];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/* Ignore GPEs that have no corresponding _Lxx/_Exx method */
 | 
								/*
 | 
				
			||||||
 | 
								 * Ignore GPEs that have no corresponding _Lxx/_Exx method
 | 
				
			||||||
			if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)
 | 
								 * and GPEs that are used to wake the system
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
 | 
				
			||||||
 | 
								     ACPI_GPE_DISPATCH_NONE)
 | 
				
			||||||
 | 
								    || ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
 | 
				
			||||||
 | 
									== ACPI_GPE_DISPATCH_HANDLER)
 | 
				
			||||||
			    || (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
 | 
								    || (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -415,6 +415,7 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
 | 
				
			||||||
	 * Add the GPE information from above to the gpe_event_info block for
 | 
						 * Add the GPE information from above to the gpe_event_info block for
 | 
				
			||||||
	 * use during dispatch of this GPE.
 | 
						 * use during dispatch of this GPE.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
						gpe_event_info->flags &= ~(ACPI_GPE_DISPATCH_MASK);
 | 
				
			||||||
	gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD);
 | 
						gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD);
 | 
				
			||||||
	gpe_event_info->dispatch.method_node = method_node;
 | 
						gpe_event_info->dispatch.method_node = method_node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -166,39 +166,75 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
 | 
					ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*******************************************************************************
 | 
					/*******************************************************************************
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * FUNCTION:    acpi_setup_gpe_for_wake
 | 
					 * FUNCTION:    acpi_setup_gpe_for_wake
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
 | 
					 * PARAMETERS:  wake_device         - Device associated with the GPE (via _PRW)
 | 
				
			||||||
 | 
					 *              gpe_device          - Parent GPE Device. NULL for GPE0/GPE1
 | 
				
			||||||
 *              gpe_number          - GPE level within the GPE block
 | 
					 *              gpe_number          - GPE level within the GPE block
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * RETURN:      Status
 | 
					 * RETURN:      Status
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * DESCRIPTION: Set the ACPI_GPE_CAN_WAKE flag for the given GPE.  If the GPE
 | 
					 * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
 | 
				
			||||||
 *              has a corresponding method and is currently enabled, disable it
 | 
					 *              interface is intended to be used as the host executes the
 | 
				
			||||||
 *              (GPEs with corresponding methods are enabled unconditionally
 | 
					 *              _PRW methods (Power Resources for Wake) in the system tables.
 | 
				
			||||||
 *              during initialization, but GPEs that can wake up are expected
 | 
					 *              Each _PRW appears under a Device Object (The wake_device), and
 | 
				
			||||||
 *              to be initially disabled).
 | 
					 *              contains the info for the wake GPE associated with the
 | 
				
			||||||
 | 
					 *              wake_device.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 ******************************************************************************/
 | 
					 ******************************************************************************/
 | 
				
			||||||
acpi_status acpi_setup_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number)
 | 
					acpi_status
 | 
				
			||||||
 | 
					acpi_setup_gpe_for_wake(acpi_handle wake_device,
 | 
				
			||||||
 | 
								acpi_handle gpe_device, u32 gpe_number)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	acpi_status status = AE_OK;
 | 
						acpi_status status = AE_BAD_PARAMETER;
 | 
				
			||||||
	struct acpi_gpe_event_info *gpe_event_info;
 | 
						struct acpi_gpe_event_info *gpe_event_info;
 | 
				
			||||||
 | 
						struct acpi_namespace_node *device_node;
 | 
				
			||||||
	acpi_cpu_flags flags;
 | 
						acpi_cpu_flags flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);
 | 
						ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Parameter Validation */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!wake_device) {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * By forcing wake_device to be valid, we automatically enable the
 | 
				
			||||||
 | 
							 * implicit notify feature on all hosts.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							return_ACPI_STATUS(AE_BAD_PARAMETER);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Validate wake_device is of type Device */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
 | 
				
			||||||
 | 
						if (device_node->type != ACPI_TYPE_DEVICE) {
 | 
				
			||||||
 | 
							return_ACPI_STATUS(AE_BAD_PARAMETER);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
 | 
						flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Ensure that we have a valid GPE number */
 | 
						/* Ensure that we have a valid GPE number */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
 | 
						gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
 | 
				
			||||||
	if (gpe_event_info) {
 | 
						if (gpe_event_info) {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * If there is no method or handler for this GPE, then the
 | 
				
			||||||
 | 
							 * wake_device will be notified whenever this GPE fires (aka
 | 
				
			||||||
 | 
							 * "implicit notify") Note: The GPE is assumed to be
 | 
				
			||||||
 | 
							 * level-triggered (for windows compatibility).
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
 | 
				
			||||||
 | 
							    ACPI_GPE_DISPATCH_NONE) {
 | 
				
			||||||
 | 
								gpe_event_info->flags =
 | 
				
			||||||
 | 
								    (ACPI_GPE_DISPATCH_NOTIFY |
 | 
				
			||||||
 | 
								     ACPI_GPE_LEVEL_TRIGGERED);
 | 
				
			||||||
 | 
								gpe_event_info->dispatch.device_node = device_node;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
 | 
							gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
 | 
				
			||||||
	} else {
 | 
							status = AE_OK;
 | 
				
			||||||
		status = AE_BAD_PARAMETER;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
 | 
						acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -619,7 +619,7 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
 | 
				
			||||||
		wake_up(&ec->wait);
 | 
							wake_up(&ec->wait);
 | 
				
			||||||
		ec_check_sci(ec, acpi_ec_read_status(ec));
 | 
							ec_check_sci(ec, acpi_ec_read_status(ec));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return ACPI_INTERRUPT_HANDLED;
 | 
						return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* --------------------------------------------------------------------------
 | 
					/* --------------------------------------------------------------------------
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -778,7 +778,7 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
 | 
				
			||||||
		wakeup->resources.handles[i] = element->reference.handle;
 | 
							wakeup->resources.handles[i] = element->reference.handle;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	acpi_setup_gpe_for_wake(wakeup->gpe_device, wakeup->gpe_number);
 | 
						acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 out:
 | 
					 out:
 | 
				
			||||||
	kfree(buffer.pointer);
 | 
						kfree(buffer.pointer);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -292,10 +292,12 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number);
 | 
					acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
acpi_status acpi_setup_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number);
 | 
					acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					acpi_status
 | 
				
			||||||
 | 
					acpi_setup_gpe_for_wake(acpi_handle parent_device,
 | 
				
			||||||
 | 
								acpi_handle gpe_device, u32 gpe_number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action);
 | 
					acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
acpi_status
 | 
					acpi_status
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -664,25 +664,26 @@ typedef u32 acpi_event_status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * GPE info flags - Per GPE
 | 
					 * GPE info flags - Per GPE
 | 
				
			||||||
 * +-------+---+-+-+
 | 
					 * +-------+-+-+---+
 | 
				
			||||||
 * |  7:4  |3:2|1|0|
 | 
					 * |  7:4  |3|2|1:0|
 | 
				
			||||||
 * +-------+---+-+-+
 | 
					 * +-------+-+-+---+
 | 
				
			||||||
 *     |    | |  |
 | 
					 *     |    | |  |
 | 
				
			||||||
 *     |     |  | +--- Interrupt type: edge or level triggered
 | 
					 *     |    | |  +-- Type of dispatch:to method, handler, notify, or none
 | 
				
			||||||
 *     |     |  +----- GPE can wake the system
 | 
					 *     |    | +----- Interrupt type: edge or level triggered
 | 
				
			||||||
 *     |     +-------- Type of dispatch:to method, handler, or none
 | 
					 *     |    +------- Is a Wake GPE
 | 
				
			||||||
 *     +-------------- <Reserved>
 | 
					 *     +------------ <Reserved>
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#define ACPI_GPE_XRUPT_TYPE_MASK        (u8) 0x01
 | 
					#define ACPI_GPE_DISPATCH_NONE          (u8) 0x00
 | 
				
			||||||
#define ACPI_GPE_LEVEL_TRIGGERED        (u8) 0x01
 | 
					#define ACPI_GPE_DISPATCH_METHOD        (u8) 0x01
 | 
				
			||||||
 | 
					#define ACPI_GPE_DISPATCH_HANDLER       (u8) 0x02
 | 
				
			||||||
 | 
					#define ACPI_GPE_DISPATCH_NOTIFY        (u8) 0x03
 | 
				
			||||||
 | 
					#define ACPI_GPE_DISPATCH_MASK          (u8) 0x03
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ACPI_GPE_LEVEL_TRIGGERED        (u8) 0x04
 | 
				
			||||||
#define ACPI_GPE_EDGE_TRIGGERED         (u8) 0x00
 | 
					#define ACPI_GPE_EDGE_TRIGGERED         (u8) 0x00
 | 
				
			||||||
 | 
					#define ACPI_GPE_XRUPT_TYPE_MASK        (u8) 0x04
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ACPI_GPE_CAN_WAKE		(u8) 0x02
 | 
					#define ACPI_GPE_CAN_WAKE               (u8) 0x08
 | 
				
			||||||
 | 
					 | 
				
			||||||
#define ACPI_GPE_DISPATCH_MASK          (u8) 0x0C
 | 
					 | 
				
			||||||
#define ACPI_GPE_DISPATCH_HANDLER       (u8) 0x04
 | 
					 | 
				
			||||||
#define ACPI_GPE_DISPATCH_METHOD        (u8) 0x08
 | 
					 | 
				
			||||||
#define ACPI_GPE_DISPATCH_NOT_USED      (u8) 0x00
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Flags for GPE and Lock interfaces
 | 
					 * Flags for GPE and Lock interfaces
 | 
				
			||||||
| 
						 | 
					@ -954,6 +955,10 @@ u32 (*acpi_interface_handler) (acpi_string interface_name, u32 supported);
 | 
				
			||||||
#define ACPI_INTERRUPT_NOT_HANDLED      0x00
 | 
					#define ACPI_INTERRUPT_NOT_HANDLED      0x00
 | 
				
			||||||
#define ACPI_INTERRUPT_HANDLED          0x01
 | 
					#define ACPI_INTERRUPT_HANDLED          0x01
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* GPE handler return values */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ACPI_REENABLE_GPE               0x80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Length of 32-bit EISAID values when converted back to a string */
 | 
					/* Length of 32-bit EISAID values when converted back to a string */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ACPI_EISAID_STRING_SIZE         8	/* Includes null terminator */
 | 
					#define ACPI_EISAID_STRING_SIZE         8	/* Includes null terminator */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue