mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 19:51:31 -04:00
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (48 commits) x86/PCI: Prevent mmconfig memory corruption ACPI: Use GPE reference counting to support shared GPEs x86/PCI: use host bridge _CRS info by default on 2008 and newer machines PCI: augment bus resource table with a list PCI: add pci_bus_for_each_resource(), remove direct bus->resource[] refs PCI: read bridge windows before filling in subtractive decode resources PCI: split up pci_read_bridge_bases() PCIe PME: use pci_pcie_cap() PCI PM: Run-time callbacks for PCI bus type PCIe PME: use pci_is_pcie() PCI / ACPI / PM: Platform support for PCI PME wake-up ACPI / ACPICA: Multiple system notify handlers per device ACPI / PM: Add more run-time wake-up fields ACPI: Use GPE reference counting to support shared GPEs PCI PM: Make it possible to force using INTx for PCIe PME signaling PCI PM: PCIe PME root port service driver PCI PM: Add function for checking PME status of devices PCI: mark is_pcie obsolete PCI: set PCI_PREF_RANGE_TYPE_64 in pci_bridge_check_ranges PCI: pciehp: second try to get big range for pcie devices ...
This commit is contained in:
commit
68c6b85984
113 changed files with 3007 additions and 1360 deletions
|
|
@ -76,12 +76,9 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node *node,
|
|||
* evgpe - GPE handling and dispatch
|
||||
*/
|
||||
acpi_status
|
||||
acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info,
|
||||
u8 type);
|
||||
acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info);
|
||||
|
||||
acpi_status
|
||||
acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info,
|
||||
u8 write_to_hardware);
|
||||
acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info);
|
||||
|
||||
acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info);
|
||||
|
||||
|
|
@ -121,9 +118,6 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info,
|
|||
|
||||
u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list);
|
||||
|
||||
acpi_status
|
||||
acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type);
|
||||
|
||||
acpi_status
|
||||
acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info);
|
||||
|
||||
|
|
|
|||
|
|
@ -426,6 +426,8 @@ struct acpi_gpe_event_info {
|
|||
struct acpi_gpe_register_info *register_info; /* Backpointer to register info */
|
||||
u8 flags; /* Misc info about this GPE */
|
||||
u8 gpe_number; /* This GPE */
|
||||
u8 runtime_count;
|
||||
u8 wakeup_count;
|
||||
};
|
||||
|
||||
/* Information about a GPE register pair, one per each status/enable pair in an array */
|
||||
|
|
|
|||
|
|
@ -287,8 +287,10 @@ struct acpi_object_buffer_field {
|
|||
|
||||
struct acpi_object_notify_handler {
|
||||
ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *node; /* Parent device */
|
||||
u32 handler_type;
|
||||
acpi_notify_handler handler;
|
||||
void *context;
|
||||
struct acpi_object_notify_handler *next;
|
||||
};
|
||||
|
||||
struct acpi_object_addr_handler {
|
||||
|
|
|
|||
|
|
@ -52,56 +52,11 @@ ACPI_MODULE_NAME("evgpe")
|
|||
/* Local prototypes */
|
||||
static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ev_set_gpe_type
|
||||
*
|
||||
* PARAMETERS: gpe_event_info - GPE to set
|
||||
* Type - New type
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ev_set_gpe_type);
|
||||
|
||||
/* Validate type and update register enable masks */
|
||||
|
||||
switch (type) {
|
||||
case ACPI_GPE_TYPE_WAKE:
|
||||
case ACPI_GPE_TYPE_RUNTIME:
|
||||
case ACPI_GPE_TYPE_WAKE_RUN:
|
||||
break;
|
||||
|
||||
default:
|
||||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/* Disable the GPE if currently enabled */
|
||||
|
||||
status = acpi_ev_disable_gpe(gpe_event_info);
|
||||
|
||||
/* Clear the type bits and insert the new Type */
|
||||
|
||||
gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK;
|
||||
gpe_event_info->flags |= type;
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ev_update_gpe_enable_masks
|
||||
*
|
||||
* PARAMETERS: gpe_event_info - GPE to update
|
||||
* Type - What to do: ACPI_GPE_DISABLE or
|
||||
* ACPI_GPE_ENABLE
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
|
|
@ -110,8 +65,7 @@ acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type)
|
|||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info,
|
||||
u8 type)
|
||||
acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
|
||||
{
|
||||
struct acpi_gpe_register_info *gpe_register_info;
|
||||
u8 register_bit;
|
||||
|
|
@ -127,37 +81,14 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info,
|
|||
(1 <<
|
||||
(gpe_event_info->gpe_number - gpe_register_info->base_gpe_number));
|
||||
|
||||
/* 1) Disable case. Simply clear all enable bits */
|
||||
ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, register_bit);
|
||||
ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);
|
||||
|
||||
if (type == ACPI_GPE_DISABLE) {
|
||||
ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
|
||||
register_bit);
|
||||
ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/* 2) Enable case. Set/Clear the appropriate enable bits */
|
||||
|
||||
switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
|
||||
case ACPI_GPE_TYPE_WAKE:
|
||||
ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit);
|
||||
ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);
|
||||
break;
|
||||
|
||||
case ACPI_GPE_TYPE_RUNTIME:
|
||||
ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
|
||||
register_bit);
|
||||
if (gpe_event_info->runtime_count)
|
||||
ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit);
|
||||
break;
|
||||
|
||||
case ACPI_GPE_TYPE_WAKE_RUN:
|
||||
if (gpe_event_info->wakeup_count)
|
||||
ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit);
|
||||
ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit);
|
||||
break;
|
||||
|
||||
default:
|
||||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
|
@ -167,8 +98,6 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info,
|
|||
* FUNCTION: acpi_ev_enable_gpe
|
||||
*
|
||||
* PARAMETERS: gpe_event_info - GPE to enable
|
||||
* write_to_hardware - Enable now, or just mark data structs
|
||||
* (WAKE GPEs should be deferred)
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
|
|
@ -176,9 +105,7 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info,
|
|||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info,
|
||||
u8 write_to_hardware)
|
||||
acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
|
|
@ -186,47 +113,20 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info,
|
|||
|
||||
/* Make sure HW enable masks are updated */
|
||||
|
||||
status =
|
||||
acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_ENABLE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
|
||||
if (ACPI_FAILURE(status))
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* Mark wake-enabled or HW enable, or both */
|
||||
|
||||
switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
|
||||
case ACPI_GPE_TYPE_WAKE:
|
||||
if (gpe_event_info->runtime_count) {
|
||||
/* Clear the GPE (of stale events), then enable it */
|
||||
status = acpi_hw_clear_gpe(gpe_event_info);
|
||||
if (ACPI_FAILURE(status))
|
||||
return_ACPI_STATUS(status);
|
||||
|
||||
ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
|
||||
break;
|
||||
|
||||
case ACPI_GPE_TYPE_WAKE_RUN:
|
||||
|
||||
ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
|
||||
|
||||
/*lint -fallthrough */
|
||||
|
||||
case ACPI_GPE_TYPE_RUNTIME:
|
||||
|
||||
ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
|
||||
|
||||
if (write_to_hardware) {
|
||||
|
||||
/* Clear the GPE (of stale events), then enable it */
|
||||
|
||||
status = acpi_hw_clear_gpe(gpe_event_info);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* Enable the requested runtime GPE */
|
||||
|
||||
status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
/* Enable the requested runtime GPE */
|
||||
status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
|
|
@ -252,34 +152,9 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
|
|||
|
||||
/* Make sure HW enable masks are updated */
|
||||
|
||||
status =
|
||||
acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_DISABLE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
|
||||
if (ACPI_FAILURE(status))
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* Clear the appropriate enabled flags for this GPE */
|
||||
|
||||
switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
|
||||
case ACPI_GPE_TYPE_WAKE:
|
||||
ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
|
||||
break;
|
||||
|
||||
case ACPI_GPE_TYPE_WAKE_RUN:
|
||||
ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
|
||||
|
||||
/* fallthrough */
|
||||
|
||||
case ACPI_GPE_TYPE_RUNTIME:
|
||||
|
||||
/* Disable the requested runtime GPE */
|
||||
|
||||
ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Even if we don't know the GPE type, make sure that we always
|
||||
|
|
@ -521,7 +396,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
|
|||
|
||||
/* Set the GPE flags for return to enabled state */
|
||||
|
||||
(void)acpi_ev_enable_gpe(gpe_event_info, FALSE);
|
||||
(void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
|
||||
|
||||
/*
|
||||
* Take a snapshot of the GPE info for this level - we copy the info to
|
||||
|
|
|
|||
|
|
@ -258,7 +258,6 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
|
|||
u32 gpe_number;
|
||||
char name[ACPI_NAME_SIZE + 1];
|
||||
u8 type;
|
||||
acpi_status status;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ev_save_method_info);
|
||||
|
||||
|
|
@ -325,26 +324,20 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
|
|||
|
||||
/*
|
||||
* Now we can add this information to the gpe_event_info block for use
|
||||
* during dispatch of this GPE. Default type is RUNTIME, although this may
|
||||
* change when the _PRW methods are executed later.
|
||||
* during dispatch of this GPE.
|
||||
*/
|
||||
gpe_event_info =
|
||||
&gpe_block->event_info[gpe_number - gpe_block->block_base_number];
|
||||
|
||||
gpe_event_info->flags = (u8)
|
||||
(type | ACPI_GPE_DISPATCH_METHOD | ACPI_GPE_TYPE_RUNTIME);
|
||||
gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD);
|
||||
|
||||
gpe_event_info->dispatch.method_node =
|
||||
(struct acpi_namespace_node *)obj_handle;
|
||||
|
||||
/* Update enable mask, but don't enable the HW GPE as of yet */
|
||||
|
||||
status = acpi_ev_enable_gpe(gpe_event_info, FALSE);
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
|
||||
"Registered GPE method %s as GPE number 0x%.2X\n",
|
||||
name, gpe_number));
|
||||
return_ACPI_STATUS(status);
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
@ -454,20 +447,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
|
|||
gpe_block->
|
||||
block_base_number];
|
||||
|
||||
/* Mark GPE for WAKE-ONLY but WAKE_DISABLED */
|
||||
|
||||
gpe_event_info->flags &=
|
||||
~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);
|
||||
|
||||
status =
|
||||
acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
status =
|
||||
acpi_ev_update_gpe_enable_masks(gpe_event_info,
|
||||
ACPI_GPE_DISABLE);
|
||||
gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
|
@ -989,7 +969,6 @@ acpi_status
|
|||
acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
|
||||
struct acpi_gpe_block_info *gpe_block)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_gpe_event_info *gpe_event_info;
|
||||
struct acpi_gpe_walk_info gpe_info;
|
||||
u32 wake_gpe_count;
|
||||
|
|
@ -1019,42 +998,50 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
|
|||
gpe_info.gpe_block = gpe_block;
|
||||
gpe_info.gpe_device = gpe_device;
|
||||
|
||||
status =
|
||||
acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
|
||||
acpi_ev_match_prw_and_gpe, NULL,
|
||||
&gpe_info, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable all GPEs in this block that have these attributes:
|
||||
* 1) are "runtime" or "run/wake" GPEs, and
|
||||
* 2) have a corresponding _Lxx or _Exx method
|
||||
*
|
||||
* Any other GPEs within this block must be enabled via the
|
||||
* acpi_enable_gpe() external interface.
|
||||
* Enable all GPEs that have a corresponding method and aren't
|
||||
* capable of generating wakeups. Any other GPEs within this block
|
||||
* must be enabled via the acpi_enable_gpe() interface.
|
||||
*/
|
||||
wake_gpe_count = 0;
|
||||
gpe_enabled_count = 0;
|
||||
if (gpe_device == acpi_gbl_fadt_gpe_device)
|
||||
gpe_device = NULL;
|
||||
|
||||
for (i = 0; i < gpe_block->register_count; i++) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
|
||||
acpi_status status;
|
||||
acpi_size gpe_index;
|
||||
int gpe_number;
|
||||
|
||||
/* Get the info block for this particular GPE */
|
||||
gpe_index = (acpi_size)i * ACPI_GPE_REGISTER_WIDTH + j;
|
||||
gpe_event_info = &gpe_block->event_info[gpe_index];
|
||||
|
||||
gpe_event_info = &gpe_block->event_info[((acpi_size) i *
|
||||
ACPI_GPE_REGISTER_WIDTH)
|
||||
+ j];
|
||||
|
||||
if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
|
||||
ACPI_GPE_DISPATCH_METHOD) &&
|
||||
(gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) {
|
||||
gpe_enabled_count++;
|
||||
}
|
||||
|
||||
if (gpe_event_info->flags & ACPI_GPE_TYPE_WAKE) {
|
||||
if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {
|
||||
wake_gpe_count++;
|
||||
if (acpi_gbl_leave_wake_gpes_disabled)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD))
|
||||
continue;
|
||||
|
||||
gpe_number = gpe_index + gpe_block->block_base_number;
|
||||
status = acpi_enable_gpe(gpe_device, gpe_number,
|
||||
ACPI_GPE_TYPE_RUNTIME);
|
||||
if (ACPI_FAILURE(status))
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Failed to enable GPE %02X\n",
|
||||
gpe_number));
|
||||
else
|
||||
gpe_enabled_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1062,15 +1049,7 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
|
|||
"Found %u Wake, Enabled %u Runtime GPEs in this block\n",
|
||||
wake_gpe_count, gpe_enabled_count));
|
||||
|
||||
/* Enable all valid runtime GPEs found above */
|
||||
|
||||
status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block, NULL);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_ERROR((AE_INFO, "Could not enable GPEs in GpeBlock %p",
|
||||
gpe_block));
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
|||
|
|
@ -259,9 +259,15 @@ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)
|
|||
|
||||
handler_obj = notify_info->notify.handler_obj;
|
||||
if (handler_obj) {
|
||||
handler_obj->notify.handler(notify_info->notify.node,
|
||||
notify_info->notify.value,
|
||||
handler_obj->notify.context);
|
||||
struct acpi_object_notify_handler *notifier;
|
||||
|
||||
notifier = &handler_obj->notify;
|
||||
while (notifier) {
|
||||
notifier->handler(notify_info->notify.node,
|
||||
notify_info->notify.value,
|
||||
notifier->context);
|
||||
notifier = notifier->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* All done with the info object */
|
||||
|
|
|
|||
|
|
@ -216,6 +216,72 @@ acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
|
|||
|
||||
ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler)
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_populate_handler_object
|
||||
*
|
||||
* PARAMETERS: handler_obj - Handler object to populate
|
||||
* handler_type - The type of handler:
|
||||
* ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
|
||||
* ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
|
||||
* ACPI_ALL_NOTIFY: both system and device
|
||||
* handler - Address of the handler
|
||||
* context - Value passed to the handler on each GPE
|
||||
* next - Address of a handler object to link to
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Populate a handler object.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void
|
||||
acpi_populate_handler_object(struct acpi_object_notify_handler *handler_obj,
|
||||
u32 handler_type,
|
||||
acpi_notify_handler handler, void *context,
|
||||
struct acpi_object_notify_handler *next)
|
||||
{
|
||||
handler_obj->handler_type = handler_type;
|
||||
handler_obj->handler = handler;
|
||||
handler_obj->context = context;
|
||||
handler_obj->next = next;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_add_handler_object
|
||||
*
|
||||
* PARAMETERS: parent_obj - Parent of the new object
|
||||
* handler - Address of the handler
|
||||
* context - Value passed to the handler on each GPE
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Create a new handler object and populate it.
|
||||
*
|
||||
******************************************************************************/
|
||||
static acpi_status
|
||||
acpi_add_handler_object(struct acpi_object_notify_handler *parent_obj,
|
||||
acpi_notify_handler handler, void *context)
|
||||
{
|
||||
struct acpi_object_notify_handler *handler_obj;
|
||||
|
||||
/* The parent must not be a defice notify handler object. */
|
||||
if (parent_obj->handler_type & ACPI_DEVICE_NOTIFY)
|
||||
return AE_BAD_PARAMETER;
|
||||
|
||||
handler_obj = ACPI_ALLOCATE_ZEROED(sizeof(*handler_obj));
|
||||
if (!handler_obj)
|
||||
return AE_NO_MEMORY;
|
||||
|
||||
acpi_populate_handler_object(handler_obj,
|
||||
ACPI_SYSTEM_NOTIFY,
|
||||
handler, context,
|
||||
parent_obj->next);
|
||||
parent_obj->next = handler_obj;
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_install_notify_handler
|
||||
|
|
@ -316,15 +382,32 @@ acpi_install_notify_handler(acpi_handle device,
|
|||
obj_desc = acpi_ns_get_attached_object(node);
|
||||
if (obj_desc) {
|
||||
|
||||
/* Object exists - make sure there's no handler */
|
||||
/* Object exists. */
|
||||
|
||||
if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
|
||||
obj_desc->common_notify.system_notify) ||
|
||||
((handler_type & ACPI_DEVICE_NOTIFY) &&
|
||||
obj_desc->common_notify.device_notify)) {
|
||||
/* For a device notify, make sure there's no handler. */
|
||||
if ((handler_type & ACPI_DEVICE_NOTIFY) &&
|
||||
obj_desc->common_notify.device_notify) {
|
||||
status = AE_ALREADY_EXISTS;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
/* System notifies may have more handlers installed. */
|
||||
notify_obj = obj_desc->common_notify.system_notify;
|
||||
|
||||
if ((handler_type & ACPI_SYSTEM_NOTIFY) && notify_obj) {
|
||||
struct acpi_object_notify_handler *parent_obj;
|
||||
|
||||
if (handler_type & ACPI_DEVICE_NOTIFY) {
|
||||
status = AE_ALREADY_EXISTS;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
parent_obj = ¬ify_obj->notify;
|
||||
status = acpi_add_handler_object(parent_obj,
|
||||
handler,
|
||||
context);
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
} else {
|
||||
/* Create a new object */
|
||||
|
||||
|
|
@ -356,9 +439,10 @@ acpi_install_notify_handler(acpi_handle device,
|
|||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
notify_obj->notify.node = node;
|
||||
notify_obj->notify.handler = handler;
|
||||
notify_obj->notify.context = context;
|
||||
acpi_populate_handler_object(¬ify_obj->notify,
|
||||
handler_type,
|
||||
handler, context,
|
||||
NULL);
|
||||
|
||||
if (handler_type & ACPI_SYSTEM_NOTIFY) {
|
||||
obj_desc->common_notify.system_notify = notify_obj;
|
||||
|
|
@ -418,6 +502,10 @@ acpi_remove_notify_handler(acpi_handle device,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
|
||||
/* Make sure all deferred tasks are completed */
|
||||
acpi_os_wait_events_complete(NULL);
|
||||
|
||||
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto exit;
|
||||
|
|
@ -445,15 +533,6 @@ acpi_remove_notify_handler(acpi_handle device,
|
|||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
/* Make sure all deferred tasks are completed */
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
acpi_os_wait_events_complete(NULL);
|
||||
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (handler_type & ACPI_SYSTEM_NOTIFY) {
|
||||
acpi_gbl_system_notify.node = NULL;
|
||||
acpi_gbl_system_notify.handler = NULL;
|
||||
|
|
@ -488,28 +567,60 @@ acpi_remove_notify_handler(acpi_handle device,
|
|||
/* Object exists - make sure there's an existing handler */
|
||||
|
||||
if (handler_type & ACPI_SYSTEM_NOTIFY) {
|
||||
struct acpi_object_notify_handler *handler_obj;
|
||||
struct acpi_object_notify_handler *parent_obj;
|
||||
|
||||
notify_obj = obj_desc->common_notify.system_notify;
|
||||
if (!notify_obj) {
|
||||
status = AE_NOT_EXIST;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
if (notify_obj->notify.handler != handler) {
|
||||
handler_obj = ¬ify_obj->notify;
|
||||
parent_obj = NULL;
|
||||
while (handler_obj->handler != handler) {
|
||||
if (handler_obj->next) {
|
||||
parent_obj = handler_obj;
|
||||
handler_obj = handler_obj->next;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (handler_obj->handler != handler) {
|
||||
status = AE_BAD_PARAMETER;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
/* Make sure all deferred tasks are completed */
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
acpi_os_wait_events_complete(NULL);
|
||||
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto exit;
|
||||
/*
|
||||
* Remove the handler. There are three possible cases.
|
||||
* First, we may need to remove a non-embedded object.
|
||||
* Second, we may need to remove the embedded object's
|
||||
* handler data, while non-embedded objects exist.
|
||||
* Finally, we may need to remove the embedded object
|
||||
* entirely along with its container.
|
||||
*/
|
||||
if (parent_obj) {
|
||||
/* Non-embedded object is being removed. */
|
||||
parent_obj->next = handler_obj->next;
|
||||
ACPI_FREE(handler_obj);
|
||||
} else if (notify_obj->notify.next) {
|
||||
/*
|
||||
* The handler matches the embedded object, but
|
||||
* there are more handler objects in the list.
|
||||
* Replace the embedded object's data with the
|
||||
* first next object's data and remove that
|
||||
* object.
|
||||
*/
|
||||
parent_obj = ¬ify_obj->notify;
|
||||
handler_obj = notify_obj->notify.next;
|
||||
*parent_obj = *handler_obj;
|
||||
ACPI_FREE(handler_obj);
|
||||
} else {
|
||||
/* No more handler objects in the list. */
|
||||
obj_desc->common_notify.system_notify = NULL;
|
||||
acpi_ut_remove_reference(notify_obj);
|
||||
}
|
||||
|
||||
/* Remove the handler */
|
||||
obj_desc->common_notify.system_notify = NULL;
|
||||
acpi_ut_remove_reference(notify_obj);
|
||||
}
|
||||
|
||||
if (handler_type & ACPI_DEVICE_NOTIFY) {
|
||||
|
|
@ -523,14 +634,6 @@ acpi_remove_notify_handler(acpi_handle device,
|
|||
status = AE_BAD_PARAMETER;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
/* Make sure all deferred tasks are completed */
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
acpi_os_wait_events_complete(NULL);
|
||||
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Remove the handler */
|
||||
obj_desc->common_notify.device_notify = NULL;
|
||||
|
|
@ -617,13 +720,6 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
|
|||
handler->context = context;
|
||||
handler->method_node = gpe_event_info->dispatch.method_node;
|
||||
|
||||
/* Disable the GPE before installing the handler */
|
||||
|
||||
status = acpi_ev_disable_gpe(gpe_event_info);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
/* Install the handler */
|
||||
|
||||
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
|
||||
|
|
@ -707,13 +803,6 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
|
|||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
/* Disable the GPE before removing the handler */
|
||||
|
||||
status = acpi_ev_disable_gpe(gpe_event_info);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
/* Make sure all deferred tasks are completed */
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
|
||||
|
|
|
|||
|
|
@ -201,67 +201,25 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event)
|
|||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_set_gpe_type
|
||||
* FUNCTION: acpi_set_gpe
|
||||
*
|
||||
* PARAMETERS: gpe_device - Parent GPE Device
|
||||
* gpe_number - GPE level within the GPE block
|
||||
* Type - New GPE type
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Set the type of an individual GPE
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
struct acpi_gpe_event_info *gpe_event_info;
|
||||
|
||||
ACPI_FUNCTION_TRACE(acpi_set_gpe_type);
|
||||
|
||||
/* Ensure that we have a valid GPE number */
|
||||
|
||||
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
|
||||
if (!gpe_event_info) {
|
||||
status = AE_BAD_PARAMETER;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) {
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/* Set the new type (will disable GPE if currently enabled) */
|
||||
|
||||
status = acpi_ev_set_gpe_type(gpe_event_info, type);
|
||||
|
||||
unlock_and_exit:
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_set_gpe_type)
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_enable_gpe
|
||||
*
|
||||
* PARAMETERS: gpe_device - Parent GPE Device
|
||||
* gpe_number - GPE level within the GPE block
|
||||
* Flags - Just enable, or also wake enable?
|
||||
* action - Enable or disable
|
||||
* Called from ISR or not
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Enable an ACPI event (general purpose)
|
||||
* DESCRIPTION: Enable or disable an ACPI event (general purpose)
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
|
||||
acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
acpi_cpu_flags flags;
|
||||
struct acpi_gpe_event_info *gpe_event_info;
|
||||
|
||||
ACPI_FUNCTION_TRACE(acpi_enable_gpe);
|
||||
ACPI_FUNCTION_TRACE(acpi_set_gpe);
|
||||
|
||||
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
|
||||
|
||||
|
|
@ -273,15 +231,90 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
|
|||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
/* Perform the enable */
|
||||
/* Perform the action */
|
||||
|
||||
status = acpi_ev_enable_gpe(gpe_event_info, TRUE);
|
||||
switch (action) {
|
||||
case ACPI_GPE_ENABLE:
|
||||
status = acpi_ev_enable_gpe(gpe_event_info);
|
||||
break;
|
||||
|
||||
case ACPI_GPE_DISABLE:
|
||||
status = acpi_ev_disable_gpe(gpe_event_info);
|
||||
break;
|
||||
|
||||
default:
|
||||
ACPI_ERROR((AE_INFO, "Invalid action\n"));
|
||||
status = AE_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
unlock_and_exit:
|
||||
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_set_gpe)
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_enable_gpe
|
||||
*
|
||||
* PARAMETERS: gpe_device - Parent GPE Device
|
||||
* gpe_number - GPE level within the GPE block
|
||||
* type - Purpose the GPE will be used for
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Take a reference to a GPE and enable it if necessary
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
acpi_cpu_flags flags;
|
||||
struct acpi_gpe_event_info *gpe_event_info;
|
||||
|
||||
ACPI_FUNCTION_TRACE(acpi_enable_gpe);
|
||||
|
||||
if (type & ~ACPI_GPE_TYPE_WAKE_RUN)
|
||||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
|
||||
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
|
||||
|
||||
/* Ensure that we have a valid GPE number */
|
||||
|
||||
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
|
||||
if (!gpe_event_info) {
|
||||
status = AE_BAD_PARAMETER;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
if (type & ACPI_GPE_TYPE_RUNTIME) {
|
||||
if (++gpe_event_info->runtime_count == 1) {
|
||||
status = acpi_ev_enable_gpe(gpe_event_info);
|
||||
if (ACPI_FAILURE(status))
|
||||
gpe_event_info->runtime_count--;
|
||||
}
|
||||
}
|
||||
|
||||
if (type & ACPI_GPE_TYPE_WAKE) {
|
||||
if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
|
||||
status = AE_BAD_PARAMETER;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wake-up GPEs are only enabled right prior to putting the
|
||||
* system into a sleep state.
|
||||
*/
|
||||
if (++gpe_event_info->wakeup_count == 1)
|
||||
acpi_ev_update_gpe_enable_masks(gpe_event_info);
|
||||
}
|
||||
|
||||
unlock_and_exit:
|
||||
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
@ -290,15 +323,14 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
|
|||
*
|
||||
* PARAMETERS: gpe_device - Parent GPE Device
|
||||
* gpe_number - GPE level within the GPE block
|
||||
* Flags - Just disable, or also wake disable?
|
||||
* Called from ISR or not
|
||||
* type - Purpose the GPE won't be used for any more
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Disable an ACPI event (general purpose)
|
||||
* DESCRIPTION: Release a reference to a GPE and disable it if necessary
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
|
||||
acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
acpi_cpu_flags flags;
|
||||
|
|
@ -306,6 +338,9 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
|
|||
|
||||
ACPI_FUNCTION_TRACE(acpi_disable_gpe);
|
||||
|
||||
if (type & ~ACPI_GPE_TYPE_WAKE_RUN)
|
||||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
|
||||
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
|
||||
/* Ensure that we have a valid GPE number */
|
||||
|
||||
|
|
@ -315,13 +350,24 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
|
|||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
status = acpi_ev_disable_gpe(gpe_event_info);
|
||||
if ((type & ACPI_GPE_TYPE_RUNTIME) && gpe_event_info->runtime_count) {
|
||||
if (--gpe_event_info->runtime_count == 0)
|
||||
status = acpi_ev_disable_gpe(gpe_event_info);
|
||||
}
|
||||
|
||||
if ((type & ACPI_GPE_TYPE_WAKE) && gpe_event_info->wakeup_count) {
|
||||
/*
|
||||
* Wake-up GPEs are not enabled after leaving system sleep
|
||||
* states, so we don't need to disable them here.
|
||||
*/
|
||||
if (--gpe_event_info->wakeup_count == 0)
|
||||
acpi_ev_update_gpe_enable_masks(gpe_event_info);
|
||||
}
|
||||
|
||||
unlock_and_exit:
|
||||
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
|||
|
|
@ -422,11 +422,10 @@ static int acpi_button_add(struct acpi_device *device)
|
|||
|
||||
if (device->wakeup.flags.valid) {
|
||||
/* Button's GPE is run-wake GPE */
|
||||
acpi_set_gpe_type(device->wakeup.gpe_device,
|
||||
device->wakeup.gpe_number,
|
||||
ACPI_GPE_TYPE_WAKE_RUN);
|
||||
acpi_enable_gpe(device->wakeup.gpe_device,
|
||||
device->wakeup.gpe_number);
|
||||
device->wakeup.gpe_number,
|
||||
ACPI_GPE_TYPE_WAKE_RUN);
|
||||
device->wakeup.run_wake_count++;
|
||||
device->wakeup.state.enabled = 1;
|
||||
}
|
||||
|
||||
|
|
@ -446,6 +445,14 @@ static int acpi_button_remove(struct acpi_device *device, int type)
|
|||
{
|
||||
struct acpi_button *button = acpi_driver_data(device);
|
||||
|
||||
if (device->wakeup.flags.valid) {
|
||||
acpi_disable_gpe(device->wakeup.gpe_device,
|
||||
device->wakeup.gpe_number,
|
||||
ACPI_GPE_TYPE_WAKE_RUN);
|
||||
device->wakeup.run_wake_count--;
|
||||
device->wakeup.state.enabled = 0;
|
||||
}
|
||||
|
||||
acpi_button_remove_fs(device);
|
||||
input_unregister_device(button->input);
|
||||
kfree(button);
|
||||
|
|
|
|||
|
|
@ -307,7 +307,11 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
|
|||
pr_debug(PREFIX "transaction start\n");
|
||||
/* disable GPE during transaction if storm is detected */
|
||||
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
|
||||
acpi_disable_gpe(NULL, ec->gpe);
|
||||
/*
|
||||
* It has to be disabled at the hardware level regardless of the
|
||||
* GPE reference counting, so that it doesn't trigger.
|
||||
*/
|
||||
acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE);
|
||||
}
|
||||
|
||||
status = acpi_ec_transaction_unlocked(ec, t);
|
||||
|
|
@ -316,8 +320,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
|
|||
ec_check_sci_sync(ec, acpi_ec_read_status(ec));
|
||||
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
|
||||
msleep(1);
|
||||
/* it is safe to enable GPE outside of transaction */
|
||||
acpi_enable_gpe(NULL, ec->gpe);
|
||||
/*
|
||||
* It is safe to enable the GPE outside of the transaction. Use
|
||||
* acpi_set_gpe() for that, since we used it to disable the GPE
|
||||
* above.
|
||||
*/
|
||||
acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE);
|
||||
} else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) {
|
||||
pr_info(PREFIX "GPE storm detected, "
|
||||
"transactions will use polling mode\n");
|
||||
|
|
@ -788,8 +796,8 @@ static int ec_install_handlers(struct acpi_ec *ec)
|
|||
&acpi_ec_gpe_handler, ec);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
|
||||
acpi_enable_gpe(NULL, ec->gpe);
|
||||
|
||||
acpi_enable_gpe(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
|
||||
status = acpi_install_address_space_handler(ec->handle,
|
||||
ACPI_ADR_SPACE_EC,
|
||||
&acpi_ec_space_handler,
|
||||
|
|
@ -806,6 +814,7 @@ static int ec_install_handlers(struct acpi_ec *ec)
|
|||
} else {
|
||||
acpi_remove_gpe_handler(NULL, ec->gpe,
|
||||
&acpi_ec_gpe_handler);
|
||||
acpi_disable_gpe(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
|
@ -816,6 +825,7 @@ static int ec_install_handlers(struct acpi_ec *ec)
|
|||
|
||||
static void ec_remove_handlers(struct acpi_ec *ec)
|
||||
{
|
||||
acpi_disable_gpe(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
|
||||
if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
|
||||
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
|
||||
pr_err(PREFIX "failed to remove space handler\n");
|
||||
|
|
@ -1057,16 +1067,16 @@ error:
|
|||
static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state)
|
||||
{
|
||||
struct acpi_ec *ec = acpi_driver_data(device);
|
||||
/* Stop using GPE */
|
||||
acpi_disable_gpe(NULL, ec->gpe);
|
||||
/* Stop using the GPE, but keep it reference counted. */
|
||||
acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_ec_resume(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_ec *ec = acpi_driver_data(device);
|
||||
/* Enable use of GPE back */
|
||||
acpi_enable_gpe(NULL, ec->gpe);
|
||||
/* Enable the GPE again, but don't reference count it once more. */
|
||||
acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,8 +36,6 @@ static inline int acpi_debug_init(void) { return 0; }
|
|||
int acpi_power_init(void);
|
||||
int acpi_device_sleep_wake(struct acpi_device *dev,
|
||||
int enable, int sleep_state, int dev_state);
|
||||
int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state);
|
||||
int acpi_disable_wakeup_device_power(struct acpi_device *dev);
|
||||
int acpi_power_get_inferred_state(struct acpi_device *device);
|
||||
int acpi_power_transition(struct acpi_device *device, int state);
|
||||
extern int acpi_power_nocheck;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pci-acpi.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
|
||||
|
|
@ -38,7 +40,13 @@ static int acpi_pci_unbind(struct acpi_device *device)
|
|||
struct pci_dev *dev;
|
||||
|
||||
dev = acpi_get_pci_dev(device->handle);
|
||||
if (!dev || !dev->subordinate)
|
||||
if (!dev)
|
||||
goto out;
|
||||
|
||||
device_set_run_wake(&dev->dev, false);
|
||||
pci_acpi_remove_pm_notifier(device);
|
||||
|
||||
if (!dev->subordinate)
|
||||
goto out;
|
||||
|
||||
acpi_pci_irq_del_prt(dev->subordinate);
|
||||
|
|
@ -62,6 +70,10 @@ static int acpi_pci_bind(struct acpi_device *device)
|
|||
if (!dev)
|
||||
return 0;
|
||||
|
||||
pci_acpi_add_pm_notifier(device, dev);
|
||||
if (device->wakeup.flags.run_wake)
|
||||
device_set_run_wake(&dev->dev, true);
|
||||
|
||||
/*
|
||||
* Install the 'bind' function to facilitate callbacks for
|
||||
* children of the P2P bridge.
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <linux/proc_fs.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pci-acpi.h>
|
||||
#include <linux/acpi.h>
|
||||
|
|
@ -528,6 +529,10 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
|
|||
if (flags != base_flags)
|
||||
acpi_pci_osc_support(root, flags);
|
||||
|
||||
pci_acpi_add_bus_pm_notifier(device, root->bus);
|
||||
if (device->wakeup.flags.run_wake)
|
||||
device_set_run_wake(root->bus->bridge, true);
|
||||
|
||||
return 0;
|
||||
|
||||
end:
|
||||
|
|
@ -549,6 +554,9 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type)
|
|||
{
|
||||
struct acpi_pci_root *root = acpi_driver_data(device);
|
||||
|
||||
device_set_run_wake(root->bus->bridge, false);
|
||||
pci_acpi_remove_bus_pm_notifier(device);
|
||||
|
||||
kfree(root);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -558,6 +566,7 @@ static int __init acpi_pci_root_init(void)
|
|||
if (acpi_pci_disabled)
|
||||
return 0;
|
||||
|
||||
pci_acpi_crs_quirks();
|
||||
if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0)
|
||||
return -ENODEV;
|
||||
|
||||
|
|
|
|||
|
|
@ -741,19 +741,40 @@ acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device,
|
|||
return AE_OK;
|
||||
}
|
||||
|
||||
static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
|
||||
static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
|
||||
{
|
||||
acpi_status status = 0;
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
union acpi_object *package = NULL;
|
||||
int psw_error;
|
||||
|
||||
struct acpi_device_id button_device_ids[] = {
|
||||
{"PNP0C0D", 0},
|
||||
{"PNP0C0C", 0},
|
||||
{"PNP0C0E", 0},
|
||||
{"", 0},
|
||||
};
|
||||
acpi_status status;
|
||||
acpi_event_status event_status;
|
||||
|
||||
device->wakeup.run_wake_count = 0;
|
||||
device->wakeup.flags.notifier_present = 0;
|
||||
|
||||
/* Power button, Lid switch always enable wakeup */
|
||||
if (!acpi_match_device_ids(device, button_device_ids)) {
|
||||
device->wakeup.flags.run_wake = 1;
|
||||
device->wakeup.flags.always_enabled = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
status = acpi_get_gpe_status(NULL, device->wakeup.gpe_number,
|
||||
ACPI_NOT_ISR, &event_status);
|
||||
if (status == AE_OK)
|
||||
device->wakeup.flags.run_wake =
|
||||
!!(event_status & ACPI_EVENT_FLAG_HANDLE);
|
||||
}
|
||||
|
||||
static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
|
||||
{
|
||||
acpi_status status = 0;
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
union acpi_object *package = NULL;
|
||||
int psw_error;
|
||||
|
||||
/* _PRW */
|
||||
status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer);
|
||||
|
|
@ -773,6 +794,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
|
|||
|
||||
device->wakeup.flags.valid = 1;
|
||||
device->wakeup.prepare_count = 0;
|
||||
acpi_bus_set_run_wake_flags(device);
|
||||
/* Call _PSW/_DSW object to disable its ability to wake the sleeping
|
||||
* system for the ACPI device with the _PRW object.
|
||||
* The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW.
|
||||
|
|
@ -784,10 +806,6 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
|
|||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"error in _DSW or _PSW evaluation\n"));
|
||||
|
||||
/* Power button, Lid switch always enable wakeup */
|
||||
if (!acpi_match_device_ids(device, button_device_ids))
|
||||
device->wakeup.flags.run_wake = 1;
|
||||
|
||||
end:
|
||||
if (ACPI_FAILURE(status))
|
||||
device->flags.wake_capable = 0;
|
||||
|
|
|
|||
|
|
@ -745,9 +745,18 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
error = enable ?
|
||||
acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) :
|
||||
acpi_disable_wakeup_device_power(adev);
|
||||
if (enable) {
|
||||
error = acpi_enable_wakeup_device_power(adev,
|
||||
acpi_target_sleep_state);
|
||||
if (!error)
|
||||
acpi_enable_gpe(adev->wakeup.gpe_device,
|
||||
adev->wakeup.gpe_number,
|
||||
ACPI_GPE_TYPE_WAKE);
|
||||
} else {
|
||||
acpi_disable_gpe(adev->wakeup.gpe_device, adev->wakeup.gpe_number,
|
||||
ACPI_GPE_TYPE_WAKE);
|
||||
error = acpi_disable_wakeup_device_power(adev);
|
||||
}
|
||||
if (!error)
|
||||
dev_info(dev, "wake-up capability %s by ACPI\n",
|
||||
enable ? "enabled" : "disabled");
|
||||
|
|
|
|||
|
|
@ -387,10 +387,10 @@ static ssize_t counter_set(struct kobject *kobj,
|
|||
if (index < num_gpes) {
|
||||
if (!strcmp(buf, "disable\n") &&
|
||||
(status & ACPI_EVENT_FLAG_ENABLED))
|
||||
result = acpi_disable_gpe(handle, index);
|
||||
result = acpi_set_gpe(handle, index, ACPI_GPE_DISABLE);
|
||||
else if (!strcmp(buf, "enable\n") &&
|
||||
!(status & ACPI_EVENT_FLAG_ENABLED))
|
||||
result = acpi_enable_gpe(handle, index);
|
||||
result = acpi_set_gpe(handle, index, ACPI_GPE_ENABLE);
|
||||
else if (!strcmp(buf, "clear\n") &&
|
||||
(status & ACPI_EVENT_FLAG_SET))
|
||||
result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR);
|
||||
|
|
|
|||
|
|
@ -21,12 +21,12 @@
|
|||
ACPI_MODULE_NAME("wakeup_devices")
|
||||
|
||||
/**
|
||||
* acpi_enable_wakeup_device_prep - prepare wakeup devices
|
||||
* @sleep_state: ACPI state
|
||||
* Enable all wakup devices power if the devices' wakeup level
|
||||
* is higher than requested sleep level
|
||||
* acpi_enable_wakeup_device_prep - Prepare wake-up devices.
|
||||
* @sleep_state: ACPI system sleep state.
|
||||
*
|
||||
* Enable all wake-up devices' power, unless the requested system sleep state is
|
||||
* too deep.
|
||||
*/
|
||||
|
||||
void acpi_enable_wakeup_device_prep(u8 sleep_state)
|
||||
{
|
||||
struct list_head *node, *next;
|
||||
|
|
@ -36,9 +36,8 @@ void acpi_enable_wakeup_device_prep(u8 sleep_state)
|
|||
struct acpi_device,
|
||||
wakeup_list);
|
||||
|
||||
if (!dev->wakeup.flags.valid ||
|
||||
!dev->wakeup.state.enabled ||
|
||||
(sleep_state > (u32) dev->wakeup.sleep_state))
|
||||
if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled
|
||||
|| (sleep_state > (u32) dev->wakeup.sleep_state))
|
||||
continue;
|
||||
|
||||
acpi_enable_wakeup_device_power(dev, sleep_state);
|
||||
|
|
@ -46,9 +45,12 @@ void acpi_enable_wakeup_device_prep(u8 sleep_state)
|
|||
}
|
||||
|
||||
/**
|
||||
* acpi_enable_wakeup_device - enable wakeup devices
|
||||
* @sleep_state: ACPI state
|
||||
* Enable all wakup devices's GPE
|
||||
* acpi_enable_wakeup_device - Enable wake-up device GPEs.
|
||||
* @sleep_state: ACPI system sleep state.
|
||||
*
|
||||
* Enable all wake-up devices' GPEs, with the assumption that
|
||||
* acpi_disable_all_gpes() was executed before, so we don't need to disable any
|
||||
* GPEs here.
|
||||
*/
|
||||
void acpi_enable_wakeup_device(u8 sleep_state)
|
||||
{
|
||||
|
|
@ -65,29 +67,22 @@ void acpi_enable_wakeup_device(u8 sleep_state)
|
|||
if (!dev->wakeup.flags.valid)
|
||||
continue;
|
||||
|
||||
/* If users want to disable run-wake GPE,
|
||||
* we only disable it for wake and leave it for runtime
|
||||
*/
|
||||
if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count)
|
||||
|| sleep_state > (u32) dev->wakeup.sleep_state) {
|
||||
if (dev->wakeup.flags.run_wake) {
|
||||
/* set_gpe_type will disable GPE, leave it like that */
|
||||
acpi_set_gpe_type(dev->wakeup.gpe_device,
|
||||
dev->wakeup.gpe_number,
|
||||
ACPI_GPE_TYPE_RUNTIME);
|
||||
}
|
||||
|| sleep_state > (u32) dev->wakeup.sleep_state)
|
||||
continue;
|
||||
}
|
||||
if (!dev->wakeup.flags.run_wake)
|
||||
acpi_enable_gpe(dev->wakeup.gpe_device,
|
||||
dev->wakeup.gpe_number);
|
||||
|
||||
/* The wake-up power should have been enabled already. */
|
||||
acpi_set_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
|
||||
ACPI_GPE_ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_disable_wakeup_device - disable devices' wakeup capability
|
||||
* @sleep_state: ACPI state
|
||||
* Disable all wakup devices's GPE and wakeup capability
|
||||
* acpi_disable_wakeup_device - Disable devices' wakeup capability.
|
||||
* @sleep_state: ACPI system sleep state.
|
||||
*
|
||||
* This function only affects devices with wakeup.state.enabled set, which means
|
||||
* that it reverses the changes made by acpi_enable_wakeup_device_prep().
|
||||
*/
|
||||
void acpi_disable_wakeup_device(u8 sleep_state)
|
||||
{
|
||||
|
|
@ -97,30 +92,11 @@ void acpi_disable_wakeup_device(u8 sleep_state)
|
|||
struct acpi_device *dev =
|
||||
container_of(node, struct acpi_device, wakeup_list);
|
||||
|
||||
if (!dev->wakeup.flags.valid)
|
||||
if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled
|
||||
|| (sleep_state > (u32) dev->wakeup.sleep_state))
|
||||
continue;
|
||||
|
||||
if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count)
|
||||
|| sleep_state > (u32) dev->wakeup.sleep_state) {
|
||||
if (dev->wakeup.flags.run_wake) {
|
||||
acpi_set_gpe_type(dev->wakeup.gpe_device,
|
||||
dev->wakeup.gpe_number,
|
||||
ACPI_GPE_TYPE_WAKE_RUN);
|
||||
/* Re-enable it, since set_gpe_type will disable it */
|
||||
acpi_enable_gpe(dev->wakeup.gpe_device,
|
||||
dev->wakeup.gpe_number);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
acpi_disable_wakeup_device_power(dev);
|
||||
/* Never disable run-wake GPE */
|
||||
if (!dev->wakeup.flags.run_wake) {
|
||||
acpi_disable_gpe(dev->wakeup.gpe_device,
|
||||
dev->wakeup.gpe_number);
|
||||
acpi_clear_gpe(dev->wakeup.gpe_device,
|
||||
dev->wakeup.gpe_number, ACPI_NOT_ISR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -134,13 +110,11 @@ int __init acpi_wakeup_device_init(void)
|
|||
struct acpi_device,
|
||||
wakeup_list);
|
||||
/* In case user doesn't load button driver */
|
||||
if (!dev->wakeup.flags.run_wake || dev->wakeup.state.enabled)
|
||||
if (!dev->wakeup.flags.always_enabled ||
|
||||
dev->wakeup.state.enabled)
|
||||
continue;
|
||||
acpi_set_gpe_type(dev->wakeup.gpe_device,
|
||||
dev->wakeup.gpe_number,
|
||||
ACPI_GPE_TYPE_WAKE_RUN);
|
||||
acpi_enable_gpe(dev->wakeup.gpe_device,
|
||||
dev->wakeup.gpe_number);
|
||||
acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
|
||||
ACPI_GPE_TYPE_WAKE);
|
||||
dev->wakeup.state.enabled = 1;
|
||||
}
|
||||
mutex_unlock(&acpi_device_lock);
|
||||
|
|
|
|||
Loading…
Reference in a new issue