Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/476456/?format=api
{ "id": 476456, "url": "http://patchwork.ozlabs.org/api/patches/476456/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-pci/patch/1432644564-24746-12-git-send-email-hanjun.guo@linaro.org/", "project": { "id": 28, "url": "http://patchwork.ozlabs.org/api/projects/28/?format=api", "name": "Linux PCI development", "link_name": "linux-pci", "list_id": "linux-pci.vger.kernel.org", "list_email": "linux-pci@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<1432644564-24746-12-git-send-email-hanjun.guo@linaro.org>", "list_archive_url": null, "date": "2015-05-26T12:49:24", "name": "[11/11] ARM64 / PCI / ACPI: support for ACPI based PCI hostbridge init", "commit_ref": null, "pull_url": null, "state": "changes-requested", "archived": false, "hash": "1f48c58d6f90e0a0aa3e09c9be8e1a24bb60a04c", "submitter": { "id": 47236, "url": "http://patchwork.ozlabs.org/api/people/47236/?format=api", "name": "Hanjun Guo", "email": "hanjun.guo@linaro.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-pci/patch/1432644564-24746-12-git-send-email-hanjun.guo@linaro.org/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/476456/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/476456/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<linux-pci-owner@vger.kernel.org>", "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])\n\tby ozlabs.org (Postfix) with ESMTP id 0070F140129\n\tfor <incoming@patchwork.ozlabs.org>;\n\tTue, 26 May 2015 23:19:40 +1000 (AEST)", "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1753169AbbEZMxT (ORCPT <rfc822;incoming@patchwork.ozlabs.org>);\n\tTue, 26 May 2015 08:53:19 -0400", "from mail-pd0-f179.google.com ([209.85.192.179]:35268 \"EHLO\n\tmail-pd0-f179.google.com\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S1753174AbbEZMxQ (ORCPT\n\t<rfc822; linux-pci@vger.kernel.org>); Tue, 26 May 2015 08:53:16 -0400", "by pdea3 with SMTP id a3so90233398pde.2\n\tfor <linux-pci@vger.kernel.org>; Tue, 26 May 2015 05:50:58 -0700 (PDT)", "from localhost ([180.150.153.56]) by mx.google.com with ESMTPSA id\n\tfs16sm13066386pdb.12.2015.05.26.05.50.56\n\t(version=TLSv1.2 cipher=RC4-SHA bits=128/128);\n\tTue, 26 May 2015 05:50:57 -0700 (PDT)" ], "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20130820;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=3V1TKek/dUeWsr4DTz1d5GSAHcvnFpY/GIyFR7rk+mA=;\n\tb=ehQWWNTpNWbh4Bz7NKLVOHdPqo2NTi8q3AMQiShmZnSHNQyboiIMjGRUGsd7CAimiG\n\tFGOHlduMkfp02/OF22KsagOhUhxJtLeBFfOhAOHdbuuOCnOmQAooiqubO5zVCyeospEh\n\tzthw6tGYnlucD1R2O/pSgWGwV7Xe9qIJPHcpwBRVBIVCq5SgR1ZwPQ8t41q8Q7EZkwjn\n\tnWDrC28jixewSpFd+HoOxP36zwsfasZkV+9zlaCMY9QVVYlkFtFo38eMm3OjJoMeCOxr\n\tMntTIrDxGc0lrkD+TPTrt6zpYsRDFb3q8JHU8C5z7HITXEGHdmfBvYBumgTvVzJXIQTj\n\tvvhQ==", "X-Gm-Message-State": "ALoCoQn+Wq6fH7mLE8PylZ5TRuMbTZhON3Px2OxpMor6gffYBQ5Gkc73h+gniXJPboB7g0ZGkY6m", "X-Received": "by 10.66.123.81 with SMTP id ly17mr49437748pab.31.1432644657999; \n\tTue, 26 May 2015 05:50:57 -0700 (PDT)", "From": "Hanjun Guo <hanjun.guo@linaro.org>", "To": "Bjorn Helgaas <bhelgaas@google.com>, Arnd Bergmann <arnd@arndb.de>,\n\tCatalin Marinas <catalin.marinas@arm.com>,\n\tWill Deacon <will.deacon@arm.com>,\n\t\"Rafael J. Wysocki\" <rjw@rjwysocki.net>", "Cc": "Jiang Liu <jiang.liu@linux.intel.com>, Liviu Dudau <Liviu.Dudau@arm.com>,\n\tThomas Gleixner <tglx@linutronix.de>,\n\tYijing Wang <wangyijing@huawei.com>,\n\tLorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>,\n\tTomasz Nowicki <tomasz.nowicki@linaro.org>,\n\tSuravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>,\n\tMark Salter <msalter@redhat.com>, linux-pci@vger.kernel.org,\n\tlinux-arm-kernel@lists.infradead.org, linux-acpi@vger.kernel.org,\n\tlinux-kernel@vger.kernel.org, linaro-acpi@lists.linaro.org,\n\tHanjun Guo <hanjun.guo@linaro.org>", "Subject": "[PATCH 11/11] ARM64 / PCI / ACPI: support for ACPI based PCI\n\thostbridge init", "Date": "Tue, 26 May 2015 20:49:24 +0800", "Message-Id": "<1432644564-24746-12-git-send-email-hanjun.guo@linaro.org>", "X-Mailer": "git-send-email 1.9.1", "In-Reply-To": "<1432644564-24746-1-git-send-email-hanjun.guo@linaro.org>", "References": "<1432644564-24746-1-git-send-email-hanjun.guo@linaro.org>", "Sender": "linux-pci-owner@vger.kernel.org", "Precedence": "bulk", "List-ID": "<linux-pci.vger.kernel.org>", "X-Mailing-List": "linux-pci@vger.kernel.org" }, "content": "Based on Jiang Liu's common interface to support PCI host bridge\ninit and refactoring of MMCONFIG, this patch using information\nfrom ACPI MCFG table and IO/irq resources from _CRS to init\nARM64 PCI hostbridge, then PCI will work on ARM64.\n\nThis patch is based on Mark Salter and Tomasz Nowicki's work.\n\nSigned-off-by: Hanjun Guo <hanjun.guo@linaro.org>\nTested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>\nCC: Arnd Bergmann <arnd@arndb.de>\nCC: Catalin Marinas <catalin.marinas@arm.com>\nCC: Liviu Dudau <Liviu.Dudau@arm.com>\nCC: Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>\nCC: Will Deacon <will.deacon@arm.com>\n---\n arch/arm64/Kconfig | 7 ++\n arch/arm64/kernel/pci.c | 245 +++++++++++++++++++++++++++++++++++++++++++++---\n drivers/pci/pci.c | 26 +++--\n 3 files changed, 257 insertions(+), 21 deletions(-)", "diff": "diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig\nindex 9b80428..8e4b789 100644\n--- a/arch/arm64/Kconfig\n+++ b/arch/arm64/Kconfig\n@@ -276,6 +276,13 @@ config PCI_DOMAINS_GENERIC\n config PCI_SYSCALL\n \tdef_bool PCI\n \n+config PCI_MMCONFIG\n+\tdef_bool y\n+\tselect PCI_ECAM\n+\tselect HAVE_PCI_ECAM\n+\tselect GENERIC_PCI_ECAM\n+\tdepends on ACPI\n+\n source \"drivers/pci/Kconfig\"\n source \"drivers/pci/pcie/Kconfig\"\n source \"drivers/pci/hotplug/Kconfig\"\ndiff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c\nindex 4095379..d1629dc 100644\n--- a/arch/arm64/kernel/pci.c\n+++ b/arch/arm64/kernel/pci.c\n@@ -11,12 +11,15 @@\n */\n \n #include <linux/acpi.h>\n+#include <linux/ecam.h>\n #include <linux/init.h>\n #include <linux/io.h>\n #include <linux/kernel.h>\n #include <linux/mm.h>\n+#include <linux/of_address.h>\n #include <linux/of_pci.h>\n #include <linux/of_platform.h>\n+#include <linux/pci-acpi.h>\n #include <linux/slab.h>\n \n #include <asm/pci-bridge.h>\n@@ -43,31 +46,251 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,\n */\n int pcibios_add_device(struct pci_dev *dev)\n {\n-\tdev->irq = of_irq_parse_and_map_pci(dev, 0, 0);\n+\tif (acpi_disabled)\n+\t\tdev->irq = of_irq_parse_and_map_pci(dev, 0, 0);\n \n \treturn 0;\n }\n \n+#ifdef CONFIG_ACPI\n+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)\n+{\n+\tstruct pci_controller *sd = bridge->bus->sysdata;\n+\n+\tACPI_COMPANION_SET(&bridge->dev, sd->companion);\n+\treturn 0;\n+}\n+\n+void pcibios_add_bus(struct pci_bus *bus)\n+{\n+\tacpi_pci_add_bus(bus);\n+}\n+\n+void pcibios_remove_bus(struct pci_bus *bus)\n+{\n+\tacpi_pci_remove_bus(bus);\n+}\n+\n+int pcibios_enable_irq(struct pci_dev *dev)\n+{\n+\tif (!pci_dev_msi_enabled(dev))\n+\t\tacpi_pci_irq_enable(dev);\n+\treturn 0;\n+}\n+\n+int pcibios_disable_irq(struct pci_dev *dev)\n+{\n+\tif (!pci_dev_msi_enabled(dev))\n+\t\tacpi_pci_irq_disable(dev);\n+\treturn 0;\n+}\n+\n+int pcibios_enable_device(struct pci_dev *dev, int bars)\n+{\n+\tint err;\n+\n+\terr = pci_enable_resources(dev, bars);\n+\tif (err < 0)\n+\t\treturn err;\n+\n+\treturn pcibios_enable_irq(dev);\n+}\n+\n+static int __init pcibios_assign_resources(void)\n+{\n+\tstruct pci_bus *root_bus;\n+\n+\tif (acpi_disabled)\n+\t\treturn 0;\n+\n+\tlist_for_each_entry(root_bus, &pci_root_buses, node) {\n+\t\tpcibios_resource_survey_bus(root_bus);\n+\t\tpci_assign_unassigned_root_bus_resources(root_bus);\n+\t}\n+\treturn 0;\n+}\n /*\n- * raw_pci_read/write - Platform-specific PCI config space access.\n+ * fs_initcall comes after subsys_initcall, so we know acpi scan\n+ * has run.\n */\n-int raw_pci_read(unsigned int domain, unsigned int bus,\n-\t\t unsigned int devfn, int reg, int len, u32 *val)\n+fs_initcall(pcibios_assign_resources);\n+\n+static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,\n+\t\t int size, u32 *value)\n {\n-\treturn -ENXIO;\n+\treturn raw_pci_read(pci_domain_nr(bus), bus->number,\n+\t\t\t devfn, where, size, value);\n }\n \n-int raw_pci_write(unsigned int domain, unsigned int bus,\n-\t\tunsigned int devfn, int reg, int len, u32 val)\n+static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,\n+\t\t int size, u32 value)\n {\n-\treturn -ENXIO;\n+\treturn raw_pci_write(pci_domain_nr(bus), bus->number,\n+\t\t\t devfn, where, size, value);\n }\n \n-#ifdef CONFIG_ACPI\n+struct pci_ops pci_root_ops = {\n+\t.read = pci_read,\n+\t.write = pci_write,\n+};\n+\n+struct pci_root_info {\n+\tstruct acpi_pci_root_info common;\n+#ifdef CONFIG_PCI_MMCONFIG\n+\tbool mcfg_added;\n+\tu8 start_bus;\n+\tu8 end_bus;\n+#endif\n+};\n+\n+#ifdef CONFIG_PCI_MMCONFIG\n+static int pci_add_mmconfig_region(struct acpi_pci_root_info *ci)\n+{\n+\tstruct pci_mmcfg_region *cfg;\n+\tstruct pci_root_info *info;\n+\tstruct acpi_pci_root *root = ci->root;\n+\tint err, seg = ci->controller.segment;\n+\n+\tinfo = container_of(ci, struct pci_root_info, common);\n+\tinfo->start_bus = (u8)root->secondary.start;\n+\tinfo->end_bus = (u8)root->secondary.end;\n+\tinfo->mcfg_added = false;\n+\n+\trcu_read_lock();\n+\tcfg = pci_mmconfig_lookup(seg, info->start_bus);\n+\trcu_read_unlock();\n+\tif (cfg)\n+\t\treturn 0;\n+\n+\tcfg = pci_mmconfig_alloc(seg, info->start_bus, info->end_bus,\n+\t\t\t\t root->mcfg_addr);\n+\tif (!cfg)\n+\t\treturn -ENOMEM;\n+\n+\terr = pci_mmconfig_inject(cfg);\n+\tif (!err)\n+\t\tinfo->mcfg_added = true;\n+\n+\treturn err;\n+}\n+\n+static void pci_remove_mmconfig_region(struct acpi_pci_root_info *ci)\n+{\n+\tstruct pci_root_info *info;\n+\n+\tinfo = container_of(ci, struct pci_root_info, common);\n+\tif (info->mcfg_added) {\n+\t\tpci_mmconfig_delete(ci->controller.segment, info->start_bus,\n+\t\t\t\t info->end_bus);\n+\t\tinfo->mcfg_added = false;\n+\t}\n+}\n+#else\n+static int pci_add_mmconfig_region(struct acpi_pci_root_info *ci)\n+{\n+\treturn 0;\n+}\n+\n+static void pci_remove_mmconfig_region(struct acpi_pci_root_info *ci) { }\n+#endif\n+\n+static int pci_acpi_root_init_info(struct acpi_pci_root_info *ci)\n+{\n+\treturn pci_add_mmconfig_region(ci);\n+}\n+\n+static void pci_acpi_root_release_info(struct acpi_pci_root_info *ci)\n+{\n+\tstruct pci_root_info *info;\n+\n+\tinfo = container_of(ci, struct pci_root_info, common);\n+\tpci_remove_mmconfig_region(ci);\n+\tkfree(info);\n+}\n+\n+static int pci_acpi_root_prepare_resources(struct acpi_pci_root_info *ci,\n+\t\t\t\t\t int status)\n+{\n+\tstruct resource_entry *entry, *tmp;\n+\n+\tresource_list_for_each_entry_safe(entry, tmp, &ci->resources) {\n+\t\tstruct resource *res = entry->res;\n+\n+\t\t/*\n+\t\t * Special handling for ARM IO range\n+\t\t * TODO: need to move pci_register_io_range() function out\n+\t\t * of drivers/of/address.c for both used by DT and ACPI\n+\t\t */\n+\t\tif (res->flags & IORESOURCE_IO) {\n+\t\t\tunsigned long port;\n+\t\t\tint err;\n+\t\t\tresource_size_t length = res->end - res->start;\n+\n+\t\t\terr = pci_register_io_range(res->start, length);\n+\t\t\tif (err) {\n+\t\t\t\tresource_list_destroy_entry(entry);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\tport = pci_address_to_pio(res->start);\n+\t\t\tif (port == (unsigned long)-1) {\n+\t\t\t\tresource_list_destroy_entry(entry);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\tres->start = port;\n+\t\t\tres->end = res->start + length - 1;\n+\n+\t\t\tif (pci_remap_iospace(res, res->start) < 0)\n+\t\t\t\tresource_list_destroy_entry(entry);\n+\t\t}\n+\t}\n+\n+\treturn status;\n+}\n+\n+static struct acpi_pci_root_ops acpi_pci_root_ops = {\n+\t.pci_ops = &pci_root_ops,\n+\t.init_info = pci_acpi_root_init_info,\n+\t.release_info = pci_acpi_root_release_info,\n+\t.prepare_resources = pci_acpi_root_prepare_resources,\n+};\n+\n /* Root bridge scanning */\n struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)\n {\n-\t/* TODO: Should be revisited when implementing PCI on ACPI */\n-\treturn NULL;\n+\tstruct pci_root_info *info;\n+\tint node;\n+\tint domain = root->segment;\n+\tint busnum = root->secondary.start;\n+\tstruct pci_bus *bus;\n+\n+\tif (domain && !pci_domains_supported) {\n+\t\tpr_warn(\"PCI %04x:%02x: multiple domains not supported.\\n\",\n+\t\t\tdomain, busnum);\n+\t\treturn NULL;\n+\t}\n+\n+\tnode = acpi_get_node(root->device->handle);\n+\tinfo = kzalloc_node(sizeof(*info), GFP_KERNEL, node);\n+\tif (!info) {\n+\t\tdev_err(&root->device->dev, \"pci_bus %04x:%02x: ignored (out of memory)\\n\",\n+\t\t\tdomain, busnum);\n+\t\treturn NULL;\n+\t}\n+\n+\tbus = acpi_pci_root_create(root, &acpi_pci_root_ops, &info->common);\n+\n+\t/* After the PCI-E bus has been walked and all devices discovered,\n+\t * configure any settings of the fabric that might be necessary.\n+\t */\n+\tif (bus) {\n+\t\tstruct pci_bus *child;\n+\n+\t\tlist_for_each_entry(child, &bus->children, node)\n+\t\t\tpcie_bus_configure_settings(child);\n+\t}\n+\n+\treturn bus;\n }\n #endif\ndiff --git a/drivers/pci/pci.c b/drivers/pci/pci.c\nindex acc4b6e..0268a1d 100644\n--- a/drivers/pci/pci.c\n+++ b/drivers/pci/pci.c\n@@ -25,6 +25,7 @@\n #include <linux/device.h>\n #include <linux/pm_runtime.h>\n #include <linux/pci_hotplug.h>\n+#include <linux/acpi.h>\n #include <asm-generic/pci-bridge.h>\n #include <asm/setup.h>\n #include \"pci.h\"\n@@ -4509,7 +4510,7 @@ int pci_get_new_domain_nr(void)\n void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)\n {\n \tstatic int use_dt_domains = -1;\n-\tint domain = of_get_pci_domain_nr(parent->of_node);\n+\tint domain;\n \n \t/*\n \t * Check DT domain and use_dt_domains values.\n@@ -4537,17 +4538,22 @@ void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)\n \t * invalidating the domain value (domain = -1) and printing a\n \t * corresponding error.\n \t */\n-\tif (domain >= 0 && use_dt_domains) {\n-\t\tuse_dt_domains = 1;\n-\t} else if (domain < 0 && use_dt_domains != 1) {\n-\t\tuse_dt_domains = 0;\n-\t\tdomain = pci_get_new_domain_nr();\n+\tif (acpi_disabled) {\n+\t\tdomain = of_get_pci_domain_nr(parent->of_node);\n+\t\tif (domain >= 0 && use_dt_domains) {\n+\t\t\tuse_dt_domains = 1;\n+\t\t} else if (domain < 0 && use_dt_domains != 1) {\n+\t\t\tuse_dt_domains = 0;\n+\t\t\tdomain = pci_get_new_domain_nr();\n+\t\t} else {\n+\t\t\tdev_err(parent, \"Node %s has inconsistent \\\"linux,pci-domain\\\" property in DT\\n\",\n+\t\t\t\tparent->of_node->full_name);\n+\t\t\tdomain = -1;\n+\t\t}\n \t} else {\n-\t\tdev_err(parent, \"Node %s has inconsistent \\\"linux,pci-domain\\\" property in DT\\n\",\n-\t\t\tparent->of_node->full_name);\n-\t\tdomain = -1;\n+\t\tstruct pci_controller *sd = bus->sysdata;\n+\t\tdomain = sd->segment;\n \t}\n-\n \tbus->domain_nr = domain;\n }\n #endif\n", "prefixes": [ "11/11" ] }