From patchwork Mon Aug 30 21:09:10 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rafael Wysocki X-Patchwork-Id: 143591 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o7ULArdg013070 for ; Mon, 30 Aug 2010 21:10:53 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754108Ab0H3VKw (ORCPT ); Mon, 30 Aug 2010 17:10:52 -0400 Received: from ogre.sisk.pl ([217.79.144.158]:59960 "EHLO ogre.sisk.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753590Ab0H3VKw (ORCPT ); Mon, 30 Aug 2010 17:10:52 -0400 Received: from localhost (localhost.localdomain [127.0.0.1]) by ogre.sisk.pl (Postfix) with ESMTP id 83D98192125; Mon, 30 Aug 2010 22:55:07 +0200 (CEST) Received: from ogre.sisk.pl ([127.0.0.1]) by localhost (ogre.sisk.pl [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 25738-09; Mon, 30 Aug 2010 22:54:59 +0200 (CEST) Received: from ferrari.rjw.lan (220-bem-13.acn.waw.pl [82.210.184.220]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ogre.sisk.pl (Postfix) with ESMTP id 5CC76191F6D; Mon, 30 Aug 2010 22:54:59 +0200 (CEST) From: "Rafael J. Wysocki" To: Bjorn Helgaas , "Moore, Robert" Subject: [PATCH] ACPI / ACPICA: Defer enabling of runtime GPEs (v2) Date: Mon, 30 Aug 2010 23:09:10 +0200 User-Agent: KMail/1.13.5 (Linux/2.6.36-rc3-rjw+; KDE/4.4.4; x86_64; ; ) Cc: Matthew Garrett , "Brown, Len" , Len Brown , "Lin, Ming M" , ACPI Devel Maling List References: <201008290110.56740.rjw@sisk.pl> <201008301400.45591.bjorn.helgaas@hp.com> In-Reply-To: <201008301400.45591.bjorn.helgaas@hp.com> MIME-Version: 1.0 Message-Id: <201008302309.11082.rjw@sisk.pl> X-Virus-Scanned: amavisd-new at ogre.sisk.pl using MkS_Vir for Linux Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Mon, 30 Aug 2010 21:10:53 +0000 (UTC) Index: linux-2.6/drivers/acpi/acpica/evxfevnt.c =================================================================== --- linux-2.6.orig/drivers/acpi/acpica/evxfevnt.c +++ linux-2.6/drivers/acpi/acpica/evxfevnt.c @@ -379,21 +379,12 @@ acpi_status acpi_gpe_can_wake(acpi_handl /* 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) { + if (gpe_event_info) { + gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; + } else { status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) { - goto unlock_and_exit; } - gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; - if (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) { - (void)acpi_raw_disable_gpe(gpe_event_info); - } - -unlock_and_exit: acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } @@ -651,7 +642,7 @@ acpi_install_gpe_block(acpi_handle gpe_d struct acpi_generic_address *gpe_block_address, u32 register_count, u32 interrupt_number) { - acpi_status status; + acpi_status status = AE_OK; union acpi_operand_object *obj_desc; struct acpi_namespace_node *node; struct acpi_gpe_block_info *gpe_block; @@ -715,10 +706,6 @@ acpi_install_gpe_block(acpi_handle gpe_d obj_desc->device.gpe_block = gpe_block; - /* Enable the runtime GPEs in the new block */ - - status = acpi_ev_initialize_gpe_block(node, gpe_block); - unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); @@ -924,3 +911,38 @@ acpi_status acpi_enable_all_runtime_gpes return_ACPI_STATUS(status); } + +/****************************************************************************** + * + * FUNCTION: acpi_start_gpes + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Enable all GPEs that have associated _Lxx or _Exx methods and + * are not pointed to by any device _PRW methods indicating that + * these GPEs are generally intended for system or device wakeup + * (such GPEs have to be enabled directly when the devices whose + * _PRW methods point to them are set up for wakeup signaling). + * + ******************************************************************************/ + +acpi_status acpi_start_gpes(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_start_gpes); + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_auto_enable_gpes = TRUE; + status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL); + + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + + return_ACPI_STATUS(status); +} Index: linux-2.6/drivers/acpi/acpica/acevents.h =================================================================== --- linux-2.6.orig/drivers/acpi/acpica/acevents.h +++ linux-2.6/drivers/acpi/acpica/acevents.h @@ -105,8 +105,9 @@ acpi_ev_create_gpe_block(struct acpi_nam struct acpi_gpe_block_info **return_gpe_block); acpi_status -acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, - struct acpi_gpe_block_info *gpe_block); +acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, + struct acpi_gpe_block_info *gpe_block, + void *ignored); acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block); Index: linux-2.6/drivers/acpi/acpica/evgpeblk.c =================================================================== --- linux-2.6.orig/drivers/acpi/acpica/evgpeblk.c +++ linux-2.6/drivers/acpi/acpica/evgpeblk.c @@ -434,14 +434,14 @@ acpi_ev_create_gpe_block(struct acpi_nam ******************************************************************************/ acpi_status -acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, - struct acpi_gpe_block_info *gpe_block) +acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, + struct acpi_gpe_block_info *gpe_block, + void *ignored) { acpi_status status; struct acpi_gpe_event_info *gpe_event_info; u32 gpe_enabled_count; u32 gpe_index; - u32 gpe_number; u32 i; u32 j; @@ -454,15 +454,12 @@ acpi_ev_initialize_gpe_block(struct acpi } /* - * Enable all GPEs that have a corresponding method. Any other GPEs - * within this block must be enabled via the acpi_enable_gpe interface. + * Enable all GPEs that have a corresponding method and have the + * ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block must + * be enabled via the acpi_enable_gpe() interface. */ 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 < ACPI_GPE_REGISTER_WIDTH; j++) { @@ -470,27 +467,19 @@ acpi_ev_initialize_gpe_block(struct acpi gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j; gpe_event_info = &gpe_block->event_info[gpe_index]; - gpe_number = gpe_index + gpe_block->block_base_number; /* Ignore GPEs that have no corresponding _Lxx/_Exx method */ - if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)) { + if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) + || (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { continue; } - /* - * If the GPE has already been enabled for runtime - * signaling, make sure it remains enabled, but do not - * increment its reference counter. - */ - status = gpe_event_info->runtime_count ? - acpi_ev_enable_gpe(gpe_event_info) : - acpi_enable_gpe(gpe_device, gpe_number); - + status = acpi_raw_enable_gpe(gpe_event_info); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, - "Could not enable GPE 0x%02X", - gpe_number)); + "Could not enable GPE 0x%02X", + gpe_index + gpe_block->block_base_number)); continue; } Index: linux-2.6/include/acpi/acpixf.h =================================================================== --- linux-2.6.orig/include/acpi/acpixf.h +++ linux-2.6/include/acpi/acpixf.h @@ -308,6 +308,8 @@ acpi_install_gpe_block(acpi_handle gpe_d acpi_status acpi_remove_gpe_block(acpi_handle gpe_device); +acpi_status acpi_start_gpes(void); + /* * Resource interfaces */ Index: linux-2.6/drivers/acpi/acpica/aclocal.h =================================================================== --- linux-2.6.orig/drivers/acpi/acpica/aclocal.h +++ linux-2.6/drivers/acpi/acpica/aclocal.h @@ -413,6 +413,7 @@ struct acpi_handler_info { void *context; /* Context to be passed to handler */ struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */ u8 orig_flags; /* Original misc info about this GPE */ + u8 orig_enabled; /* Set if the GPE was originally enabled */ }; union acpi_gpe_dispatch_info { Index: linux-2.6/drivers/acpi/acpica/evevent.c =================================================================== --- linux-2.6.orig/drivers/acpi/acpica/evevent.c +++ linux-2.6/drivers/acpi/acpica/evevent.c @@ -95,47 +95,6 @@ acpi_status acpi_ev_initialize_events(vo /******************************************************************************* * - * FUNCTION: acpi_ev_install_fadt_gpes - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Completes initialization of the FADT-defined GPE blocks - * (0 and 1). The HW must be fully initialized at this point, - * including global lock support. - * - ******************************************************************************/ - -acpi_status acpi_ev_install_fadt_gpes(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_install_fadt_gpes); - - /* Namespace must be locked */ - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* FADT GPE Block 0 */ - - (void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device, - acpi_gbl_gpe_fadt_blocks[0]); - - /* FADT GPE Block 1 */ - - (void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device, - acpi_gbl_gpe_fadt_blocks[1]); - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * * FUNCTION: acpi_ev_install_xrupt_handlers * * PARAMETERS: None Index: linux-2.6/drivers/acpi/acpica/utxface.c =================================================================== --- linux-2.6.orig/drivers/acpi/acpica/utxface.c +++ linux-2.6/drivers/acpi/acpica/utxface.c @@ -290,19 +290,6 @@ acpi_status acpi_initialize_objects(u32 } /* - * Complete the GPE initialization for the GPE blocks defined in the FADT - * (GPE block 0 and 1). - * - * NOTE: Currently, there seems to be no need to run the _REG methods - * before enabling the GPEs. - */ - if (!(flags & ACPI_NO_EVENT_INIT)) { - status = acpi_ev_install_fadt_gpes(); - if (ACPI_FAILURE(status)) - return (status); - } - - /* * Empty the caches (delete the cached objects) on the assumption that * the table load filled them up more than they will be at runtime -- * thus wasting non-paged memory. Index: linux-2.6/drivers/acpi/bus.c =================================================================== --- linux-2.6.orig/drivers/acpi/bus.c +++ linux-2.6/drivers/acpi/bus.c @@ -1032,6 +1032,7 @@ static int __init acpi_init(void) dmi_check_system(power_nocheck_dmi_table); acpi_scan_init(); + acpi_start_gpes(); acpi_ec_init(); acpi_power_init(); acpi_sysfs_init(); Index: linux-2.6/drivers/acpi/acpica/evxface.c =================================================================== --- linux-2.6.orig/drivers/acpi/acpica/evxface.c +++ linux-2.6/drivers/acpi/acpica/evxface.c @@ -793,15 +793,16 @@ acpi_install_gpe_handler(acpi_handle gpe (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* - * If the GPE is associated with a method and it cannot wake up the - * system from sleep states, it was enabled automatically during - * initialization, so it has to be disabled now to avoid spurious - * execution of the handler. + * If the GPE is associated with a method, it might have been enabled + * automatically during initialization, in which case it has to be + * disabled now to avoid spurious execution of the handler. */ if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD) - && !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) + && gpe_event_info->runtime_count) { + handler->orig_enabled = 1; (void)acpi_raw_disable_gpe(gpe_event_info); + } /* Install the handler */ @@ -904,13 +905,13 @@ acpi_remove_gpe_handler(acpi_handle gpe_ gpe_event_info->flags |= handler->orig_flags; /* - * If the GPE was previously associated with a method and it cannot wake - * up the system from sleep states, it should be enabled at this point - * to restore the post-initialization configuration. + * If the GPE was previously associated with a method and it was + * enabled, it should be enabled at this point to restore the + * post-initialization configuration. */ if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD) - && !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) + && handler->orig_enabled) (void)acpi_raw_enable_gpe(gpe_event_info); /* Now we can free the handler object */ Index: linux-2.6/drivers/acpi/acpica/acglobal.h =================================================================== --- linux-2.6.orig/drivers/acpi/acpica/acglobal.h +++ linux-2.6/drivers/acpi/acpica/acglobal.h @@ -364,6 +364,7 @@ ACPI_EXTERN struct acpi_fixed_event_hand ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head; ACPI_EXTERN struct acpi_gpe_block_info *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]; +ACPI_EXTERN u8 acpi_auto_enable_gpes; /***************************************************************************** * Index: linux-2.6/drivers/acpi/acpica/utglobal.c =================================================================== --- linux-2.6.orig/drivers/acpi/acpica/utglobal.c +++ linux-2.6/drivers/acpi/acpica/utglobal.c @@ -766,6 +766,7 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_gpe_fadt_blocks[0] = NULL; acpi_gbl_gpe_fadt_blocks[1] = NULL; acpi_current_gpe_count = 0; + acpi_auto_enable_gpes = FALSE; /* Global handlers */ Index: linux-2.6/drivers/acpi/acpica/evgpeinit.c =================================================================== --- linux-2.6.orig/drivers/acpi/acpica/evgpeinit.c +++ linux-2.6/drivers/acpi/acpica/evgpeinit.c @@ -239,7 +239,7 @@ void acpi_ev_update_gpes(acpi_owner_id t walk_info.owner_id = table_owner_id; walk_info.execute_by_owner_id = TRUE; walk_info.count = 0; - walk_info.enable_this_gpe = TRUE; + walk_info.enable_this_gpe = acpi_auto_enable_gpes; /* Walk the interrupt level descriptor list */