From patchwork Mon Nov 12 22:28:16 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Wu X-Patchwork-Id: 1731491 Return-Path: X-Original-To: patchwork-linux-acpi@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 73773DFE80 for ; Mon, 12 Nov 2012 22:28:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752718Ab2KLW2U (ORCPT ); Mon, 12 Nov 2012 17:28:20 -0500 Received: from mail-wi0-f170.google.com ([209.85.212.170]:36982 "EHLO mail-wi0-f170.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752157Ab2KLW2T (ORCPT ); Mon, 12 Nov 2012 17:28:19 -0500 Received: by mail-wi0-f170.google.com with SMTP id hm9so2686201wib.1 for ; Mon, 12 Nov 2012 14:28:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:user-agent:mime-version :content-transfer-encoding:content-type; bh=Gx0zsizaIOwaAfu+AjiCFF3PqdjZ8vVlgKHUH5l2q/8=; b=MpbSWq+xDzgsLRS0J9R9r0fm6cPsll1skAX8kdrn2UXQxrbrqZnNlv2klkKN0wQeo3 X5W3fAS8BTQPLYqGC1nJI6n7KKDrmFpkRiUgVGgPhL3hRhd4vp4mt6A2+0QgZML/Z2XT PGey27OPS+uc5Tj3+RY7GHjQ5i3AleDCcB/OYLFGs183D2TIj0snA3TTbhqu3WQ7shpl JvymEq8Xkg8Aq7U3rEhhmfefZ2JZrKQG4fp4i6R42bAsANhp7TlRFGP1WiollEJ4rz+e Mue/H7EEeJZxzhud8JsgW1axzaaJ7lfnMPtP4K3wOn5HsWfUhEBQs6fSuIipgPJleEtY 2pDQ== Received: by 10.180.94.169 with SMTP id dd9mr17196323wib.14.1352759298664; Mon, 12 Nov 2012 14:28:18 -0800 (PST) Received: from al.localnet (svr.lekensteyn.nl. [178.21.112.251]) by mx.google.com with ESMTPS id ec3sm4247227wib.10.2012.11.12.14.28.17 (version=SSLv3 cipher=OTHER); Mon, 12 Nov 2012 14:28:18 -0800 (PST) From: Lekensteyn To: Len Brown , "Rafael J. Wysocki" Cc: linux-acpi@vger.kernel.org, Sergio Perez Subject: [PATCH] ACPI: return first _ADR match for acpi_get_child Date: Mon, 12 Nov 2012 23:28:16 +0100 Message-ID: <8150264.b2f1OROKxE@al> User-Agent: KMail/4.9.3 (Linux/3.7.0-1-custom; KDE/4.9.3; x86_64; ; ) MIME-Version: 1.0 Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org From: Peter Wu When acpi_get_child is called, it loops through all direct child devices and calls do_acpi_find_child to find an ACPI handle matching the _ADR. The previous implementation visits every direct child, if there were multiple devices with a matching _ADR, the last match was always returned. This behaviour (returning the last result) does not work for many recent Lenovo machines when looking for the correct ACPI handle for a Nvidia PCI video device. On these machines, the first handle should be used instead of the last one. On these machines, the PCI Bus ID is 01:00.0, hence the address that is searched for is 0 (via acpi_pci_find_device). When acpi_pci_find_device calls acpi_get_child, it iterates through: Address: 00000000 (valid); handle: \_SB_.PCI0.PEG0.PEGP Address: 00000001 (valid); handle: \_SB_.PCI0.PEG0.VGA1 Address: 00000000 (valid); handle: \_SB_.PCI0.PEG0.VGA_ The correct handle here is "\_SB_.PCI0.PEG0.PEGP" which contains the _ROM method as well as _PSx for PM, and not \_SB.PCI0.PEG0.VGA. On my own laptop, and many others I believe, there is only one matching handle for a PCI device. The acpi_get_child method has been added in 2005, 4e10d12a3d88c88fba3258809aa42d14fd8cf1d1, and there is no message indicating that the last (or first) handle should be returned. However, it is kind of useless to iterate from beginning to the end if you only need the last match. Therefore, just return the first match (which is likely the last one too in almost all cases). Verified to work for an affected Lenovo Ideapad Y480, tested for no regressions on my laptop (Clevo B7130). Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=42696 Tested-by: Sergio Perez Signed-off-by: Peter Wu --- drivers/acpi/glue.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 0837308..dc9c945 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -99,18 +99,20 @@ struct acpi_find_child { static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl, void *context, void **rv) { - acpi_status status; + acpi_status status, ret = AE_OK; struct acpi_device_info *info; struct acpi_find_child *find = context; status = acpi_get_object_info(handle, &info); if (ACPI_SUCCESS(status)) { if ((info->address == find->address) - && (info->valid & ACPI_VALID_ADR)) + && (info->valid & ACPI_VALID_ADR)) { find->handle = handle; + ret = AE_CTRL_TERMINATE; + } kfree(info); } - return AE_OK; + return ret; } acpi_handle acpi_get_child(acpi_handle parent, u64 address)