From patchwork Fri Oct 8 10:40:14 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Renninger X-Patchwork-Id: 241081 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 o98AeL8q027768 for ; Fri, 8 Oct 2010 10:40:24 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755763Ab0JHKkT (ORCPT ); Fri, 8 Oct 2010 06:40:19 -0400 Received: from cantor.suse.de ([195.135.220.2]:46516 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753053Ab0JHKkS (ORCPT ); Fri, 8 Oct 2010 06:40:18 -0400 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.221.2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.suse.de (Postfix) with ESMTP id 1B75094393; Fri, 8 Oct 2010 12:40:17 +0200 (CEST) From: Thomas Renninger Organization: SUSE Products GmbH To: "Moore, Robert" , ACPI Devel Maling List Subject: [PATCH] ACPICA: Do not hang at mutex forever if BIOS tries to release global lock Date: Fri, 8 Oct 2010 12:40:14 +0200 User-Agent: KMail/1.13.3 (Linux/2.6.31.5-0.1-desktop; KDE/4.4.3; x86_64; ; ) Cc: devel@acpica.org, stuart_hayes@dell.com MIME-Version: 1.0 Message-Id: <201010081240.15203.trenn@suse.de> 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]); Fri, 08 Oct 2010 10:40:24 +0000 (UTC) From: Stuart Hayes ACPICA: Do not hang at mutex forever if BIOS tries to release global lock and OS did not request the lock (means the pending bit was not set). Which in fact is a BIOS/HW bug (compare with ACPI Spec 3.0b): 5.2.10.1 Global Lock: .. This signal only occurs when the other environment attempted to acquire ownership while the lock was owned. .. or 4.7.3.1.1 PM1 Status Registers GBL_STS: .. This bit is set in response to the BIOS releasing control of the Global Lock and having seen the pending bit set. .. There seem to be chipsets which can get this wrong (especially after a kexec boot on Linux). Also one could theoretically run into this if a new kernel got booted without proper reboot and BIOS re-initialization (like kexec) while: 1) The OS hold the global lock 2) The BIOS hold the global lock This patch would handle condition 1. To make sure condition 2. cannot happen, it should get stated in the ACPI spec that the global lock needs to be zeroed by BIOS everytime the OS tries to (re-)enable ACPI mode. Modifications by trenn: - Add a message -> This should not happen and if it happens it should not be ignored/handled silently - Adjusted from Linux kernel to acpica sources Signed-off-by: Thomas Renninger --- source/components/events/evmisc.c | 22 ++++++++++++++++++++-- source/components/utilities/utglobal.c | 1 + 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/source/components/events/evmisc.c b/source/components/events/evmisc.c index b0e1cac..8c0f9b1 100644 --- a/source/components/events/evmisc.c +++ b/source/components/events/evmisc.c @@ -399,6 +399,23 @@ AcpiEvGlobalLockHandler ( /* + * This must not happen: BIOS must only release the lock if OS has set + * it pending. Such inconsistancies could happen if another kernel is booted + * without a proper reboot and BIOS re-initialization and the global lock bits + * did not get cleared. But in general it's a BIOS bug if a gbl lock release + * GPE is triggered and OS has not tried to acquire the lock. + */ + + if (!AcpiGbl_GlobalLockPending) { + u8 pending; + /* Clear lock bits. BIOS released lock and OS isn't waiting. */ + ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_FACS, pending) + ACPI_WARNING ((AE_INFO, "Global lock release GPE, even OS did not try" + "to acquire the lock")); + return (ACPI_INTERRUPT_HANDLED); + } + + /* * Attempt to get the lock. * * If we don't get it now, it will be marked pending and we will @@ -410,7 +427,7 @@ AcpiEvGlobalLockHandler ( /* Got the lock, now wake the thread waiting for it */ AcpiGbl_GlobalLockAcquired = TRUE; - + AcpiGbl_GlobalLockPending--; /* Send a unit to the semaphore */ Status = AcpiOsSignalSemaphore (AcpiGbl_GlobalLockSemaphore, 1); @@ -579,7 +596,8 @@ AcpiEvAcquireGlobalLock ( AcpiGbl_GlobalLockAcquired = TRUE; return_ACPI_STATUS (AE_OK); - } + } else + AcpiGbl_GlobalLockPending++; /* * Did not get the lock. The pending bit was set above, and we must now diff --git a/source/components/utilities/utglobal.c b/source/components/utilities/utglobal.c index a7e1baa..5f0f29f 100644 --- a/source/components/utilities/utglobal.c +++ b/source/components/utilities/utglobal.c @@ -916,6 +916,7 @@ AcpiUtInitGlobals ( AcpiGbl_GlobalLockAcquired = FALSE; AcpiGbl_GlobalLockHandle = 0; AcpiGbl_GlobalLockPresent = FALSE; + AcpiGbl_GlobalLockPending = 0; /* Miscellaneous variables */