diff options
Diffstat (limited to 'arm64-pcie-acpi.patch')
-rw-r--r-- | arm64-pcie-acpi.patch | 1247 |
1 files changed, 0 insertions, 1247 deletions
diff --git a/arm64-pcie-acpi.patch b/arm64-pcie-acpi.patch deleted file mode 100644 index e9a359db6..000000000 --- a/arm64-pcie-acpi.patch +++ /dev/null @@ -1,1247 +0,0 @@ -From 1fc02559de87cd88339a83ad05baa9c2b5bd1ac0 Mon Sep 17 00:00:00 2001 -From: Jayachandran C <jchandra@broadcom.com> -Date: Fri, 10 Jun 2016 21:55:09 +0200 -Subject: [PATCH 01/11] PCI/ECAM: Move ecam.h to linux/include/pci-ecam.h - -This header will be used from arch/arm64 for ACPI PCI implementation -so it needs to be moved out of drivers/pci. - -Update users of the header file to use the new name. No functional -changes. - -Signed-off-by: Jayachandran C <jchandra@broadcom.com> -Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> ---- - drivers/pci/ecam.c | 3 +- - drivers/pci/ecam.h | 67 ------------------------------------- - drivers/pci/host/pci-host-common.c | 3 +- - drivers/pci/host/pci-host-generic.c | 3 +- - drivers/pci/host/pci-thunder-ecam.c | 3 +- - drivers/pci/host/pci-thunder-pem.c | 3 +- - include/linux/pci-ecam.h | 67 +++++++++++++++++++++++++++++++++++++ - 7 files changed, 72 insertions(+), 77 deletions(-) - delete mode 100644 drivers/pci/ecam.h - create mode 100644 include/linux/pci-ecam.h - -diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c -index f9832ad..820e26b 100644 ---- a/drivers/pci/ecam.c -+++ b/drivers/pci/ecam.c -@@ -19,10 +19,9 @@ - #include <linux/kernel.h> - #include <linux/module.h> - #include <linux/pci.h> -+#include <linux/pci-ecam.h> - #include <linux/slab.h> - --#include "ecam.h" -- - /* - * On 64-bit systems, we do a single ioremap for the whole config space - * since we have enough virtual address range available. On 32-bit, we -diff --git a/drivers/pci/ecam.h b/drivers/pci/ecam.h -deleted file mode 100644 -index 9878beb..0000000 ---- a/drivers/pci/ecam.h -+++ /dev/null -@@ -1,67 +0,0 @@ --/* -- * Copyright 2016 Broadcom -- * -- * 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. -- */ --#ifndef DRIVERS_PCI_ECAM_H --#define DRIVERS_PCI_ECAM_H -- --#include <linux/kernel.h> --#include <linux/platform_device.h> -- --/* -- * struct to hold pci ops and bus shift of the config window -- * for a PCI controller. -- */ --struct pci_config_window; --struct pci_ecam_ops { -- unsigned int bus_shift; -- struct pci_ops pci_ops; -- int (*init)(struct device *, -- struct pci_config_window *); --}; -- --/* -- * struct to hold the mappings of a config space window. This -- * is expected to be used as sysdata for PCI controllers that -- * use ECAM. -- */ --struct pci_config_window { -- struct resource res; -- struct resource busr; -- void *priv; -- struct pci_ecam_ops *ops; -- union { -- void __iomem *win; /* 64-bit single mapping */ -- void __iomem **winp; /* 32-bit per-bus mapping */ -- }; --}; -- --/* create and free pci_config_window */ --struct pci_config_window *pci_ecam_create(struct device *dev, -- struct resource *cfgres, struct resource *busr, -- struct pci_ecam_ops *ops); --void pci_ecam_free(struct pci_config_window *cfg); -- --/* map_bus when ->sysdata is an instance of pci_config_window */ --void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn, -- int where); --/* default ECAM ops */ --extern struct pci_ecam_ops pci_generic_ecam_ops; -- --#ifdef CONFIG_PCI_HOST_GENERIC --/* for DT-based PCI controllers that support ECAM */ --int pci_host_common_probe(struct platform_device *pdev, -- struct pci_ecam_ops *ops); --#endif --#endif -diff --git a/drivers/pci/host/pci-host-common.c b/drivers/pci/host/pci-host-common.c -index 8cba7ab..c18b9e3 100644 ---- a/drivers/pci/host/pci-host-common.c -+++ b/drivers/pci/host/pci-host-common.c -@@ -20,10 +20,9 @@ - #include <linux/module.h> - #include <linux/of_address.h> - #include <linux/of_pci.h> -+#include <linux/pci-ecam.h> - #include <linux/platform_device.h> - --#include "../ecam.h" -- - static int gen_pci_parse_request_of_pci_ranges(struct device *dev, - struct list_head *resources, struct resource **bus_range) - { -diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c -index 6eaceab..f0ca6de 100644 ---- a/drivers/pci/host/pci-host-generic.c -+++ b/drivers/pci/host/pci-host-generic.c -@@ -23,10 +23,9 @@ - #include <linux/module.h> - #include <linux/of_address.h> - #include <linux/of_pci.h> -+#include <linux/pci-ecam.h> - #include <linux/platform_device.h> - --#include "../ecam.h" -- - static struct pci_ecam_ops gen_pci_cfg_cam_bus_ops = { - .bus_shift = 16, - .pci_ops = { -diff --git a/drivers/pci/host/pci-thunder-ecam.c b/drivers/pci/host/pci-thunder-ecam.c -index 540d030..a9fc1c9 100644 ---- a/drivers/pci/host/pci-thunder-ecam.c -+++ b/drivers/pci/host/pci-thunder-ecam.c -@@ -11,10 +11,9 @@ - #include <linux/ioport.h> - #include <linux/of_pci.h> - #include <linux/of.h> -+#include <linux/pci-ecam.h> - #include <linux/platform_device.h> - --#include "../ecam.h" -- - static void set_val(u32 v, int where, int size, u32 *val) - { - int shift = (where & 3) * 8; -diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c -index 9b8ab94..5020d3d 100644 ---- a/drivers/pci/host/pci-thunder-pem.c -+++ b/drivers/pci/host/pci-thunder-pem.c -@@ -18,10 +18,9 @@ - #include <linux/module.h> - #include <linux/of_address.h> - #include <linux/of_pci.h> -+#include <linux/pci-ecam.h> - #include <linux/platform_device.h> - --#include "../ecam.h" -- - #define PEM_CFG_WR 0x28 - #define PEM_CFG_RD 0x30 - -diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h -new file mode 100644 -index 0000000..9878beb ---- /dev/null -+++ b/include/linux/pci-ecam.h -@@ -0,0 +1,67 @@ -+/* -+ * Copyright 2016 Broadcom -+ * -+ * 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. -+ */ -+#ifndef DRIVERS_PCI_ECAM_H -+#define DRIVERS_PCI_ECAM_H -+ -+#include <linux/kernel.h> -+#include <linux/platform_device.h> -+ -+/* -+ * struct to hold pci ops and bus shift of the config window -+ * for a PCI controller. -+ */ -+struct pci_config_window; -+struct pci_ecam_ops { -+ unsigned int bus_shift; -+ struct pci_ops pci_ops; -+ int (*init)(struct device *, -+ struct pci_config_window *); -+}; -+ -+/* -+ * struct to hold the mappings of a config space window. This -+ * is expected to be used as sysdata for PCI controllers that -+ * use ECAM. -+ */ -+struct pci_config_window { -+ struct resource res; -+ struct resource busr; -+ void *priv; -+ struct pci_ecam_ops *ops; -+ union { -+ void __iomem *win; /* 64-bit single mapping */ -+ void __iomem **winp; /* 32-bit per-bus mapping */ -+ }; -+}; -+ -+/* create and free pci_config_window */ -+struct pci_config_window *pci_ecam_create(struct device *dev, -+ struct resource *cfgres, struct resource *busr, -+ struct pci_ecam_ops *ops); -+void pci_ecam_free(struct pci_config_window *cfg); -+ -+/* map_bus when ->sysdata is an instance of pci_config_window */ -+void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn, -+ int where); -+/* default ECAM ops */ -+extern struct pci_ecam_ops pci_generic_ecam_ops; -+ -+#ifdef CONFIG_PCI_HOST_GENERIC -+/* for DT-based PCI controllers that support ECAM */ -+int pci_host_common_probe(struct platform_device *pdev, -+ struct pci_ecam_ops *ops); -+#endif -+#endif --- -2.7.4 - -From 5eb9996fc097629854f359f9ad3d959fdacb7f8f Mon Sep 17 00:00:00 2001 -From: Jayachandran C <jchandra@broadcom.com> -Date: Fri, 10 Jun 2016 21:55:10 +0200 -Subject: [PATCH 02/11] PCI/ECAM: Add parent device field to pci_config_window - -Add a parent device field to struct pci_config_window. The parent -is not saved now, but will be useful to save it in some cases. -Specifically in case of ACPI for ARM64, it can be used to setup -ACPI companion and domain. - -Since the parent dev is in struct pci_config_window now, we need -not pass it to the init function as a separate argument. - -Signed-off-by: Jayachandran C <jchandra@broadcom.com> -Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> ---- - drivers/pci/ecam.c | 3 ++- - drivers/pci/host/pci-thunder-pem.c | 3 ++- - include/linux/pci-ecam.h | 4 ++-- - 3 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c -index 820e26b..66e0d71 100644 ---- a/drivers/pci/ecam.c -+++ b/drivers/pci/ecam.c -@@ -51,6 +51,7 @@ struct pci_config_window *pci_ecam_create(struct device *dev, - if (!cfg) - return ERR_PTR(-ENOMEM); - -+ cfg->parent = dev; - cfg->ops = ops; - cfg->busr.start = busr->start; - cfg->busr.end = busr->end; -@@ -94,7 +95,7 @@ struct pci_config_window *pci_ecam_create(struct device *dev, - } - - if (ops->init) { -- err = ops->init(dev, cfg); -+ err = ops->init(cfg); - if (err) - goto err_exit; - } -diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c -index 5020d3d..91f6fc6 100644 ---- a/drivers/pci/host/pci-thunder-pem.c -+++ b/drivers/pci/host/pci-thunder-pem.c -@@ -284,8 +284,9 @@ static int thunder_pem_config_write(struct pci_bus *bus, unsigned int devfn, - return pci_generic_config_write(bus, devfn, where, size, val); - } - --static int thunder_pem_init(struct device *dev, struct pci_config_window *cfg) -+static int thunder_pem_init(struct pci_config_window *cfg) - { -+ struct device *dev = cfg->parent; - resource_size_t bar4_start; - struct resource *res_pem; - struct thunder_pem_pci *pem_pci; -diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h -index 9878beb..7adad20 100644 ---- a/include/linux/pci-ecam.h -+++ b/include/linux/pci-ecam.h -@@ -27,8 +27,7 @@ struct pci_config_window; - struct pci_ecam_ops { - unsigned int bus_shift; - struct pci_ops pci_ops; -- int (*init)(struct device *, -- struct pci_config_window *); -+ int (*init)(struct pci_config_window *); - }; - - /* -@@ -45,6 +44,7 @@ struct pci_config_window { - void __iomem *win; /* 64-bit single mapping */ - void __iomem **winp; /* 32-bit per-bus mapping */ - }; -+ struct device *parent;/* ECAM res was from this dev */ - }; - - /* create and free pci_config_window */ --- -2.7.4 - -From 6ed6c1365df5c9201e9b275e8ed4eaa64ef2ec0d Mon Sep 17 00:00:00 2001 -From: Sinan Kaya <okaya@codeaurora.org> -Date: Fri, 10 Jun 2016 21:55:11 +0200 -Subject: [PATCH 03/11] PCI: Add new function to unmap IO resources - -We need to release I/O resources so that the same I/O resources -can be allocated again in pci_remap_iospace(), like in PCI hotplug removal -scenario. Therefore implement new pci_unmap_iospace() call which -unmaps I/O space as the symmetry to pci_remap_iospace(). - -Signed-off-by: Sinan Kaya <okaya@codeaurora.org> -Signed-off-by: Tomasz Nowicki <tn@semihalf.com> -Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> ---- - drivers/pci/pci.c | 18 ++++++++++++++++++ - include/linux/pci.h | 1 + - 2 files changed, 19 insertions(+) - -diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c -index c8b4dbd..eb431b5 100644 ---- a/drivers/pci/pci.c -+++ b/drivers/pci/pci.c -@@ -25,6 +25,7 @@ - #include <linux/device.h> - #include <linux/pm_runtime.h> - #include <linux/pci_hotplug.h> -+#include <linux/vmalloc.h> - #include <asm/setup.h> - #include <linux/aer.h> - #include "pci.h" -@@ -3165,6 +3166,23 @@ int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr) - #endif - } - -+/** -+ * pci_unmap_iospace - Unmap the memory mapped I/O space -+ * @res: resource to be unmapped -+ * -+ * Unmap the CPU virtual address @res from virtual address space. -+ * Only architectures that have memory mapped IO functions defined -+ * (and the PCI_IOBASE value defined) should call this function. -+ */ -+void pci_unmap_iospace(struct resource *res) -+{ -+#if defined(PCI_IOBASE) && defined(CONFIG_MMU) -+ unsigned long vaddr = (unsigned long)PCI_IOBASE + res->start; -+ -+ unmap_kernel_range(vaddr, resource_size(res)); -+#endif -+} -+ - static void __pci_set_master(struct pci_dev *dev, bool enable) - { - u16 old_cmd, cmd; -diff --git a/include/linux/pci.h b/include/linux/pci.h -index b67e4df..12349de 100644 ---- a/include/linux/pci.h -+++ b/include/linux/pci.h -@@ -1167,6 +1167,7 @@ int pci_register_io_range(phys_addr_t addr, resource_size_t size); - unsigned long pci_address_to_pio(phys_addr_t addr); - phys_addr_t pci_pio_to_address(unsigned long pio); - int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr); -+void pci_unmap_iospace(struct resource *res); - - static inline pci_bus_addr_t pci_bus_address(struct pci_dev *pdev, int bar) - { --- -2.7.4 - -From 62f4d54fc2d2882b9ebaa920189574f422e12207 Mon Sep 17 00:00:00 2001 -From: Jayachandran C <jchandra@broadcom.com> -Date: Fri, 10 Jun 2016 21:55:12 +0200 -Subject: [PATCH 04/11] ACPI/PCI: Support IO resources when parsing PCI host - bridge resources - -Platforms that have memory mapped IO port (such as ARM64) need special -handling for PCI I/O resources. For host bridge's resource probing case -these resources need to be fixed up with -pci_register_io_range()/pci_remap_iospace() etc. - -The same I/O resources need to be released after hotplug -removal so that it can be re-added back by the pci_remap_iospace() -function during insertion. As a consequence unmap I/O resources -with pci_unmap_iospace() when we release host bridge resources. - -Signed-off-by: Jayachandran C <jchandra@broadcom.com> -Signed-off-by: Sinan Kaya <okaya@codeaurora.org> -[ Tomasz: merged in Sinan's patch to unmap IO resources properly, updated changelog] -Signed-off-by: Tomasz Nowicki <tn@semihalf.com> -Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> ---- - drivers/acpi/pci_root.c | 39 +++++++++++++++++++++++++++++++++++++++ - 1 file changed, 39 insertions(+) - -diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c -index ae3fe4e..9a26dd1 100644 ---- a/drivers/acpi/pci_root.c -+++ b/drivers/acpi/pci_root.c -@@ -720,6 +720,40 @@ next: - } - } - -+#ifdef PCI_IOBASE -+static void acpi_pci_root_remap_iospace(struct resource_entry *entry) -+{ -+ struct resource *res = entry->res; -+ resource_size_t cpu_addr = res->start; -+ resource_size_t pci_addr = cpu_addr - entry->offset; -+ resource_size_t length = resource_size(res); -+ unsigned long port; -+ -+ if (pci_register_io_range(cpu_addr, length)) -+ goto err; -+ -+ port = pci_address_to_pio(cpu_addr); -+ if (port == (unsigned long)-1) -+ goto err; -+ -+ res->start = port; -+ res->end = port + length - 1; -+ entry->offset = port - pci_addr; -+ -+ if (pci_remap_iospace(res, cpu_addr) < 0) -+ goto err; -+ -+ pr_info("Remapped I/O %pa to %pR\n", &cpu_addr, res); -+ return; -+err: -+ res->flags |= IORESOURCE_DISABLED; -+} -+#else -+static inline void acpi_pci_root_remap_iospace(struct resource_entry *entry) -+{ -+} -+#endif -+ - int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info) - { - int ret; -@@ -740,6 +774,9 @@ int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info) - "no IO and memory resources present in _CRS\n"); - else { - resource_list_for_each_entry_safe(entry, tmp, list) { -+ if (entry->res->flags & IORESOURCE_IO) -+ acpi_pci_root_remap_iospace(entry); -+ - if (entry->res->flags & IORESOURCE_DISABLED) - resource_list_destroy_entry(entry); - else -@@ -811,6 +848,8 @@ static void acpi_pci_root_release_info(struct pci_host_bridge *bridge) - - resource_list_for_each_entry(entry, &bridge->windows) { - res = entry->res; -+ if (res->flags & IORESOURCE_IO) -+ pci_unmap_iospace(res); - if (res->parent && - (res->flags & (IORESOURCE_MEM | IORESOURCE_IO))) - release_resource(res); --- -2.7.4 - -From dd4f7822d702cca83baa1de7a5f69344ffb82af9 Mon Sep 17 00:00:00 2001 -From: Tomasz Nowicki <tn@semihalf.com> -Date: Fri, 10 Jun 2016 21:55:13 +0200 -Subject: [PATCH 05/11] ACPI/PCI: Add generic MCFG table handling - -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 <tn@semihalf.com> -Signed-off-by: Jayachandran C <jchandra@broadcom.com> -Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> ---- - 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 <jchandra@broadcom.com> -+ * Copyright (C) 2016 Semihalf -+ * Author: Tomasz Nowicki <tn@semihalf.com> -+ * -+ * 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 <linux/kernel.h> -+#include <linux/pci.h> -+#include <linux/pci-acpi.h> -+ -+/* 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 --- -2.7.4 - -From fc1907f9c79f9a0a0c2f4d579896e678915fec48 Mon Sep 17 00:00:00 2001 -From: Tomasz Nowicki <tn@semihalf.com> -Date: Fri, 10 Jun 2016 21:55:14 +0200 -Subject: [PATCH 06/11] PCI: Refactor generic bus domain assignment - -Change the way PCI bus domain number is assigned and improve function -name to reflect what function does. No functional changes. - -Instead of assigning bus domain number inside of pci_bus_assign_domain_nr() -simply return domain number and let pci_create_root_bus() do assignment. -This way pci_create_root_bus() setups bus structure data in the consistent -way. Since pci_bus_assign_domain_nr() now does not assign but retrieves -domain number instead, rename it to pci_bus_find_domain_nr(). - -Signed-off-by: Tomasz Nowicki <tn@semihalf.com> -Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> ---- - drivers/pci/pci.c | 4 ++-- - drivers/pci/probe.c | 4 +++- - include/linux/pci.h | 7 +------ - 3 files changed, 6 insertions(+), 9 deletions(-) - -diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c -index eb431b5..b9a7833 100644 ---- a/drivers/pci/pci.c -+++ b/drivers/pci/pci.c -@@ -4941,7 +4941,7 @@ int pci_get_new_domain_nr(void) - } - - #ifdef CONFIG_PCI_DOMAINS_GENERIC --void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent) -+int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent) - { - static int use_dt_domains = -1; - int domain = -1; -@@ -4985,7 +4985,7 @@ void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent) - domain = -1; - } - -- bus->domain_nr = domain; -+ return domain; - } - #endif - #endif -diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c -index 8e3ef72..380d46d 100644 ---- a/drivers/pci/probe.c -+++ b/drivers/pci/probe.c -@@ -2127,7 +2127,9 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, - b->sysdata = sysdata; - b->ops = ops; - b->number = b->busn_res.start = bus; -- pci_bus_assign_domain_nr(b, parent); -+#ifdef CONFIG_PCI_DOMAINS_GENERIC -+ b->domain_nr = pci_bus_find_domain_nr(b, parent); -+#endif - b2 = pci_find_bus(pci_domain_nr(b), bus); - if (b2) { - /* If we already got to this bus through a different bridge, ignore it */ -diff --git a/include/linux/pci.h b/include/linux/pci.h -index ce03d65..48839e8 100644 ---- a/include/linux/pci.h -+++ b/include/linux/pci.h -@@ -1390,12 +1390,7 @@ static inline int pci_domain_nr(struct pci_bus *bus) - { - return bus->domain_nr; - } --void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent); --#else --static inline void pci_bus_assign_domain_nr(struct pci_bus *bus, -- struct device *parent) --{ --} -+int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent); - #endif - - /* some architectures require additional setup to direct VGA traffic */ --- -2.7.4 - -From d6d45ae1d58658111d5e838c41b9ed4729bbb81e Mon Sep 17 00:00:00 2001 -From: Tomasz Nowicki <tn@semihalf.com> -Date: Fri, 10 Jun 2016 21:55:15 +0200 -Subject: [PATCH 07/11] PCI: Factor DT specific pci_bus_find_domain_nr() code - out - -pci_bus_find_domain_nr() retrieves the host bridge domain number in a DT -specific way. Factor our pci_bus_find_domain_nr() in a separate DT -function (ie of_pci_bus_find_domain_nr()) so that DT code is self -contained, paving the way for retrieving domain number in -pci_bus_find_domain_nr() with additional firmware methods (ie ACPI). - -Signed-off-by: Tomasz Nowicki <tn@semihalf.com> -Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> ---- - drivers/pci/pci.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c -index b9a7833..97f7cd4 100644 ---- a/drivers/pci/pci.c -+++ b/drivers/pci/pci.c -@@ -4941,7 +4941,7 @@ int pci_get_new_domain_nr(void) - } - - #ifdef CONFIG_PCI_DOMAINS_GENERIC --int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent) -+static int of_pci_bus_find_domain_nr(struct device *parent) - { - static int use_dt_domains = -1; - int domain = -1; -@@ -4987,6 +4987,11 @@ int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent) - - return domain; - } -+ -+int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent) -+{ -+ return of_pci_bus_find_domain_nr(parent); -+} - #endif - #endif - --- -2.7.4 - -From 92d59511fd365d3c0c31d074b5e96cf48c58f68b Mon Sep 17 00:00:00 2001 -From: Peter Robinson <pbrobinson@gmail.com> -Date: Thu, 30 Jun 2016 16:56:24 +0100 -Subject: [PATCH 08/11] ARM64/PCI: Add ACPI hook to assign domain number - -PCI core code provides a config option (CONFIG_PCI_DOMAINS_GENERIC) -that allows assigning the PCI bus domain number generically by -relying on device tree bindings, and falling back to a simple counter -when the respective DT properties (ie "linux,pci-domain") are not -specified in the host bridge device tree node. - -In a similar way, when a system is booted through ACPI, architectures -that are selecting CONFIG_PCI_DOMAINS_GENERIC (ie ARM64) require kernel -hooks to retrieve the domain number so that the PCI bus domain number -set-up can be handled seamlessly with DT and ACPI in generic core code -when CONFIG_PCI_DOMAINS_GENERIC is selected. - -Since currently it is not possible to retrieve a pointer to the PCI -host bridge ACPI device backing the host bridge from core PCI code -(which would allow retrieving the domain number in an arch agnostic -way through the ACPI _SEG method), an arch specific ACPI hook has to -be declared and implemented by all arches that rely on -CONFIG_PCI_DOMAINS_GENERIC to retrieve the domain number and set it -up in core PCI code. - -For the aforementioned reasons, introduce acpi_pci_bus_find_domain_nr() -hook to retrieve the domain number on a per-arch basis when the system -boots through ACPI. ARM64 dummy implementation of the same is provided -in first place in preparation for ARM64 ACPI based PCI host controller -driver. - -acpi_pci_bus_find_domain_nr() is called from generic -pci_bus_find_domain_nr() as an ACPI option to DT domain assignment. - -Signed-off-by: Tomasz Nowicki <tn@semihalf.com> -Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> ---- - arch/arm64/kernel/pci.c | 7 +++++++ - drivers/pci/pci.c | 4 +++- - include/linux/pci.h | 7 +++++++ - 3 files changed, 17 insertions(+), 1 deletion(-) - -diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c -index 3c4e308..d5d3d26 100644 ---- a/arch/arm64/kernel/pci.c -+++ b/arch/arm64/kernel/pci.c -@@ -17,6 +17,7 @@ - #include <linux/mm.h> - #include <linux/of_pci.h> - #include <linux/of_platform.h> -+#include <linux/pci.h> - #include <linux/slab.h> - - /* -@@ -85,6 +86,12 @@ EXPORT_SYMBOL(pcibus_to_node); - #endif - - #ifdef CONFIG_ACPI -+ -+int acpi_pci_bus_find_domain_nr(struct pci_bus *bus) -+{ -+ return 0; -+} -+ - /* Root bridge scanning */ - struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) - { -diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c -index 97f7cd4..4834cee 100644 ---- a/drivers/pci/pci.c -+++ b/drivers/pci/pci.c -@@ -7,6 +7,7 @@ - * Copyright 1997 -- 2000 Martin Mares <mj@ucw.cz> - */ - -+#include <linux/acpi.h> - #include <linux/kernel.h> - #include <linux/delay.h> - #include <linux/init.h> -@@ -4990,7 +4991,8 @@ static int of_pci_bus_find_domain_nr(struct device *parent) - - int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent) - { -- return of_pci_bus_find_domain_nr(parent); -+ return acpi_disabled ? of_pci_bus_find_domain_nr(parent) : -+ acpi_pci_bus_find_domain_nr(bus); - } - #endif - #endif -diff --git a/include/linux/pci.h b/include/linux/pci.h -index 48839e8..49ba8af 100644 ---- a/include/linux/pci.h -+++ b/include/linux/pci.h -@@ -1390,6 +1390,13 @@ static inline int pci_domain_nr(struct pci_bus *bus) - { - return bus->domain_nr; - } -+/* Arch specific ACPI hook to set-up domain number */ -+#ifdef CONFIG_ACPI -+int acpi_pci_bus_find_domain_nr(struct pci_bus *bus); -+#else -+static inline int acpi_pci_bus_find_domain_nr(struct pci_bus *bus) -+{ return 0; } -+#endif - int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent); - #endif - --- -2.7.4 - -From bb06753d2e163d8100a017f06a6d9dd195d68a76 Mon Sep 17 00:00:00 2001 -From: Tomasz Nowicki <tn@semihalf.com> -Date: Fri, 10 Jun 2016 21:55:17 +0200 -Subject: [PATCH 09/11] ARM64/PCI: ACPI support for legacy IRQs parsing and - consolidation with DT code - -To enable PCI legacy IRQs on platforms booting with ACPI, arch code -should include ACPI specific callbacks that parse and set-up the -device IRQ number, equivalent to the DT boot path. Owing to the current -ACPI core scan handlers implementation, ACPI PCI legacy IRQs bindings -cannot be parsed at device add time, since that would trigger ACPI scan -handlers ordering issues depending on how the ACPI tables are defined. - -To solve this problem and consolidate FW PCI legacy IRQs parsing in -one single pcibios callback (pending final removal), this patch moves -DT PCI IRQ parsing to the pcibios_alloc_irq() callback (called by -PCI core code at device probe time) and adds ACPI PCI legacy IRQs -parsing to the same callback too, so that FW PCI legacy IRQs parsing -is confined in one single arch callback that can be easily removed -when code parsing PCI legacy IRQs is consolidated and moved to core -PCI code. - -Signed-off-by: Tomasz Nowicki <tn@semihalf.com> -Suggested-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> ---- - arch/arm64/kernel/pci.c | 11 ++++++++--- - 1 file changed, 8 insertions(+), 3 deletions(-) - -diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c -index d5d3d26..b3b8a2c 100644 ---- a/arch/arm64/kernel/pci.c -+++ b/arch/arm64/kernel/pci.c -@@ -51,11 +51,16 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) - } - - /* -- * Try to assign the IRQ number from DT when adding a new device -+ * Try to assign the IRQ number when probing a new device - */ --int pcibios_add_device(struct pci_dev *dev) -+int pcibios_alloc_irq(struct pci_dev *dev) - { -- dev->irq = of_irq_parse_and_map_pci(dev, 0, 0); -+ if (acpi_disabled) -+ dev->irq = of_irq_parse_and_map_pci(dev, 0, 0); -+#ifdef CONFIG_ACPI -+ else -+ return acpi_pci_irq_enable(dev); -+#endif - - return 0; - } --- -2.7.4 - -From b6e298840f532192a589f8ade128dec3fef3a4c6 Mon Sep 17 00:00:00 2001 -From: Tomasz Nowicki <tn@semihalf.com> -Date: Fri, 10 Jun 2016 21:55:18 +0200 -Subject: [PATCH 10/11] ARM64/PCI: Implement ACPI low-level calls to access - PCI_Config region from AML - -ACPI spec6.1 - chapter: 5.5.2.4 defines OperationRegion (Declare Operation -Region). Following the spec: " [...] An Operation Region is a specific -region of operation within an address space that is declared as a subset -of the entire address space using a starting address (offset) and a length. -Control methods must have exclusive access to any address accessed via -fields declared in Operation Regions. [...]". - -OperationRegion allows to declare various of operation region address space -identifiers including PCI_Config. PCI_Config is meant to access PCI -configuration space from the ASL. So every time ASL opcode operates -on PCI_Config space region, ASL interpreter dispatches accesses to OS -low-level calls - raw_pci_write() and raw_pci_read() for Linux - so-called -ACPI RAW accessors. - -In order to support PCI_Config operation region, implement mentioned -raw_pci_write() and raw_pci_read() calls so they find associated bus -and call read/write ops. - -Waiting for clarification in the ACPI specifications in relation -to PCI_Config space handling before PCI bus enumeration is completed, -current code does not support PCI_Config region accesses before PCI bus -enumeration whilst providing full AML PCI_Config access availability -when the PCI bus enumeration is completed by the kernel so that -RAW accessors can look-up PCI operations through the struct pci_bus -associated with a PCI bus. - -Signed-off-by: Tomasz Nowicki <tn@semihalf.com> -Signed-off-by: Jayachandran C <jchandra@broadcom.com> -Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> ---- - arch/arm64/kernel/pci.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c -index b3b8a2c..328f857 100644 ---- a/arch/arm64/kernel/pci.c -+++ b/arch/arm64/kernel/pci.c -@@ -71,13 +71,21 @@ int pcibios_alloc_irq(struct pci_dev *dev) - int raw_pci_read(unsigned int domain, unsigned int bus, - unsigned int devfn, int reg, int len, u32 *val) - { -- return -ENXIO; -+ struct pci_bus *b = pci_find_bus(domain, bus); -+ -+ if (!b) -+ return PCIBIOS_DEVICE_NOT_FOUND; -+ return b->ops->read(b, devfn, reg, len, val); - } - - int raw_pci_write(unsigned int domain, unsigned int bus, - unsigned int devfn, int reg, int len, u32 val) - { -- return -ENXIO; -+ struct pci_bus *b = pci_find_bus(domain, bus); -+ -+ if (!b) -+ return PCIBIOS_DEVICE_NOT_FOUND; -+ return b->ops->write(b, devfn, reg, len, val); - } - - #ifdef CONFIG_NUMA --- -2.7.4 - -From 3b8cff3fa89ba3ef6f1cf09a0667aa470b7fad0b Mon Sep 17 00:00:00 2001 -From: Tomasz Nowicki <tn@semihalf.com> -Date: Fri, 10 Jun 2016 21:55:19 +0200 -Subject: [PATCH 11/11] ARM64/PCI: Support for ACPI based PCI host controller - -Implement pci_acpi_scan_root and other arch-specific call so that ARM64 -can start using ACPI to setup and enumerate PCI buses. - -Prior to buses enumeration the pci_acpi_scan_root() implementation looks -for configuration space start address (obtained through ACPI _CBA method or -MCFG interface). If succeed, it uses ECAM library to create new mapping. -Then it attaches generic ECAM ops (pci_generic_ecam_ops) which are used -for accessing configuration space later on. - -On ARM64, we need to use generic domains (CONFIG_PCI_DOMAINS_GENERIC). -In order to achieve that for ACPI case implement -acpi_pci_bus_find_domain_nr() body so that it retrieves pci_config_window -structure from bus sysdata and eventually gets domain number from -acpi_pci_root structure. - -ACPI requires to run acpi_pci_{add|remove}_bus while new PCI bus is created. -This allows to do some ACPI-specific additional configuration, like -PCI hotplug slot enumeration. In order to fulfill these requirements, -we implement arch-specific pcibios_{add|remove}_bus calls -and call acpi_pci_{add|remove}_bus from there. - -Signed-off-by: Tomasz Nowicki <tn@semihalf.com> -Signed-off-by: Jayachandran C <jchandra@broadcom.com> -Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> ---- - arch/arm64/Kconfig | 2 + - arch/arm64/kernel/pci.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++-- - 2 files changed, 115 insertions(+), 3 deletions(-) - -diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig -index 5a0a691..4806cde 100644 ---- a/arch/arm64/Kconfig -+++ b/arch/arm64/Kconfig -@@ -3,6 +3,7 @@ config ARM64 - select ACPI_CCA_REQUIRED if ACPI - select ACPI_GENERIC_GSI if ACPI - select ACPI_REDUCED_HARDWARE_ONLY if ACPI -+ select ACPI_MCFG if ACPI - select ARCH_HAS_DEVMEM_IS_ALLOWED - select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE - select ARCH_HAS_ELF_RANDOMIZE -@@ -96,6 +97,7 @@ config ARM64 - select OF_EARLY_FLATTREE - select OF_NUMA if NUMA && OF - select OF_RESERVED_MEM -+ select PCI_ECAM if ACPI - select PERF_USE_VMALLOC - select POWER_RESET - select POWER_SUPPLY -diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c -index 328f857..94cd43c 100644 ---- a/arch/arm64/kernel/pci.c -+++ b/arch/arm64/kernel/pci.c -@@ -18,6 +18,8 @@ - #include <linux/of_pci.h> - #include <linux/of_platform.h> - #include <linux/pci.h> -+#include <linux/pci-acpi.h> -+#include <linux/pci-ecam.h> - #include <linux/slab.h> - - /* -@@ -100,15 +102,123 @@ EXPORT_SYMBOL(pcibus_to_node); - - #ifdef CONFIG_ACPI - -+struct acpi_pci_generic_root_info { -+ struct acpi_pci_root_info common; -+ struct pci_config_window *cfg; /* config space mapping */ -+}; -+ - int acpi_pci_bus_find_domain_nr(struct pci_bus *bus) - { -+ struct pci_config_window *cfg = bus->sysdata; -+ struct acpi_device *adev = to_acpi_device(cfg->parent); -+ struct acpi_pci_root *root = acpi_driver_data(adev); -+ -+ return root->segment; -+} -+ -+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) -+{ -+ if (!acpi_disabled) { -+ struct pci_config_window *cfg = bridge->bus->sysdata; -+ struct acpi_device *adev = to_acpi_device(cfg->parent); -+ ACPI_COMPANION_SET(&bridge->dev, adev); -+ } -+ - return 0; - } - --/* Root bridge scanning */ -+/* -+ * Lookup the bus range for the domain in MCFG, and set up config space -+ * mapping. -+ */ -+static struct pci_config_window * -+pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root) -+{ -+ struct resource *bus_res = &root->secondary; -+ u16 seg = root->segment; -+ struct pci_config_window *cfg; -+ struct resource cfgres; -+ unsigned int bsz; -+ -+ /* Use address from _CBA if present, otherwise lookup MCFG */ -+ if (!root->mcfg_addr) -+ root->mcfg_addr = pci_mcfg_lookup(seg, bus_res); -+ -+ if (!root->mcfg_addr) { -+ dev_err(&root->device->dev, "%04x:%pR ECAM region not found\n", -+ seg, bus_res); -+ return NULL; -+ } -+ -+ bsz = 1 << pci_generic_ecam_ops.bus_shift; -+ cfgres.start = root->mcfg_addr + bus_res->start * bsz; -+ cfgres.end = cfgres.start + resource_size(bus_res) * bsz - 1; -+ cfgres.flags = IORESOURCE_MEM; -+ cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res, -+ &pci_generic_ecam_ops); -+ if (IS_ERR(cfg)) { -+ dev_err(&root->device->dev, "%04x:%pR error %ld mapping ECAM\n", -+ seg, bus_res, PTR_ERR(cfg)); -+ return NULL; -+ } -+ -+ return cfg; -+} -+ -+/* release_info: free resources allocated by init_info */ -+static void pci_acpi_generic_release_info(struct acpi_pci_root_info *ci) -+{ -+ struct acpi_pci_generic_root_info *ri; -+ -+ ri = container_of(ci, struct acpi_pci_generic_root_info, common); -+ pci_ecam_free(ri->cfg); -+ kfree(ri); -+} -+ -+static struct acpi_pci_root_ops acpi_pci_root_ops = { -+ .release_info = pci_acpi_generic_release_info, -+}; -+ -+/* Interface called from ACPI code to setup PCI host controller */ - struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) - { -- /* TODO: Should be revisited when implementing PCI on ACPI */ -- return NULL; -+ int node = acpi_get_node(root->device->handle); -+ struct acpi_pci_generic_root_info *ri; -+ struct pci_bus *bus, *child; -+ -+ ri = kzalloc_node(sizeof(*ri), GFP_KERNEL, node); -+ if (!ri) -+ return NULL; -+ -+ ri->cfg = pci_acpi_setup_ecam_mapping(root); -+ if (!ri->cfg) { -+ kfree(ri); -+ return NULL; -+ } -+ -+ acpi_pci_root_ops.pci_ops = &ri->cfg->ops->pci_ops; -+ bus = acpi_pci_root_create(root, &acpi_pci_root_ops, &ri->common, -+ ri->cfg); -+ if (!bus) -+ return NULL; -+ -+ pci_bus_size_bridges(bus); -+ pci_bus_assign_resources(bus); -+ -+ list_for_each_entry(child, &bus->children, node) -+ pcie_bus_configure_settings(child); -+ -+ return bus; -+} -+ -+void pcibios_add_bus(struct pci_bus *bus) -+{ -+ acpi_pci_add_bus(bus); - } -+ -+void pcibios_remove_bus(struct pci_bus *bus) -+{ -+ acpi_pci_remove_bus(bus); -+} -+ - #endif --- -2.7.4 - |