From patchwork Fri Jun 10 19:55:13 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Nowicki X-Patchwork-Id: 9170383 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id E17776048F for ; Fri, 10 Jun 2016 19:58:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C81FD28369 for ; Fri, 10 Jun 2016 19:58:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BAF5A2836E; Fri, 10 Jun 2016 19:58:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 2ED9E2835E for ; Fri, 10 Jun 2016 19:58:20 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1bBSXp-0001MK-Ay; Fri, 10 Jun 2016 19:56:41 +0000 Received: from mail-lf0-x22e.google.com ([2a00:1450:4010:c07::22e]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1bBSXO-00012J-Ua for linux-arm-kernel@lists.infradead.org; Fri, 10 Jun 2016 19:56:17 +0000 Received: by mail-lf0-x22e.google.com with SMTP id q132so14580623lfe.3 for ; Fri, 10 Jun 2016 12:55:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Mwc6o0yx5itilQJdknr1WubNG3JjdtJb35VaEBQy2OM=; b=b3EzK1Xo4XkeRB3p7A0sz4D6dIHyAU4UZUq6hCu47TbUxGCHrkAXXlNTgJg0cVR7lS QHbjpU66xg/7DfMtBCWmYpul6uq484pJIoR4YIWvMAQgE7qqmlwxVVBBx6JOd8/tSGd7 D7rzcWer2RZJszl6MpCF5UlXXyIsbTXm+H//BTsY3f/4eW2KlnjfpkbDFr5ZjHP1xCDT 4i/Txj8AGCfbR46cuBCqbEPfERX86zlIrLtgBbEcDxAzny2OyfyPQSEQ+tgD6pPgp+uT l0v02MhD6y9okxnMFOD5DH3TtazaEdR9TiYa200SQmIlJgo3oKzrc5Fy46GjIyxARrZ/ DvjQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Mwc6o0yx5itilQJdknr1WubNG3JjdtJb35VaEBQy2OM=; b=YN8F0f+e+WUQw5mkD4MdbEewWbXuwznfdoyo2iRkl8if7eguqVfGw+7JgwJciKyjOX axm98ctfGC0Htfy9jYFXQjwlytMVK+U4cBeWZAgQM/i+EEnagFxDNDUZte8mcR8nbRx0 S97OB7OTjz/mV7VWp0WVLAT18dIWWJ0RwTMeT+uByTq3WUY1W/+vz/5pSNjNsomw+jx5 0ZF2LsbTSHK4ciuYmpdjpJ/GQtaFphZdKJrjCtRO5sx/APjge0kvE0XBeojVKe+xs54z /cLeTO7IIcRZkBWjyfdTzLm/QsN4s+nCBninjI4uGXteuBZCN847An2Vqq30fdfR0tEA Fi2A== X-Gm-Message-State: ALyK8tJxp/yAE/2D4jVXSlhZFfCMe689HEP/xO77vwz2FFSaDoEWfEbARYLKcGMKDc4aFw== X-Received: by 10.25.4.202 with SMTP id 193mr1165943lfe.204.1465588553079; Fri, 10 Jun 2016 12:55:53 -0700 (PDT) Received: from tn-HP-4.semihalf.local (31-172-191-173.noc.fibertech.net.pl. [31.172.191.173]) by smtp.gmail.com with ESMTPSA id a190sm1377175lfe.21.2016.06.10.12.55.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 10 Jun 2016 12:55:52 -0700 (PDT) From: Tomasz Nowicki To: helgaas@kernel.org, arnd@arndb.de, will.deacon@arm.com, catalin.marinas@arm.com, rafael@kernel.org, hanjun.guo@linaro.org, Lorenzo.Pieralisi@arm.com, okaya@codeaurora.org, jchandra@broadcom.com Subject: [PATCH V9 05/11] ACPI/PCI: Add generic MCFG table handling Date: Fri, 10 Jun 2016 21:55:13 +0200 Message-Id: <1465588519-11334-6-git-send-email-tn@semihalf.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1465588519-11334-1-git-send-email-tn@semihalf.com> References: <1465588519-11334-1-git-send-email-tn@semihalf.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160610_125615_408144_57D8DCD0 X-CRM114-Status: GOOD ( 22.81 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: jcm@redhat.com, linaro-acpi@lists.linaro.org, linux-pci@vger.kernel.org, dhdang@apm.com, Liviu.Dudau@arm.com, ddaney@caviumnetworks.com, jeremy.linton@arm.com, linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, robert.richter@caviumnetworks.com, cov@codeaurora.org, Suravee.Suthikulpanit@amd.com, msalter@redhat.com, wangyijing@huawei.com, Tomasz Nowicki , mw@semihalf.com, andrea.gallo@linaro.org, linux-arm-kernel@lists.infradead.org, liudongdong3@huawei.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP According to PCI firmware specifications, on systems booting with ACPI, PCI configuration for a host bridge must be set-up through the MCFG table regions for non-hotpluggable bridges and _CBA method for hotpluggable ones. Current MCFG table handling code, as implemented for x86, cannot be easily generalized owing to x86 specific quirks handling and related code, which makes it hard to reuse on other architectures. In order to implement MCFG PCI configuration handling for new platforms booting with ACPI (eg ARM64) this patch re-implements MCFG handling from scratch in a streamlined fashion and provides (through a generic interface available to all arches): - Simplified MCFG table parsing (executed through the pci_mmcfg_late_init() hook as in current x86) - MCFG regions look-up interface through domain:bus_start:bus_end tuple The new MCFG regions handling interface is added to generic ACPI code so that existing architectures (eg x86) can be moved over to it and architectures relying on MCFG for ACPI PCI config space can rely on it without having to resort to arch specific implementations. Signed-off-by: Tomasz Nowicki Signed-off-by: Jayachandran C Reviewed-by: Lorenzo Pieralisi --- drivers/acpi/Kconfig | 3 ++ drivers/acpi/Makefile | 1 + drivers/acpi/pci_mcfg.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/pci-acpi.h | 2 ++ include/linux/pci.h | 2 +- 5 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 drivers/acpi/pci_mcfg.c diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index b7e2e77..f98c328 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -217,6 +217,9 @@ config ACPI_PROCESSOR_IDLE bool select CPU_IDLE +config ACPI_MCFG + bool + config ACPI_CPPC_LIB bool depends on ACPI_PROCESSOR diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 251ce85..632e81f 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -40,6 +40,7 @@ acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o acpi-y += pci_root.o pci_link.o pci_irq.o +obj-$(CONFIG_ACPI_MCFG) += pci_mcfg.o acpi-y += acpi_lpss.o acpi_apd.o acpi-y += acpi_platform.o acpi-y += acpi_pnp.o diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c new file mode 100644 index 0000000..d3c3e85 --- /dev/null +++ b/drivers/acpi/pci_mcfg.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2016 Broadcom + * Author: Jayachandran C + * Copyright (C) 2016 Semihalf + * Author: Tomasz Nowicki + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ + +#define pr_fmt(fmt) "ACPI: " fmt + +#include +#include +#include + +/* Structure to hold entries from the MCFG table */ +struct mcfg_entry { + struct list_head list; + phys_addr_t addr; + u16 segment; + u8 bus_start; + u8 bus_end; +}; + +/* List to save mcfg entries */ +static LIST_HEAD(pci_mcfg_list); + +phys_addr_t pci_mcfg_lookup(u16 seg, struct resource *bus_res) +{ + struct mcfg_entry *e; + + /* + * We expect exact match, unless MCFG entry end bus covers more than + * specified by caller. + */ + list_for_each_entry(e, &pci_mcfg_list, list) { + if (e->segment == seg && e->bus_start == bus_res->start && + e->bus_end >= bus_res->end) + return e->addr; + } + + return 0; +} + +static __init int pci_mcfg_parse(struct acpi_table_header *header) +{ + struct acpi_table_mcfg *mcfg; + struct acpi_mcfg_allocation *mptr; + struct mcfg_entry *e, *arr; + int i, n; + + if (header->length < sizeof(struct acpi_table_mcfg)) + return -EINVAL; + + n = (header->length - sizeof(struct acpi_table_mcfg)) / + sizeof(struct acpi_mcfg_allocation); + mcfg = (struct acpi_table_mcfg *)header; + mptr = (struct acpi_mcfg_allocation *) &mcfg[1]; + + arr = kcalloc(n, sizeof(*arr), GFP_KERNEL); + if (!arr) + return -ENOMEM; + + for (i = 0, e = arr; i < n; i++, mptr++, e++) { + e->segment = mptr->pci_segment; + e->addr = mptr->address; + e->bus_start = mptr->start_bus_number; + e->bus_end = mptr->end_bus_number; + list_add(&e->list, &pci_mcfg_list); + } + + pr_info("MCFG table detected, %d entries\n", n); + return 0; +} + +/* Interface called by ACPI - parse and save MCFG table */ +void __init pci_mmcfg_late_init(void) +{ + int err = acpi_table_parse(ACPI_SIG_MCFG, pci_mcfg_parse); + if (err) + pr_err("Failed to parse MCFG (%d)\n", err); +} diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h index 89ab057..7d63a66 100644 --- a/include/linux/pci-acpi.h +++ b/include/linux/pci-acpi.h @@ -24,6 +24,8 @@ static inline acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev) } extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle); +extern phys_addr_t pci_mcfg_lookup(u16 domain, struct resource *bus_res); + static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev) { struct pci_bus *pbus = pdev->bus; diff --git a/include/linux/pci.h b/include/linux/pci.h index 12349de..ce03d65 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1723,7 +1723,7 @@ void pcibios_free_irq(struct pci_dev *dev); extern struct dev_pm_ops pcibios_pm_ops; #endif -#ifdef CONFIG_PCI_MMCONFIG +#if defined(CONFIG_PCI_MMCONFIG) || defined(CONFIG_ACPI_MCFG) void __init pci_mmcfg_early_init(void); void __init pci_mmcfg_late_init(void); #else