From patchwork Wed May 23 03:50:23 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Liu X-Patchwork-Id: 160786 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id C1FAEB6FCA for ; Wed, 23 May 2012 13:51:54 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759074Ab2EWDvx (ORCPT ); Tue, 22 May 2012 23:51:53 -0400 Received: from szxga01-in.huawei.com ([58.251.152.64]:60629 "EHLO szxga01-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756729Ab2EWDvw (ORCPT ); Tue, 22 May 2012 23:51:52 -0400 Received: from huawei.com (szxga05-in [172.24.2.49]) by szxga05-in.huawei.com (iPlanet Messaging Server 5.2 HotFix 2.14 (built Aug 8 2006)) with ESMTP id <0M4G00KWHIPTEE@szxga05-in.huawei.com>; Wed, 23 May 2012 11:51:29 +0800 (CST) Received: from szxrg01-dlp.huawei.com ([172.24.2.119]) by szxga05-in.huawei.com (iPlanet Messaging Server 5.2 HotFix 2.14 (built Aug 8 2006)) with ESMTP id <0M4G0025AIPTW7@szxga05-in.huawei.com>; Wed, 23 May 2012 11:51:29 +0800 (CST) Received: from szxeml211-edg.china.huawei.com ([172.24.2.119]) by szxrg01-dlp.huawei.com (MOS 4.1.9-GA) with ESMTP id AJH53288; Wed, 23 May 2012 11:50:58 +0800 Received: from SZXEML416-HUB.china.huawei.com (10.82.67.155) by szxeml211-edg.china.huawei.com (172.24.2.182) with Microsoft SMTP Server (TLS) id 14.1.323.3; Wed, 23 May 2012 11:50:52 +0800 Received: from localhost (10.107.208.49) by szxeml416-hub.china.huawei.com (10.82.67.155) with Microsoft SMTP Server id 14.1.323.3; Wed, 23 May 2012 11:50:49 +0800 Date: Wed, 23 May 2012 11:50:23 +0800 From: Jiang Liu Subject: [PATCH v6 6/9] PCI, ACPI: provide MCFG address for PCI host bridges In-reply-to: <1337745026-1180-1-git-send-email-jiang.liu@huawei.com> X-Originating-IP: [10.107.208.49] To: Bjorn Helgaas , Taku Izumi , Yinghai Lu , Kenji Kaneshige , Don Dutile Cc: Jiang Liu , Yijing Wang , Keping Chen , linux-acpi , linux-pci@vger.kernel.org Message-id: <1337745026-1180-7-git-send-email-jiang.liu@huawei.com> MIME-version: 1.0 X-Mailer: git-send-email 1.7.8.msysgit.0 Content-type: text/plain Content-transfer-encoding: 7BIT X-CFilter-Loop: Reflected References: <1337745026-1180-1-git-send-email-jiang.liu@huawei.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org From: Jiang Liu From: Jiang Liu This patch provide MCFG address for PCI host bridges, which will be used to support host bridge hotplug. It gets MCFG address by evaluating _CBA method if available, or by scanning the ACPI MCFG table. Signed-off-by: Jiang Liu --- drivers/acpi/pci_root.c | 12 ++++++++++++ drivers/pci/pci-acpi.c | 34 ++++++++++++++++++++++++++++++++++ include/acpi/acnames.h | 1 + include/acpi/acpi_bus.h | 3 +++ include/linux/pci-acpi.h | 5 +++++ 5 files changed, 55 insertions(+), 0 deletions(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 7aff631..fc716cf 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -458,6 +458,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) acpi_handle handle; struct acpi_device *child; u32 flags, base_flags; + int end_bus = -1; root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); if (!root) @@ -505,6 +506,17 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); device->driver_data = root; + root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle, + root->segment, (uint8_t)root->secondary.start, &end_bus); + + /* + * End bus number for MCFG may be less than root's subordinary + * bus number with buggy BIOS implementation. + */ + if (end_bus < 0 || end_bus > root->secondary.end) + end_bus = root->secondary.end; + root->mcfg_end_bus = (uint8_t)end_bus; + /* * All supported architectures that use ACPI have support for * PCI domains, so we indicate this in _OSC support capabilities. diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 0f150f2..9af71d2 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -162,6 +162,40 @@ acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev) return remove_pm_notifier(dev, pci_acpi_wake_dev); } +/* acpi_table_parse() is marked as __init, so cache MCFG info at boot time */ +int pci_acpi_mcfg_entries; +struct acpi_mcfg_allocation *pci_acpi_mcfg_array; + +phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle, uint16_t seg, + uint8_t start, int *endp) +{ + int i, end_bus = -1; + acpi_status status = AE_NOT_EXIST; + unsigned long long mcfg_addr = 0; + struct acpi_mcfg_allocation *cfg; + + if (handle) + status = acpi_evaluate_integer(handle, METHOD_NAME__CBA, + NULL, &mcfg_addr); + if (ACPI_FAILURE(status) && pci_acpi_mcfg_entries && + pci_acpi_mcfg_array) { + mcfg_addr = 0; + cfg = pci_acpi_mcfg_array; + for (i = 0; i < pci_acpi_mcfg_entries; i++, cfg++) + if (seg == cfg->pci_segment && + start >= cfg->start_bus_number && + start <= cfg->end_bus_number) { + end_bus = cfg->end_bus_number; + mcfg_addr = cfg->address; + break; + } + } + if (endp) + *endp = end_bus; + + return (phys_addr_t)mcfg_addr; +} + /* * _SxD returns the D-state with the highest power * (lowest D-state number) supported in the S-state "x". diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h index 38f5088..99bda75 100644 --- a/include/acpi/acnames.h +++ b/include/acpi/acnames.h @@ -62,6 +62,7 @@ #define METHOD_NAME__AEI "_AEI" #define METHOD_NAME__PRW "_PRW" #define METHOD_NAME__SRS "_SRS" +#define METHOD_NAME__CBA "_CBA" /* Method names - these methods must appear at the namespace root */ diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index f1c8ca6..8bc5229 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -370,6 +370,9 @@ struct acpi_pci_root { u32 osc_support_set; /* _OSC state of support bits */ u32 osc_control_set; /* _OSC state of control bits */ + uint8_t mcfg_end_bus; /* End bus for MCFG may differ from + * root's subordinary bus. */ + phys_addr_t mcfg_addr; }; /* helper */ diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h index 4462350..0369149 100644 --- a/include/linux/pci-acpi.h +++ b/include/linux/pci-acpi.h @@ -11,12 +11,17 @@ #include #ifdef CONFIG_ACPI +extern int pci_acpi_mcfg_entries; +extern struct acpi_mcfg_allocation *pci_acpi_mcfg_array; + extern acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, struct pci_bus *pci_bus); extern acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev); extern acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, struct pci_dev *pci_dev); extern acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev); +extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle, + uint16_t seg, uint8_t start, int *endp); static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev) {