From: Bjorn Helgaas <bhelgaas@google.com>
To: Tomasz Nowicki <tomasz.nowicki@linaro.org>
Cc: catalin.marinas@arm.com, will.deacon@arm.com,
lorenzo.pieralisi@arm.com, wangyijing@huawei.com, arnd@arndb.de,
hanjun.guo@linaro.org, Liviu.Dudau@arm.com, tglx@linutronix.de,
mingo@redhat.com, hpa@zytor.com, rjw@rjwysocki.net,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, x86@kernel.org,
linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org,
linaro-acpi@lists.linaro.org
Subject: Re: [PATCH 2/6] x86, acpi, pci: Move arch-agnostic MMCFG code out of arch/x86/ directory
Date: Wed, 10 Dec 2014 16:55:00 -0700 [thread overview]
Message-ID: <20141210235500.GA22886@google.com> (raw)
In-Reply-To: <1416413091-13452-3-git-send-email-tomasz.nowicki@linaro.org>
On Wed, Nov 19, 2014 at 05:04:47PM +0100, Tomasz Nowicki wrote:
> MMCFG table seems to be architecture independent and it makes sense
> to share common code across all architectures. The ones that may need
> architectural specific actions have default prototype (__weak).
>
> Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
> Tested-by: Hanjun Guo <hanjun.guo@linaro.org>
> ---
> arch/x86/include/asm/pci_x86.h | 29 -----
> arch/x86/pci/acpi.c | 1 +
> arch/x86/pci/init.c | 1 +
> arch/x86/pci/mmconfig-shared.c | 200 +---------------------------------
> arch/x86/pci/mmconfig_32.c | 1 +
> arch/x86/pci/mmconfig_64.c | 1 +
> drivers/acpi/Makefile | 1 +
> drivers/acpi/bus.c | 1 +
> drivers/acpi/mmconfig.c | 242 +++++++++++++++++++++++++++++++++++++++++
> include/linux/mmconfig.h | 58 ++++++++++
> include/linux/pci.h | 8 --
> 11 files changed, 308 insertions(+), 235 deletions(-)
> create mode 100644 drivers/acpi/mmconfig.c
> create mode 100644 include/linux/mmconfig.h
> ...
Much of the code you're moving to drivers/acpi/mmconfig.c is not actually
ACPI-specific and would have to be duplicated for a non-ACPI architecture
that supports ECAM. Could that code be moved somewhere like
drivers/pci/ecam.c, where it could be shared?
Bjorn
> diff --git a/drivers/acpi/mmconfig.c b/drivers/acpi/mmconfig.c
> new file mode 100644
> index 0000000..d62dccda
> --- /dev/null
> +++ b/drivers/acpi/mmconfig.c
> @@ -0,0 +1,242 @@
> +/*
> + * Arch agnostic low-level direct PCI config space access via MMCONFIG
> + *
> + * Per-architecture code takes care of the mappings, region validation and
> + * accesses themselves.
> + *
> + * 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.
> + *
> + */
> +
> +#include <linux/mutex.h>
> +#include <linux/rculist.h>
> +#include <linux/mmconfig.h>
> +
> +#define PREFIX "PCI: "
> +
> +static DEFINE_MUTEX(pci_mmcfg_lock);
> +
> +LIST_HEAD(pci_mmcfg_list);
> +
> +static void __init pci_mmconfig_remove(struct pci_mmcfg_region *cfg)
> +{
> + if (cfg->res.parent)
> + release_resource(&cfg->res);
> + list_del(&cfg->list);
> + kfree(cfg);
> +}
> +
> +void __init free_all_mmcfg(void)
> +{
> + struct pci_mmcfg_region *cfg, *tmp;
> +
> + pci_mmcfg_arch_free();
> + list_for_each_entry_safe(cfg, tmp, &pci_mmcfg_list, list)
> + pci_mmconfig_remove(cfg);
> +}
> +
> +void list_add_sorted(struct pci_mmcfg_region *new)
> +{
> + struct pci_mmcfg_region *cfg;
> +
> + /* keep list sorted by segment and starting bus number */
> + list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list) {
> + if (cfg->segment > new->segment ||
> + (cfg->segment == new->segment &&
> + cfg->start_bus >= new->start_bus)) {
> + list_add_tail_rcu(&new->list, &cfg->list);
> + return;
> + }
> + }
> + list_add_tail_rcu(&new->list, &pci_mmcfg_list);
> +}
> +
> +struct pci_mmcfg_region *pci_mmconfig_alloc(int segment, int start,
> + int end, u64 addr)
> +{
> + struct pci_mmcfg_region *new;
> + struct resource *res;
> +
> + if (addr == 0)
> + return NULL;
> +
> + new = kzalloc(sizeof(*new), GFP_KERNEL);
> + if (!new)
> + return NULL;
> +
> + new->address = addr;
> + new->segment = segment;
> + new->start_bus = start;
> + new->end_bus = end;
> +
> + res = &new->res;
> + res->start = addr + PCI_MMCFG_BUS_OFFSET(start);
> + res->end = addr + PCI_MMCFG_BUS_OFFSET(end + 1) - 1;
> + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
> + snprintf(new->name, PCI_MMCFG_RESOURCE_NAME_LEN,
> + "PCI MMCONFIG %04x [bus %02x-%02x]", segment, start, end);
> + res->name = new->name;
> +
> + return new;
> +}
> +
> +struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
> + int end, u64 addr)
> +{
> + struct pci_mmcfg_region *new;
> +
> + new = pci_mmconfig_alloc(segment, start, end, addr);
> + if (new) {
> + mutex_lock(&pci_mmcfg_lock);
> + list_add_sorted(new);
> + mutex_unlock(&pci_mmcfg_lock);
> +
> + pr_info(PREFIX
> + "MMCONFIG for domain %04x [bus %02x-%02x] at %pR "
> + "(base %#lx)\n",
> + segment, start, end, &new->res, (unsigned long)addr);
> + }
> +
> + return new;
> +}
> +
> +int __init pci_mmconfig_inject(struct pci_mmcfg_region *cfg)
> +{
> + struct pci_mmcfg_region *cfg_conflict;
> + int err = 0;
> +
> + mutex_lock(&pci_mmcfg_lock);
> + cfg_conflict = pci_mmconfig_lookup(cfg->segment, cfg->start_bus);
> + if (cfg_conflict) {
> + if (cfg_conflict->end_bus < cfg->end_bus)
> + pr_info(FW_INFO "MMCONFIG for "
> + "domain %04x [bus %02x-%02x] "
> + "only partially covers this bridge\n",
> + cfg_conflict->segment, cfg_conflict->start_bus,
> + cfg_conflict->end_bus);
> + err = -EEXIST;
> + goto out;
> + }
> +
> + if (pci_mmcfg_arch_map(cfg)) {
> + pr_warn("fail to map MMCONFIG %pR.\n", &cfg->res);
> + err = -ENOMEM;
> + goto out;
> + } else {
> + list_add_sorted(cfg);
> + pr_info("MMCONFIG at %pR (base %#lx)\n",
> + &cfg->res, (unsigned long)cfg->address);
> +
> + }
> +out:
> + mutex_unlock(&pci_mmcfg_lock);
> + return err;
> +}
> +
> +struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus)
> +{
> + struct pci_mmcfg_region *cfg;
> +
> + list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list)
> + if (cfg->segment == segment &&
> + cfg->start_bus <= bus && bus <= cfg->end_bus)
> + return cfg;
> +
> + return NULL;
> +}
> +
> +int __init __weak acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg,
> + struct acpi_mcfg_allocation *cfg)
> +{
> + return 0;
> +}
> +
> +int __init pci_parse_mcfg(struct acpi_table_header *header)
> +{
> + struct acpi_table_mcfg *mcfg;
> + struct acpi_mcfg_allocation *cfg_table, *cfg;
> + unsigned long i;
> + int entries;
> +
> + if (!header)
> + return -EINVAL;
> +
> + mcfg = (struct acpi_table_mcfg *)header;
> +
> + /* how many config structures do we have */
> + free_all_mmcfg();
> + entries = 0;
> + i = header->length - sizeof(struct acpi_table_mcfg);
> + while (i >= sizeof(struct acpi_mcfg_allocation)) {
> + entries++;
> + i -= sizeof(struct acpi_mcfg_allocation);
> + }
> + if (entries == 0) {
> + pr_err(PREFIX "MMCONFIG has no entries\n");
> + return -ENODEV;
> + }
> +
> + cfg_table = (struct acpi_mcfg_allocation *) &mcfg[1];
> + for (i = 0; i < entries; i++) {
> + cfg = &cfg_table[i];
> + if (acpi_mcfg_check_entry(mcfg, cfg)) {
> + free_all_mmcfg();
> + return -ENODEV;
> + }
> +
> + if (pci_mmconfig_add(cfg->pci_segment, cfg->start_bus_number,
> + cfg->end_bus_number, cfg->address) == NULL) {
> + pr_warn(PREFIX "no memory for MCFG entries\n");
> + free_all_mmcfg();
> + return -ENOMEM;
> + }
> + }
> +
> + return 0;
> +}
> +
> +/* Delete MMCFG information for host bridges */
> +int pci_mmconfig_delete(u16 seg, u8 start, u8 end)
> +{
> + struct pci_mmcfg_region *cfg;
> +
> + mutex_lock(&pci_mmcfg_lock);
> + list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list)
> + if (cfg->segment == seg && cfg->start_bus == start &&
> + cfg->end_bus == end) {
> + list_del_rcu(&cfg->list);
> + synchronize_rcu();
> + pci_mmcfg_arch_unmap(cfg);
> + if (cfg->res.parent)
> + release_resource(&cfg->res);
> + mutex_unlock(&pci_mmcfg_lock);
> + kfree(cfg);
> + return 0;
> + }
> + mutex_unlock(&pci_mmcfg_lock);
> +
> + return -ENOENT;
> +}
> +
> +void __init __weak pci_mmcfg_early_init(void)
> +{
> +
> +}
> +
> +void __init __weak pci_mmcfg_late_init(void)
> +{
> + struct pci_mmcfg_region *cfg;
> +
> + acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
> +
> + if (list_empty(&pci_mmcfg_list))
> + return;
> +
> + if (!pci_mmcfg_arch_init())
> + free_all_mmcfg();
> +
> + list_for_each_entry(cfg, &pci_mmcfg_list, list)
> + insert_resource(&iomem_resource, &cfg->res);
> +}
> diff --git a/include/linux/mmconfig.h b/include/linux/mmconfig.h
> new file mode 100644
> index 0000000..6ccd1ee
> --- /dev/null
> +++ b/include/linux/mmconfig.h
> @@ -0,0 +1,58 @@
> +#ifndef __MMCONFIG_H
> +#define __MMCONFIG_H
> +#ifdef __KERNEL__
> +
> +#include <linux/types.h>
> +#include <linux/acpi.h>
> +
> +#ifdef CONFIG_PCI_MMCONFIG
> +/* "PCI MMCONFIG %04x [bus %02x-%02x]" */
> +#define PCI_MMCFG_RESOURCE_NAME_LEN (22 + 4 + 2 + 2)
> +
> +struct pci_mmcfg_region {
> + struct list_head list;
> + struct resource res;
> + u64 address;
> + char __iomem *virt;
> + u16 segment;
> + u8 start_bus;
> + u8 end_bus;
> + char name[PCI_MMCFG_RESOURCE_NAME_LEN];
> +};
> +
> +void pci_mmcfg_early_init(void);
> +void pci_mmcfg_late_init(void);
> +struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus);
> +
> +int pci_parse_mcfg(struct acpi_table_header *header);
> +struct pci_mmcfg_region *pci_mmconfig_alloc(int segment, int start,
> + int end, u64 addr);
> +int pci_mmconfig_inject(struct pci_mmcfg_region *cfg);
> +struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
> + int end, u64 addr);
> +void list_add_sorted(struct pci_mmcfg_region *new);
> +int acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg,
> + struct acpi_mcfg_allocation *cfg);
> +void free_all_mmcfg(void);
> +int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end,
> + phys_addr_t addr);
> +int pci_mmconfig_delete(u16 seg, u8 start, u8 end);
> +
> +/* Arch specific calls */
> +int pci_mmcfg_arch_init(void);
> +void pci_mmcfg_arch_free(void);
> +int pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg);
> +void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg);
> +
> +extern struct list_head pci_mmcfg_list;
> +
> +#define PCI_MMCFG_BUS_OFFSET(bus) ((bus) << 20)
> +#else /* CONFIG_PCI_MMCONFIG */
> +static inline void pci_mmcfg_late_init(void) { }
> +static inline void pci_mmcfg_early_init(void) { }
> +static inline void *pci_mmconfig_lookup(int segment, int bus)
> +{ return NULL; }
> +#endif /* CONFIG_PCI_MMCONFIG */
> +
> +#endif /* __KERNEL__ */
> +#endif /* __MMCONFIG_H */
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 6afba72..0a8b82e 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1658,14 +1658,6 @@ void pcibios_release_device(struct pci_dev *dev);
> extern struct dev_pm_ops pcibios_pm_ops;
> #endif
>
> -#ifdef CONFIG_PCI_MMCONFIG
> -void __init pci_mmcfg_early_init(void);
> -void __init pci_mmcfg_late_init(void);
> -#else
> -static inline void pci_mmcfg_early_init(void) { }
> -static inline void pci_mmcfg_late_init(void) { }
> -#endif
> -
> int pci_ext_cfg_avail(void);
>
> void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar);
> --
> 1.9.1
>
WARNING: multiple messages have this Message-ID (diff)
From: bhelgaas@google.com (Bjorn Helgaas)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 2/6] x86, acpi, pci: Move arch-agnostic MMCFG code out of arch/x86/ directory
Date: Wed, 10 Dec 2014 16:55:00 -0700 [thread overview]
Message-ID: <20141210235500.GA22886@google.com> (raw)
In-Reply-To: <1416413091-13452-3-git-send-email-tomasz.nowicki@linaro.org>
On Wed, Nov 19, 2014 at 05:04:47PM +0100, Tomasz Nowicki wrote:
> MMCFG table seems to be architecture independent and it makes sense
> to share common code across all architectures. The ones that may need
> architectural specific actions have default prototype (__weak).
>
> Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
> Tested-by: Hanjun Guo <hanjun.guo@linaro.org>
> ---
> arch/x86/include/asm/pci_x86.h | 29 -----
> arch/x86/pci/acpi.c | 1 +
> arch/x86/pci/init.c | 1 +
> arch/x86/pci/mmconfig-shared.c | 200 +---------------------------------
> arch/x86/pci/mmconfig_32.c | 1 +
> arch/x86/pci/mmconfig_64.c | 1 +
> drivers/acpi/Makefile | 1 +
> drivers/acpi/bus.c | 1 +
> drivers/acpi/mmconfig.c | 242 +++++++++++++++++++++++++++++++++++++++++
> include/linux/mmconfig.h | 58 ++++++++++
> include/linux/pci.h | 8 --
> 11 files changed, 308 insertions(+), 235 deletions(-)
> create mode 100644 drivers/acpi/mmconfig.c
> create mode 100644 include/linux/mmconfig.h
> ...
Much of the code you're moving to drivers/acpi/mmconfig.c is not actually
ACPI-specific and would have to be duplicated for a non-ACPI architecture
that supports ECAM. Could that code be moved somewhere like
drivers/pci/ecam.c, where it could be shared?
Bjorn
> diff --git a/drivers/acpi/mmconfig.c b/drivers/acpi/mmconfig.c
> new file mode 100644
> index 0000000..d62dccda
> --- /dev/null
> +++ b/drivers/acpi/mmconfig.c
> @@ -0,0 +1,242 @@
> +/*
> + * Arch agnostic low-level direct PCI config space access via MMCONFIG
> + *
> + * Per-architecture code takes care of the mappings, region validation and
> + * accesses themselves.
> + *
> + * 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.
> + *
> + */
> +
> +#include <linux/mutex.h>
> +#include <linux/rculist.h>
> +#include <linux/mmconfig.h>
> +
> +#define PREFIX "PCI: "
> +
> +static DEFINE_MUTEX(pci_mmcfg_lock);
> +
> +LIST_HEAD(pci_mmcfg_list);
> +
> +static void __init pci_mmconfig_remove(struct pci_mmcfg_region *cfg)
> +{
> + if (cfg->res.parent)
> + release_resource(&cfg->res);
> + list_del(&cfg->list);
> + kfree(cfg);
> +}
> +
> +void __init free_all_mmcfg(void)
> +{
> + struct pci_mmcfg_region *cfg, *tmp;
> +
> + pci_mmcfg_arch_free();
> + list_for_each_entry_safe(cfg, tmp, &pci_mmcfg_list, list)
> + pci_mmconfig_remove(cfg);
> +}
> +
> +void list_add_sorted(struct pci_mmcfg_region *new)
> +{
> + struct pci_mmcfg_region *cfg;
> +
> + /* keep list sorted by segment and starting bus number */
> + list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list) {
> + if (cfg->segment > new->segment ||
> + (cfg->segment == new->segment &&
> + cfg->start_bus >= new->start_bus)) {
> + list_add_tail_rcu(&new->list, &cfg->list);
> + return;
> + }
> + }
> + list_add_tail_rcu(&new->list, &pci_mmcfg_list);
> +}
> +
> +struct pci_mmcfg_region *pci_mmconfig_alloc(int segment, int start,
> + int end, u64 addr)
> +{
> + struct pci_mmcfg_region *new;
> + struct resource *res;
> +
> + if (addr == 0)
> + return NULL;
> +
> + new = kzalloc(sizeof(*new), GFP_KERNEL);
> + if (!new)
> + return NULL;
> +
> + new->address = addr;
> + new->segment = segment;
> + new->start_bus = start;
> + new->end_bus = end;
> +
> + res = &new->res;
> + res->start = addr + PCI_MMCFG_BUS_OFFSET(start);
> + res->end = addr + PCI_MMCFG_BUS_OFFSET(end + 1) - 1;
> + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
> + snprintf(new->name, PCI_MMCFG_RESOURCE_NAME_LEN,
> + "PCI MMCONFIG %04x [bus %02x-%02x]", segment, start, end);
> + res->name = new->name;
> +
> + return new;
> +}
> +
> +struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
> + int end, u64 addr)
> +{
> + struct pci_mmcfg_region *new;
> +
> + new = pci_mmconfig_alloc(segment, start, end, addr);
> + if (new) {
> + mutex_lock(&pci_mmcfg_lock);
> + list_add_sorted(new);
> + mutex_unlock(&pci_mmcfg_lock);
> +
> + pr_info(PREFIX
> + "MMCONFIG for domain %04x [bus %02x-%02x] at %pR "
> + "(base %#lx)\n",
> + segment, start, end, &new->res, (unsigned long)addr);
> + }
> +
> + return new;
> +}
> +
> +int __init pci_mmconfig_inject(struct pci_mmcfg_region *cfg)
> +{
> + struct pci_mmcfg_region *cfg_conflict;
> + int err = 0;
> +
> + mutex_lock(&pci_mmcfg_lock);
> + cfg_conflict = pci_mmconfig_lookup(cfg->segment, cfg->start_bus);
> + if (cfg_conflict) {
> + if (cfg_conflict->end_bus < cfg->end_bus)
> + pr_info(FW_INFO "MMCONFIG for "
> + "domain %04x [bus %02x-%02x] "
> + "only partially covers this bridge\n",
> + cfg_conflict->segment, cfg_conflict->start_bus,
> + cfg_conflict->end_bus);
> + err = -EEXIST;
> + goto out;
> + }
> +
> + if (pci_mmcfg_arch_map(cfg)) {
> + pr_warn("fail to map MMCONFIG %pR.\n", &cfg->res);
> + err = -ENOMEM;
> + goto out;
> + } else {
> + list_add_sorted(cfg);
> + pr_info("MMCONFIG at %pR (base %#lx)\n",
> + &cfg->res, (unsigned long)cfg->address);
> +
> + }
> +out:
> + mutex_unlock(&pci_mmcfg_lock);
> + return err;
> +}
> +
> +struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus)
> +{
> + struct pci_mmcfg_region *cfg;
> +
> + list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list)
> + if (cfg->segment == segment &&
> + cfg->start_bus <= bus && bus <= cfg->end_bus)
> + return cfg;
> +
> + return NULL;
> +}
> +
> +int __init __weak acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg,
> + struct acpi_mcfg_allocation *cfg)
> +{
> + return 0;
> +}
> +
> +int __init pci_parse_mcfg(struct acpi_table_header *header)
> +{
> + struct acpi_table_mcfg *mcfg;
> + struct acpi_mcfg_allocation *cfg_table, *cfg;
> + unsigned long i;
> + int entries;
> +
> + if (!header)
> + return -EINVAL;
> +
> + mcfg = (struct acpi_table_mcfg *)header;
> +
> + /* how many config structures do we have */
> + free_all_mmcfg();
> + entries = 0;
> + i = header->length - sizeof(struct acpi_table_mcfg);
> + while (i >= sizeof(struct acpi_mcfg_allocation)) {
> + entries++;
> + i -= sizeof(struct acpi_mcfg_allocation);
> + }
> + if (entries == 0) {
> + pr_err(PREFIX "MMCONFIG has no entries\n");
> + return -ENODEV;
> + }
> +
> + cfg_table = (struct acpi_mcfg_allocation *) &mcfg[1];
> + for (i = 0; i < entries; i++) {
> + cfg = &cfg_table[i];
> + if (acpi_mcfg_check_entry(mcfg, cfg)) {
> + free_all_mmcfg();
> + return -ENODEV;
> + }
> +
> + if (pci_mmconfig_add(cfg->pci_segment, cfg->start_bus_number,
> + cfg->end_bus_number, cfg->address) == NULL) {
> + pr_warn(PREFIX "no memory for MCFG entries\n");
> + free_all_mmcfg();
> + return -ENOMEM;
> + }
> + }
> +
> + return 0;
> +}
> +
> +/* Delete MMCFG information for host bridges */
> +int pci_mmconfig_delete(u16 seg, u8 start, u8 end)
> +{
> + struct pci_mmcfg_region *cfg;
> +
> + mutex_lock(&pci_mmcfg_lock);
> + list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list)
> + if (cfg->segment == seg && cfg->start_bus == start &&
> + cfg->end_bus == end) {
> + list_del_rcu(&cfg->list);
> + synchronize_rcu();
> + pci_mmcfg_arch_unmap(cfg);
> + if (cfg->res.parent)
> + release_resource(&cfg->res);
> + mutex_unlock(&pci_mmcfg_lock);
> + kfree(cfg);
> + return 0;
> + }
> + mutex_unlock(&pci_mmcfg_lock);
> +
> + return -ENOENT;
> +}
> +
> +void __init __weak pci_mmcfg_early_init(void)
> +{
> +
> +}
> +
> +void __init __weak pci_mmcfg_late_init(void)
> +{
> + struct pci_mmcfg_region *cfg;
> +
> + acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
> +
> + if (list_empty(&pci_mmcfg_list))
> + return;
> +
> + if (!pci_mmcfg_arch_init())
> + free_all_mmcfg();
> +
> + list_for_each_entry(cfg, &pci_mmcfg_list, list)
> + insert_resource(&iomem_resource, &cfg->res);
> +}
> diff --git a/include/linux/mmconfig.h b/include/linux/mmconfig.h
> new file mode 100644
> index 0000000..6ccd1ee
> --- /dev/null
> +++ b/include/linux/mmconfig.h
> @@ -0,0 +1,58 @@
> +#ifndef __MMCONFIG_H
> +#define __MMCONFIG_H
> +#ifdef __KERNEL__
> +
> +#include <linux/types.h>
> +#include <linux/acpi.h>
> +
> +#ifdef CONFIG_PCI_MMCONFIG
> +/* "PCI MMCONFIG %04x [bus %02x-%02x]" */
> +#define PCI_MMCFG_RESOURCE_NAME_LEN (22 + 4 + 2 + 2)
> +
> +struct pci_mmcfg_region {
> + struct list_head list;
> + struct resource res;
> + u64 address;
> + char __iomem *virt;
> + u16 segment;
> + u8 start_bus;
> + u8 end_bus;
> + char name[PCI_MMCFG_RESOURCE_NAME_LEN];
> +};
> +
> +void pci_mmcfg_early_init(void);
> +void pci_mmcfg_late_init(void);
> +struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus);
> +
> +int pci_parse_mcfg(struct acpi_table_header *header);
> +struct pci_mmcfg_region *pci_mmconfig_alloc(int segment, int start,
> + int end, u64 addr);
> +int pci_mmconfig_inject(struct pci_mmcfg_region *cfg);
> +struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
> + int end, u64 addr);
> +void list_add_sorted(struct pci_mmcfg_region *new);
> +int acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg,
> + struct acpi_mcfg_allocation *cfg);
> +void free_all_mmcfg(void);
> +int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end,
> + phys_addr_t addr);
> +int pci_mmconfig_delete(u16 seg, u8 start, u8 end);
> +
> +/* Arch specific calls */
> +int pci_mmcfg_arch_init(void);
> +void pci_mmcfg_arch_free(void);
> +int pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg);
> +void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg);
> +
> +extern struct list_head pci_mmcfg_list;
> +
> +#define PCI_MMCFG_BUS_OFFSET(bus) ((bus) << 20)
> +#else /* CONFIG_PCI_MMCONFIG */
> +static inline void pci_mmcfg_late_init(void) { }
> +static inline void pci_mmcfg_early_init(void) { }
> +static inline void *pci_mmconfig_lookup(int segment, int bus)
> +{ return NULL; }
> +#endif /* CONFIG_PCI_MMCONFIG */
> +
> +#endif /* __KERNEL__ */
> +#endif /* __MMCONFIG_H */
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 6afba72..0a8b82e 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1658,14 +1658,6 @@ void pcibios_release_device(struct pci_dev *dev);
> extern struct dev_pm_ops pcibios_pm_ops;
> #endif
>
> -#ifdef CONFIG_PCI_MMCONFIG
> -void __init pci_mmcfg_early_init(void);
> -void __init pci_mmcfg_late_init(void);
> -#else
> -static inline void pci_mmcfg_early_init(void) { }
> -static inline void pci_mmcfg_late_init(void) { }
> -#endif
> -
> int pci_ext_cfg_avail(void);
>
> void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar);
> --
> 1.9.1
>
next prev parent reply other threads:[~2014-12-10 23:55 UTC|newest]
Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-11-19 16:04 [PATCH 0/6] PCI: MMCONFIG clean up Tomasz Nowicki
2014-11-19 16:04 ` Tomasz Nowicki
2014-11-19 16:04 ` [PATCH 1/6] x86, acpi, pci: Reorder logic of pci_mmconfig_insert() function Tomasz Nowicki
2014-11-19 16:04 ` Tomasz Nowicki
2014-11-19 16:04 ` Tomasz Nowicki
2014-11-19 16:04 ` [PATCH 2/6] x86, acpi, pci: Move arch-agnostic MMCFG code out of arch/x86/ directory Tomasz Nowicki
2014-11-19 16:04 ` Tomasz Nowicki
2014-12-10 23:35 ` Bjorn Helgaas
2014-12-10 23:35 ` Bjorn Helgaas
2014-12-10 23:55 ` Bjorn Helgaas [this message]
2014-12-10 23:55 ` Bjorn Helgaas
2014-12-12 14:55 ` [Linaro-acpi] " Arnd Bergmann
2014-12-12 14:55 ` Arnd Bergmann
2014-11-19 16:04 ` [PATCH 3/6] x86, acpi, pci: Move PCI config space accessors Tomasz Nowicki
2014-11-19 16:04 ` Tomasz Nowicki
2014-12-10 23:17 ` Bjorn Helgaas
2014-12-10 23:17 ` Bjorn Helgaas
2015-02-03 9:30 ` Tomasz Nowicki
2015-02-03 9:30 ` Tomasz Nowicki
2015-02-17 13:03 ` Tomasz Nowicki
2015-02-17 13:03 ` Tomasz Nowicki
2015-02-18 18:27 ` Bjorn Helgaas
2015-02-18 18:27 ` Bjorn Helgaas
2015-02-18 19:02 ` Rob Herring
2015-02-18 19:02 ` Rob Herring
2014-11-19 16:04 ` [PATCH 4/6] x86, acpi, pci: mmconfig_{32,64}.c code refactoring - remove code duplication Tomasz Nowicki
2014-11-19 16:04 ` [PATCH 4/6] x86, acpi, pci: mmconfig_{32, 64}.c " Tomasz Nowicki
2014-11-19 16:04 ` [PATCH 5/6] x86, acpi, pci: mmconfig_64.c becomes default implementation for arch agnostic low-level direct PCI config space accessors via MMCONFIG Tomasz Nowicki
2014-11-19 16:04 ` Tomasz Nowicki
2014-11-19 16:04 ` [PATCH 6/6] pci, acpi: Share ACPI PCI config space accessors Tomasz Nowicki
2014-11-19 16:04 ` Tomasz Nowicki
2014-11-19 16:19 ` Arnd Bergmann
2014-11-19 16:19 ` Arnd Bergmann
2014-11-19 16:24 ` Tomasz Nowicki
2014-11-19 16:24 ` Tomasz Nowicki
2014-11-20 22:26 ` Bjorn Helgaas
2014-11-20 22:26 ` Bjorn Helgaas
2014-11-21 4:00 ` Myron Stowe
2014-11-21 4:00 ` Myron Stowe
2014-11-21 12:24 ` Arnd Bergmann
2014-11-21 12:24 ` Arnd Bergmann
2014-11-21 18:08 ` Bjorn Helgaas
2014-11-21 18:08 ` Bjorn Helgaas
2014-11-24 10:41 ` Arnd Bergmann
2014-11-24 10:41 ` Arnd Bergmann
2014-12-08 7:13 ` Tomasz Nowicki
2014-12-08 7:13 ` Tomasz Nowicki
2014-12-09 21:50 ` Bjorn Helgaas
2014-12-09 21:50 ` Bjorn Helgaas
2014-12-10 6:16 ` Tomasz Nowicki
2014-12-10 6:16 ` Tomasz Nowicki
2015-02-02 20:42 ` [PATCH 0/6] PCI: MMCONFIG clean up Bjorn Helgaas
2015-02-02 20:42 ` Bjorn Helgaas
2015-02-03 7:42 ` Tomasz Nowicki
2015-02-03 7:42 ` Tomasz Nowicki
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20141210235500.GA22886@google.com \
--to=bhelgaas@google.com \
--cc=Liviu.Dudau@arm.com \
--cc=arnd@arndb.de \
--cc=catalin.marinas@arm.com \
--cc=hanjun.guo@linaro.org \
--cc=hpa@zytor.com \
--cc=linaro-acpi@lists.linaro.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=lorenzo.pieralisi@arm.com \
--cc=mingo@redhat.com \
--cc=rjw@rjwysocki.net \
--cc=tglx@linutronix.de \
--cc=tomasz.nowicki@linaro.org \
--cc=wangyijing@huawei.com \
--cc=will.deacon@arm.com \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.