From: Bjorn Helgaas <helgaas@kernel.org>
To: Tomasz Nowicki <tn@semihalf.com>
Cc: 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, robert.richter@caviumnetworks.com,
mw@semihalf.com, Liviu.Dudau@arm.com, ddaney@caviumnetworks.com,
wangyijing@huawei.com, Suravee.Suthikulpanit@amd.com,
msalter@redhat.com, linux-pci@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, linux-acpi@vger.kernel.org,
linux-kernel@vger.kernel.org, linaro-acpi@lists.linaro.org,
jcm@redhat.com, andrea.gallo@linaro.org, dhdang@apm.com,
jeremy.linton@arm.com, liudongdong3@huawei.com,
cov@codeaurora.org
Subject: Re: [PATCH V8 7/9] acpi: Add generic MCFG table handling
Date: Tue, 7 Jun 2016 20:56:31 -0500 [thread overview]
Message-ID: <20160608015631.GE4759@localhost> (raw)
In-Reply-To: <1464621262-26770-8-git-send-email-tn@semihalf.com>
On Mon, May 30, 2016 at 05:14:20PM +0200, Tomasz Nowicki wrote:
> In order to handle PCI config space regions properly in ACPI, new MCFG
> interface is defined which does sanity checks on MCFG table and keeps its
> root pointer. The user is able to lookup MCFG regions based on
> host bridge root structure and domain:bus_start:bus_end touple.
> Use pci_mmcfg_late_init old prototype to avoid another function name.
>
> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
> Signed-off-by: Jayachandran C <jchandra@broadcom.com>
> ---
> drivers/acpi/Kconfig | 3 ++
> drivers/acpi/Makefile | 1 +
> drivers/acpi/pci_mcfg.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/pci-acpi.h | 2 ++
> include/linux/pci.h | 2 +-
> 5 files changed, 101 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..1847f74
> --- /dev/null
> +++ b/drivers/acpi/pci_mcfg.c
> @@ -0,0 +1,94 @@
> +/*
> + * 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>
> +
> +/* Root pointer to the mapped MCFG table */
> +static struct acpi_table_mcfg *mcfg_table;
> +static int mcfg_entries;
> +
> +int pci_mcfg_lookup(struct acpi_pci_root *root)
I think this would be better if we passed in the domain and a pointer
to the bus range resource and returned the ECAM base address. I don't
think we need to be connected to struct acpi_pci_root.
> +{
> + struct acpi_mcfg_allocation *mptr, *entry = NULL;
> + struct resource *bus_res = &root->secondary;
> + int i;
> +
> + if (mcfg_table) {
> + mptr = (struct acpi_mcfg_allocation *) &mcfg_table[1];
> + for (i = 0; i < mcfg_entries && !entry; i++, mptr++)
> + if (mptr->pci_segment == root->segment &&
> + mptr->start_bus_number == bus_res->start)
> + entry = mptr;
> + }
> +
> + /* not found, use _CBA if available, else error */
> + if (!entry) {
> + if (root->mcfg_addr)
> + return root->mcfg_addr;
> + pr_err("%04x:%pR MCFG lookup failed\n", root->segment, bus_res);
> + return -ENOENT;
> + } else if (root->mcfg_addr && entry->address != root->mcfg_addr) {
> + pr_warn("%04x:%pR CBA %pa != MCFG %lx, using CBA\n",
> + root->segment, bus_res, &root->mcfg_addr,
> + (unsigned long)entry->address);
> + return 0;
> + }
I keep looking at this code, trying to find where we "use _CBA", but I
can't find it. Oh, I see, acpi_pci_root_add() calls
acpi_pci_root_get_mcfg_addr() (which evaluates _CBA), and sets
root->mcfg_addr to the result.
"root->mcfg_addr" is sort of an unfortunate name because "MCFG" is the
ACPI table name, we've used "ECAM" for the memory-mapped config space,
and this address can come from either the MCFG table or the _CBA
method.
In the case where we have both _CBA and an MCFG entry, I think we
should prefer _CBA, and I'm not sure it's even worth warning about it.
So I think you could simplify this function if you made
pci_acpi_setup_ecam_mapping() look like this:
... pci_acpi_setup_ecam_mapping(...)
{
...
if (!root->mcfg_addr)
root->mcfg_addr = pci_mcfg_lookup(root);
if (!root->mcfg_addr) {
dev_err(..., "no ECAM region found\n");
return -EINVAL;
}
> +
> + /* found matching entry, bus range check */
> + if (entry->end_bus_number != bus_res->end) {
> + resource_size_t bus_end = min_t(resource_size_t,
> + entry->end_bus_number, bus_res->end);
> + pr_warn("%04x:%pR bus end mismatch, using %02lx\n",
> + root->segment, bus_res, (unsigned long)bus_end);
> + bus_res->end = bus_end;
> + }
> +
> + if (!root->mcfg_addr)
> + root->mcfg_addr = entry->address;
Please move the assignment to the caller (I think Lorenzo pointed this
out already).
> + return 0;
> +}
> +
> +static __init int pci_mcfg_parse(struct acpi_table_header *header)
> +{
> + if (header->length < sizeof(struct acpi_table_mcfg))
> + return -EINVAL;
> +
> + mcfg_entries = (header->length - sizeof(struct acpi_table_mcfg)) /
> + sizeof(struct acpi_mcfg_allocation);
> + if (mcfg_entries == 0) {
> + pr_err("MCFG has no entries\n");
Include an address here? I'm not really sure either of the messages
here is necessary. Users (callers of pci_mcfg_lookup()) will notice
if we can't find any ECAM space and will probably complain there,
where the message can include more information, e.g., the affected
device.
> + return -EINVAL;
> + }
> +
> + mcfg_table = (struct acpi_table_mcfg *)header;
> + pr_info("MCFG table detected, %d entries\n", mcfg_entries);
> + return 0;
> +}
> +
> +/* Interface called by ACPI - parse and save MCFG table */
I think we save a *pointer* to the MCFG table, not the table itself.
And acpi_table_parse() calls early_acpi_os_unmap_memory() immediately
after it calls pci_mcfg_parse(), so I'm doubtful that the pointer
remains valid.
> +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..e0e6dfc 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 int pci_mcfg_lookup(struct acpi_pci_root *root);
> +
> 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 bba4053..9661c85 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1724,7 +1724,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
> --
> 1.9.1
>
WARNING: multiple messages have this Message-ID (diff)
From: Bjorn Helgaas <helgaas@kernel.org>
To: Tomasz Nowicki <tn@semihalf.com>
Cc: rafael@kernel.org, linux-pci@vger.kernel.org,
will.deacon@arm.com, okaya@codeaurora.org, wangyijing@huawei.com,
andrea.gallo@linaro.org, Lorenzo.Pieralisi@arm.com,
linaro-acpi@lists.linaro.org, ddaney@caviumnetworks.com,
linux-acpi@vger.kernel.org, robert.richter@caviumnetworks.com,
liudongdong3@huawei.com, catalin.marinas@arm.com,
Liviu.Dudau@arm.com, arnd@arndb.de, jcm@redhat.com,
msalter@redhat.com, cov@codeaurora.org, mw@semihalf.com,
linux-arm-kernel@lists.infradead.org, jchandra@broadcom.com,
dhdang@apm.com, linux-kernel@vger.kernel.org,
jeremy.linton@arm.com, hanjun.guo@linaro.org,
Suravee.Suthikulpanit@amd.com
Subject: Re: [PATCH V8 7/9] acpi: Add generic MCFG table handling
Date: Tue, 7 Jun 2016 20:56:31 -0500 [thread overview]
Message-ID: <20160608015631.GE4759@localhost> (raw)
In-Reply-To: <1464621262-26770-8-git-send-email-tn@semihalf.com>
On Mon, May 30, 2016 at 05:14:20PM +0200, Tomasz Nowicki wrote:
> In order to handle PCI config space regions properly in ACPI, new MCFG
> interface is defined which does sanity checks on MCFG table and keeps its
> root pointer. The user is able to lookup MCFG regions based on
> host bridge root structure and domain:bus_start:bus_end touple.
> Use pci_mmcfg_late_init old prototype to avoid another function name.
>
> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
> Signed-off-by: Jayachandran C <jchandra@broadcom.com>
> ---
> drivers/acpi/Kconfig | 3 ++
> drivers/acpi/Makefile | 1 +
> drivers/acpi/pci_mcfg.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/pci-acpi.h | 2 ++
> include/linux/pci.h | 2 +-
> 5 files changed, 101 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..1847f74
> --- /dev/null
> +++ b/drivers/acpi/pci_mcfg.c
> @@ -0,0 +1,94 @@
> +/*
> + * 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>
> +
> +/* Root pointer to the mapped MCFG table */
> +static struct acpi_table_mcfg *mcfg_table;
> +static int mcfg_entries;
> +
> +int pci_mcfg_lookup(struct acpi_pci_root *root)
I think this would be better if we passed in the domain and a pointer
to the bus range resource and returned the ECAM base address. I don't
think we need to be connected to struct acpi_pci_root.
> +{
> + struct acpi_mcfg_allocation *mptr, *entry = NULL;
> + struct resource *bus_res = &root->secondary;
> + int i;
> +
> + if (mcfg_table) {
> + mptr = (struct acpi_mcfg_allocation *) &mcfg_table[1];
> + for (i = 0; i < mcfg_entries && !entry; i++, mptr++)
> + if (mptr->pci_segment == root->segment &&
> + mptr->start_bus_number == bus_res->start)
> + entry = mptr;
> + }
> +
> + /* not found, use _CBA if available, else error */
> + if (!entry) {
> + if (root->mcfg_addr)
> + return root->mcfg_addr;
> + pr_err("%04x:%pR MCFG lookup failed\n", root->segment, bus_res);
> + return -ENOENT;
> + } else if (root->mcfg_addr && entry->address != root->mcfg_addr) {
> + pr_warn("%04x:%pR CBA %pa != MCFG %lx, using CBA\n",
> + root->segment, bus_res, &root->mcfg_addr,
> + (unsigned long)entry->address);
> + return 0;
> + }
I keep looking at this code, trying to find where we "use _CBA", but I
can't find it. Oh, I see, acpi_pci_root_add() calls
acpi_pci_root_get_mcfg_addr() (which evaluates _CBA), and sets
root->mcfg_addr to the result.
"root->mcfg_addr" is sort of an unfortunate name because "MCFG" is the
ACPI table name, we've used "ECAM" for the memory-mapped config space,
and this address can come from either the MCFG table or the _CBA
method.
In the case where we have both _CBA and an MCFG entry, I think we
should prefer _CBA, and I'm not sure it's even worth warning about it.
So I think you could simplify this function if you made
pci_acpi_setup_ecam_mapping() look like this:
... pci_acpi_setup_ecam_mapping(...)
{
...
if (!root->mcfg_addr)
root->mcfg_addr = pci_mcfg_lookup(root);
if (!root->mcfg_addr) {
dev_err(..., "no ECAM region found\n");
return -EINVAL;
}
> +
> + /* found matching entry, bus range check */
> + if (entry->end_bus_number != bus_res->end) {
> + resource_size_t bus_end = min_t(resource_size_t,
> + entry->end_bus_number, bus_res->end);
> + pr_warn("%04x:%pR bus end mismatch, using %02lx\n",
> + root->segment, bus_res, (unsigned long)bus_end);
> + bus_res->end = bus_end;
> + }
> +
> + if (!root->mcfg_addr)
> + root->mcfg_addr = entry->address;
Please move the assignment to the caller (I think Lorenzo pointed this
out already).
> + return 0;
> +}
> +
> +static __init int pci_mcfg_parse(struct acpi_table_header *header)
> +{
> + if (header->length < sizeof(struct acpi_table_mcfg))
> + return -EINVAL;
> +
> + mcfg_entries = (header->length - sizeof(struct acpi_table_mcfg)) /
> + sizeof(struct acpi_mcfg_allocation);
> + if (mcfg_entries == 0) {
> + pr_err("MCFG has no entries\n");
Include an address here? I'm not really sure either of the messages
here is necessary. Users (callers of pci_mcfg_lookup()) will notice
if we can't find any ECAM space and will probably complain there,
where the message can include more information, e.g., the affected
device.
> + return -EINVAL;
> + }
> +
> + mcfg_table = (struct acpi_table_mcfg *)header;
> + pr_info("MCFG table detected, %d entries\n", mcfg_entries);
> + return 0;
> +}
> +
> +/* Interface called by ACPI - parse and save MCFG table */
I think we save a *pointer* to the MCFG table, not the table itself.
And acpi_table_parse() calls early_acpi_os_unmap_memory() immediately
after it calls pci_mcfg_parse(), so I'm doubtful that the pointer
remains valid.
> +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..e0e6dfc 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 int pci_mcfg_lookup(struct acpi_pci_root *root);
> +
> 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 bba4053..9661c85 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1724,7 +1724,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
> --
> 1.9.1
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
WARNING: multiple messages have this Message-ID (diff)
From: helgaas@kernel.org (Bjorn Helgaas)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH V8 7/9] acpi: Add generic MCFG table handling
Date: Tue, 7 Jun 2016 20:56:31 -0500 [thread overview]
Message-ID: <20160608015631.GE4759@localhost> (raw)
In-Reply-To: <1464621262-26770-8-git-send-email-tn@semihalf.com>
On Mon, May 30, 2016 at 05:14:20PM +0200, Tomasz Nowicki wrote:
> In order to handle PCI config space regions properly in ACPI, new MCFG
> interface is defined which does sanity checks on MCFG table and keeps its
> root pointer. The user is able to lookup MCFG regions based on
> host bridge root structure and domain:bus_start:bus_end touple.
> Use pci_mmcfg_late_init old prototype to avoid another function name.
>
> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
> Signed-off-by: Jayachandran C <jchandra@broadcom.com>
> ---
> drivers/acpi/Kconfig | 3 ++
> drivers/acpi/Makefile | 1 +
> drivers/acpi/pci_mcfg.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/pci-acpi.h | 2 ++
> include/linux/pci.h | 2 +-
> 5 files changed, 101 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..1847f74
> --- /dev/null
> +++ b/drivers/acpi/pci_mcfg.c
> @@ -0,0 +1,94 @@
> +/*
> + * 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>
> +
> +/* Root pointer to the mapped MCFG table */
> +static struct acpi_table_mcfg *mcfg_table;
> +static int mcfg_entries;
> +
> +int pci_mcfg_lookup(struct acpi_pci_root *root)
I think this would be better if we passed in the domain and a pointer
to the bus range resource and returned the ECAM base address. I don't
think we need to be connected to struct acpi_pci_root.
> +{
> + struct acpi_mcfg_allocation *mptr, *entry = NULL;
> + struct resource *bus_res = &root->secondary;
> + int i;
> +
> + if (mcfg_table) {
> + mptr = (struct acpi_mcfg_allocation *) &mcfg_table[1];
> + for (i = 0; i < mcfg_entries && !entry; i++, mptr++)
> + if (mptr->pci_segment == root->segment &&
> + mptr->start_bus_number == bus_res->start)
> + entry = mptr;
> + }
> +
> + /* not found, use _CBA if available, else error */
> + if (!entry) {
> + if (root->mcfg_addr)
> + return root->mcfg_addr;
> + pr_err("%04x:%pR MCFG lookup failed\n", root->segment, bus_res);
> + return -ENOENT;
> + } else if (root->mcfg_addr && entry->address != root->mcfg_addr) {
> + pr_warn("%04x:%pR CBA %pa != MCFG %lx, using CBA\n",
> + root->segment, bus_res, &root->mcfg_addr,
> + (unsigned long)entry->address);
> + return 0;
> + }
I keep looking at this code, trying to find where we "use _CBA", but I
can't find it. Oh, I see, acpi_pci_root_add() calls
acpi_pci_root_get_mcfg_addr() (which evaluates _CBA), and sets
root->mcfg_addr to the result.
"root->mcfg_addr" is sort of an unfortunate name because "MCFG" is the
ACPI table name, we've used "ECAM" for the memory-mapped config space,
and this address can come from either the MCFG table or the _CBA
method.
In the case where we have both _CBA and an MCFG entry, I think we
should prefer _CBA, and I'm not sure it's even worth warning about it.
So I think you could simplify this function if you made
pci_acpi_setup_ecam_mapping() look like this:
... pci_acpi_setup_ecam_mapping(...)
{
...
if (!root->mcfg_addr)
root->mcfg_addr = pci_mcfg_lookup(root);
if (!root->mcfg_addr) {
dev_err(..., "no ECAM region found\n");
return -EINVAL;
}
> +
> + /* found matching entry, bus range check */
> + if (entry->end_bus_number != bus_res->end) {
> + resource_size_t bus_end = min_t(resource_size_t,
> + entry->end_bus_number, bus_res->end);
> + pr_warn("%04x:%pR bus end mismatch, using %02lx\n",
> + root->segment, bus_res, (unsigned long)bus_end);
> + bus_res->end = bus_end;
> + }
> +
> + if (!root->mcfg_addr)
> + root->mcfg_addr = entry->address;
Please move the assignment to the caller (I think Lorenzo pointed this
out already).
> + return 0;
> +}
> +
> +static __init int pci_mcfg_parse(struct acpi_table_header *header)
> +{
> + if (header->length < sizeof(struct acpi_table_mcfg))
> + return -EINVAL;
> +
> + mcfg_entries = (header->length - sizeof(struct acpi_table_mcfg)) /
> + sizeof(struct acpi_mcfg_allocation);
> + if (mcfg_entries == 0) {
> + pr_err("MCFG has no entries\n");
Include an address here? I'm not really sure either of the messages
here is necessary. Users (callers of pci_mcfg_lookup()) will notice
if we can't find any ECAM space and will probably complain there,
where the message can include more information, e.g., the affected
device.
> + return -EINVAL;
> + }
> +
> + mcfg_table = (struct acpi_table_mcfg *)header;
> + pr_info("MCFG table detected, %d entries\n", mcfg_entries);
> + return 0;
> +}
> +
> +/* Interface called by ACPI - parse and save MCFG table */
I think we save a *pointer* to the MCFG table, not the table itself.
And acpi_table_parse() calls early_acpi_os_unmap_memory() immediately
after it calls pci_mcfg_parse(), so I'm doubtful that the pointer
remains valid.
> +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..e0e6dfc 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 int pci_mcfg_lookup(struct acpi_pci_root *root);
> +
> 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 bba4053..9661c85 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1724,7 +1724,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
> --
> 1.9.1
>
next prev parent reply other threads:[~2016-06-08 1:56 UTC|newest]
Thread overview: 113+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-30 15:14 [PATCH V8 0/9] Support for ARM64 ACPI based PCI host controller Tomasz Nowicki
2016-05-30 15:14 ` Tomasz Nowicki
2016-05-30 15:14 ` [PATCH V8 1/9] PCI: ecam: move ecam.h to linux/include/pci-ecam.h Tomasz Nowicki
2016-05-30 15:14 ` Tomasz Nowicki
2016-05-30 15:14 ` Tomasz Nowicki
2016-06-02 9:48 ` Lorenzo Pieralisi
2016-06-02 9:48 ` Lorenzo Pieralisi
2016-05-30 15:14 ` [PATCH V8 2/9] PCI: ecam: Add parent device field to pci_config_window Tomasz Nowicki
2016-05-30 15:14 ` Tomasz Nowicki
2016-05-30 15:14 ` Tomasz Nowicki
2016-06-02 10:13 ` Lorenzo Pieralisi
2016-06-02 10:13 ` Lorenzo Pieralisi
2016-05-30 15:14 ` [PATCH V8 3/9] pci: Add new function to unmap IO resources Tomasz Nowicki
2016-05-30 15:14 ` Tomasz Nowicki
2016-05-30 15:14 ` Tomasz Nowicki
2016-06-02 16:50 ` Lorenzo Pieralisi
2016-06-02 16:50 ` Lorenzo Pieralisi
2016-05-30 15:14 ` [PATCH V8 4/9] acpi, pci: Support IO resources when parsing PCI host bridge resources Tomasz Nowicki
2016-05-30 15:14 ` Tomasz Nowicki
2016-06-02 17:30 ` Lorenzo Pieralisi
2016-06-02 17:30 ` Lorenzo Pieralisi
2016-06-07 23:56 ` Bjorn Helgaas
2016-06-07 23:56 ` Bjorn Helgaas
2016-06-07 23:56 ` Bjorn Helgaas
2016-05-30 15:14 ` [PATCH V8 5/9] pci, acpi: add acpi hook to assign domain number Tomasz Nowicki
2016-05-30 15:14 ` Tomasz Nowicki
2016-05-30 15:14 ` Tomasz Nowicki
2016-06-08 0:15 ` Bjorn Helgaas
2016-06-08 0:15 ` Bjorn Helgaas
2016-06-08 0:15 ` Bjorn Helgaas
2016-06-08 10:21 ` Tomasz Nowicki
2016-06-08 10:21 ` Tomasz Nowicki
2016-06-08 13:22 ` Bjorn Helgaas
2016-06-08 13:22 ` Bjorn Helgaas
2016-06-08 13:22 ` Bjorn Helgaas
2016-06-10 15:14 ` Lorenzo Pieralisi
2016-06-10 15:14 ` Lorenzo Pieralisi
2016-06-10 15:49 ` Lorenzo Pieralisi
2016-06-10 15:49 ` Lorenzo Pieralisi
2016-06-10 16:49 ` Tomasz Nowicki
2016-06-10 16:49 ` Tomasz Nowicki
2016-06-10 18:18 ` Bjorn Helgaas
2016-06-10 18:18 ` Bjorn Helgaas
2016-06-10 18:54 ` Jon Masters
2016-06-10 18:54 ` Jon Masters
2016-06-10 18:54 ` Jon Masters
2016-05-30 15:14 ` [PATCH V8 6/9] arm64, pci, acpi: ACPI support for legacy IRQs parsing and consolidation with DT code Tomasz Nowicki
2016-05-30 15:14 ` Tomasz Nowicki
2016-05-30 15:14 ` [PATCH V8 7/9] acpi: Add generic MCFG table handling Tomasz Nowicki
2016-05-30 15:14 ` Tomasz Nowicki
2016-06-03 11:38 ` Lorenzo Pieralisi
2016-06-03 11:38 ` Lorenzo Pieralisi
2016-06-06 12:55 ` Tomasz Nowicki
2016-06-06 12:55 ` Tomasz Nowicki
2016-06-08 1:56 ` Bjorn Helgaas [this message]
2016-06-08 1:56 ` Bjorn Helgaas
2016-06-08 1:56 ` Bjorn Helgaas
2016-06-08 12:21 ` Tomasz Nowicki
2016-06-08 12:21 ` Tomasz Nowicki
2016-06-08 13:17 ` Bjorn Helgaas
2016-06-08 13:17 ` Bjorn Helgaas
2016-06-08 13:17 ` Bjorn Helgaas
2016-06-08 13:44 ` Tomasz Nowicki
2016-06-08 13:44 ` Tomasz Nowicki
2016-05-30 15:14 ` [PATCH V8 8/9] arm64, pci, acpi: Provide ACPI-specific prerequisites for PCI bus enumeration Tomasz Nowicki
2016-05-30 15:14 ` Tomasz Nowicki
2016-06-02 9:45 ` Lorenzo Pieralisi
2016-06-02 9:45 ` Lorenzo Pieralisi
2016-06-02 9:51 ` Tomasz Nowicki
2016-06-02 9:51 ` Tomasz Nowicki
2016-05-30 15:14 ` [PATCH V8 9/9] pci, acpi: ARM64 support for ACPI based generic PCI host controller Tomasz Nowicki
2016-05-30 15:14 ` Tomasz Nowicki
2016-05-30 15:38 ` Arnd Bergmann
2016-05-30 15:38 ` Arnd Bergmann
2016-05-30 16:13 ` Jayachandran C
2016-05-30 16:13 ` Jayachandran C
2016-05-30 16:13 ` Jayachandran C
2016-06-02 9:35 ` Lorenzo Pieralisi
2016-06-02 9:35 ` Lorenzo Pieralisi
2016-06-02 9:44 ` Tomasz Nowicki
2016-06-02 9:44 ` Tomasz Nowicki
2016-06-08 2:14 ` Bjorn Helgaas
2016-06-08 2:14 ` Bjorn Helgaas
2016-06-08 2:14 ` Bjorn Helgaas
2016-06-01 7:36 ` [PATCH V8 0/9] Support for ARM64 ACPI based " Gabriele Paoloni
2016-06-01 7:36 ` Gabriele Paoloni
2016-06-01 7:36 ` Gabriele Paoloni
2016-06-01 7:36 ` Gabriele Paoloni
2016-06-02 7:31 ` Jon Masters
2016-06-02 7:31 ` Jon Masters
2016-06-02 8:53 ` [Linaro-acpi] " Martin Stadtler
2016-06-02 10:06 ` Gabriele Paoloni
2016-06-02 10:06 ` Gabriele Paoloni
2016-06-02 10:06 ` Gabriele Paoloni
2016-06-02 8:52 ` Tomasz Nowicki
2016-06-02 8:52 ` Tomasz Nowicki
2016-06-02 8:52 ` Tomasz Nowicki
2016-06-02 9:58 ` Gabriele Paoloni
2016-06-02 9:58 ` Gabriele Paoloni
2016-06-02 9:58 ` Gabriele Paoloni
2016-06-02 9:58 ` Gabriele Paoloni
2016-06-02 8:48 ` Jon Masters
2016-06-02 8:48 ` Jon Masters
2016-06-07 23:13 ` Bjorn Helgaas
2016-06-07 23:13 ` Bjorn Helgaas
2016-06-07 23:13 ` Bjorn Helgaas
2016-06-08 9:20 ` Dongdong Liu
2016-06-08 9:20 ` Dongdong Liu
2016-06-08 9:20 ` Dongdong Liu
2016-06-09 16:45 ` Suravee Suthikulanit
2016-06-09 16:45 ` Suravee Suthikulanit
2016-06-09 16:45 ` Suravee Suthikulanit
2016-06-09 16:45 ` Suravee Suthikulanit
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=20160608015631.GE4759@localhost \
--to=helgaas@kernel.org \
--cc=Liviu.Dudau@arm.com \
--cc=Lorenzo.Pieralisi@arm.com \
--cc=Suravee.Suthikulpanit@amd.com \
--cc=andrea.gallo@linaro.org \
--cc=arnd@arndb.de \
--cc=catalin.marinas@arm.com \
--cc=cov@codeaurora.org \
--cc=ddaney@caviumnetworks.com \
--cc=dhdang@apm.com \
--cc=hanjun.guo@linaro.org \
--cc=jchandra@broadcom.com \
--cc=jcm@redhat.com \
--cc=jeremy.linton@arm.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=liudongdong3@huawei.com \
--cc=msalter@redhat.com \
--cc=mw@semihalf.com \
--cc=okaya@codeaurora.org \
--cc=rafael@kernel.org \
--cc=robert.richter@caviumnetworks.com \
--cc=tn@semihalf.com \
--cc=wangyijing@huawei.com \
--cc=will.deacon@arm.com \
/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.