From: Arnd Bergmann <arnd@arndb.de>
To: linaro-kernel@lists.linaro.org
Cc: Liviu Dudau <Liviu.Dudau@arm.com>,
linux-pci <linux-pci@vger.kernel.org>,
Bjorn Helgaas <bhelgaas@google.com>,
Catalin Marinas <Catalin.Marinas@arm.com>,
Will Deacon <Will.Deacon@arm.com>,
"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
LKML <linux-kernel@vger.kernel.org>,
LAKML <linux-arm-kernel@lists.infradead.org>
Subject: Re: [PATCH v2 3/3] arm64: Add architecture support for PCI
Date: Thu, 27 Feb 2014 17:06:24 +0100 [thread overview]
Message-ID: <5402126.Dbh9PNPIjR@wuerfel> (raw)
In-Reply-To: <1393506599-11561-4-git-send-email-Liviu.Dudau@arm.com>
On Thursday 27 February 2014 13:09:59 Liviu Dudau wrote:
> +/*
> + * PCI address space differs from physical memory address space
> + */
> +#define PCI_DMA_BUS_IS_PHYS (0)
> +
> +extern int isa_dma_bridge_buggy;
I got curious about isa_dma_bridge_buggy: apparently this is a quirk for
some old x86 bridges. We don't have those on arm64, and we also don't have
ISA_DMA_API, so just define this to (0).
> +static inline int pci_domain_nr(struct pci_bus *bus)
> +{
> + struct pci_host_bridge *bridge = to_pci_host_bridge(bus->bridge);
> +
> + if (bridge)
> + return bridge->domain_nr;
> +
> + return 0;
> +}
> +
> +static inline int pci_proc_domain(struct pci_bus *bus)
> +{
> + return pci_domain_nr(bus);
> +}
And this one I would change to always return '1': we can deal with
domain numbers showing up in /procfs for all buses, since there is
no legacy software to worry about.
> diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
> new file mode 100644
> index 0000000..496df41
> --- /dev/null
> +++ b/arch/arm64/kernel/pci.c
> @@ -0,1 +1,126 @@
Ok, this is nice and short. Let's see if we can reduce it to nothing ;-)
> +/*
> + * Called after each bus is probed, but before its children are examined
> + */
> +void pcibios_fixup_bus(struct pci_bus *bus)
> +{
> + struct pci_dev *dev;
> + struct resource *res;
> + int i;
> +
> + if (!pci_is_root_bus(bus)) {
> + pci_read_bridge_bases(bus);
> +
> + pci_bus_for_each_resource(bus, res, i) {
> + if (!res || !res->flags || res->parent)
> + continue;
> +
> + /*
> + * If we are going to reassign everything, we can
> + * shrink the P2P resource to have zero size to
> + * save space
> + */
> + if (pci_has_flag(PCI_REASSIGN_ALL_RSRC)) {
> + res->flags |= IORESOURCE_UNSET;
> + res->start = 0;
> + res->end = -1;
> + continue;
> + }
> + }
> + }
> +
> + list_for_each_entry(dev, &bus->devices, bus_list) {
> + /* Ignore fully discovered devices */
> + if (dev->is_added)
> + continue;
> +
> + set_dev_node(&dev->dev, pcibus_to_node(dev->bus));
> +
> + /* Read default IRQs and fixup if necessary */
> + dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
> + }
> +}
> +EXPORT_SYMBOL(pcibios_fixup_bus);
Shrinking the P2P resources I suppose is optional, but everything
else is in fact needed for any DT based architecture. Could this
be turned into a generic helper function in the PCI core that we
can call from architecture code?
If you name it pci_generic_fixup_bus(), we can add a weak helper
like:
void __weak pcibios_fixup_bus(struct pci_bus *bus)
{
pci_generic_fixup_bus(bus);
}
for architectures like arm64 that don't actually need to do anything
else.
> +/*
> + * We don't have to worry about legacy ISA devices, so nothing to do here
> + */
> +resource_size_t pcibios_align_resource(void *data, const struct resource *res,
> + resource_size_t size, resource_size_t align)
> +{
> + return ALIGN(res->start, align);
> +}
> +EXPORT_SYMBOL(pcibios_align_resource);
Where did this come from? The most common implementation seems to be
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size, resource_size_t align)
{
return start;
}
EXPORT_SYMBOL(pcibios_align_resource);
if you don't have to worry about ISA devices. The ALIGN() part seems to
be handled by __find_resource() already.
I'd say that should be made the default implementation in the PCI core.
I'm also pretty sure you don't need the EXPORT_SYMBOL, since the PCI
core cannot be a loadable module (yet).
> +int pcibios_enable_device(struct pci_dev *dev, int mask)
> +{
> + return pci_enable_resources(dev, mask);
> +}
> +
> +void pcibios_fixup_bridge_ranges(struct list_head *resources)
> +{
> +}
These are clearly the right implementations, but they should be weak
functions, too.
> +#define IO_SPACE_PAGES ((IO_SPACE_LIMIT + 1) / PAGE_SIZE)
> +static DECLARE_BITMAP(pci_iospace, IO_SPACE_PAGES);
> +
> +unsigned long pci_ioremap_io(const struct resource *res, phys_addr_t phys_addr)
> +{
> + unsigned long start, len, virt_start;
> + int err;
> +
> + if (res->end > IO_SPACE_LIMIT)
> + return -EINVAL;
> +
> + /*
> + * try finding free space for the whole size first,
> + * fall back to 64K if not available
> + */
> + len = resource_size(res);
> + start = bitmap_find_next_zero_area(pci_iospace, IO_SPACE_PAGES,
> + res->start / PAGE_SIZE, len / PAGE_SIZE, 0);
> + if (start == IO_SPACE_PAGES && len > SZ_64K) {
> + len = SZ_64K;
> + start = 0;
> + start = bitmap_find_next_zero_area(pci_iospace, IO_SPACE_PAGES,
> + start, len / PAGE_SIZE, 0);
> + }
> +
> + /* no 64K area found */
> + if (start == IO_SPACE_PAGES)
> + return -ENOMEM;
> +
> + /* ioremap physical aperture to virtual aperture */
> + virt_start = start * PAGE_SIZE + (unsigned long)PCI_IOBASE;
> + err = ioremap_page_range(virt_start, virt_start + len,
> + phys_addr, __pgprot(PROT_DEVICE_nGnRE));
> + if (err)
> + return err;
> +
> + bitmap_set(pci_iospace, start, len / PAGE_SIZE);
> +
> + /* return io_offset */
> + return start * PAGE_SIZE - res->start;
> +}
Maybe this can become an optional helper function with a separate Kconfig symbol
to enable it.
Arnd
WARNING: multiple messages have this Message-ID (diff)
From: arnd@arndb.de (Arnd Bergmann)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 3/3] arm64: Add architecture support for PCI
Date: Thu, 27 Feb 2014 17:06:24 +0100 [thread overview]
Message-ID: <5402126.Dbh9PNPIjR@wuerfel> (raw)
In-Reply-To: <1393506599-11561-4-git-send-email-Liviu.Dudau@arm.com>
On Thursday 27 February 2014 13:09:59 Liviu Dudau wrote:
> +/*
> + * PCI address space differs from physical memory address space
> + */
> +#define PCI_DMA_BUS_IS_PHYS (0)
> +
> +extern int isa_dma_bridge_buggy;
I got curious about isa_dma_bridge_buggy: apparently this is a quirk for
some old x86 bridges. We don't have those on arm64, and we also don't have
ISA_DMA_API, so just define this to (0).
> +static inline int pci_domain_nr(struct pci_bus *bus)
> +{
> + struct pci_host_bridge *bridge = to_pci_host_bridge(bus->bridge);
> +
> + if (bridge)
> + return bridge->domain_nr;
> +
> + return 0;
> +}
> +
> +static inline int pci_proc_domain(struct pci_bus *bus)
> +{
> + return pci_domain_nr(bus);
> +}
And this one I would change to always return '1': we can deal with
domain numbers showing up in /procfs for all buses, since there is
no legacy software to worry about.
> diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
> new file mode 100644
> index 0000000..496df41
> --- /dev/null
> +++ b/arch/arm64/kernel/pci.c
> @@ -0,1 +1,126 @@
Ok, this is nice and short. Let's see if we can reduce it to nothing ;-)
> +/*
> + * Called after each bus is probed, but before its children are examined
> + */
> +void pcibios_fixup_bus(struct pci_bus *bus)
> +{
> + struct pci_dev *dev;
> + struct resource *res;
> + int i;
> +
> + if (!pci_is_root_bus(bus)) {
> + pci_read_bridge_bases(bus);
> +
> + pci_bus_for_each_resource(bus, res, i) {
> + if (!res || !res->flags || res->parent)
> + continue;
> +
> + /*
> + * If we are going to reassign everything, we can
> + * shrink the P2P resource to have zero size to
> + * save space
> + */
> + if (pci_has_flag(PCI_REASSIGN_ALL_RSRC)) {
> + res->flags |= IORESOURCE_UNSET;
> + res->start = 0;
> + res->end = -1;
> + continue;
> + }
> + }
> + }
> +
> + list_for_each_entry(dev, &bus->devices, bus_list) {
> + /* Ignore fully discovered devices */
> + if (dev->is_added)
> + continue;
> +
> + set_dev_node(&dev->dev, pcibus_to_node(dev->bus));
> +
> + /* Read default IRQs and fixup if necessary */
> + dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
> + }
> +}
> +EXPORT_SYMBOL(pcibios_fixup_bus);
Shrinking the P2P resources I suppose is optional, but everything
else is in fact needed for any DT based architecture. Could this
be turned into a generic helper function in the PCI core that we
can call from architecture code?
If you name it pci_generic_fixup_bus(), we can add a weak helper
like:
void __weak pcibios_fixup_bus(struct pci_bus *bus)
{
pci_generic_fixup_bus(bus);
}
for architectures like arm64 that don't actually need to do anything
else.
> +/*
> + * We don't have to worry about legacy ISA devices, so nothing to do here
> + */
> +resource_size_t pcibios_align_resource(void *data, const struct resource *res,
> + resource_size_t size, resource_size_t align)
> +{
> + return ALIGN(res->start, align);
> +}
> +EXPORT_SYMBOL(pcibios_align_resource);
Where did this come from? The most common implementation seems to be
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size, resource_size_t align)
{
return start;
}
EXPORT_SYMBOL(pcibios_align_resource);
if you don't have to worry about ISA devices. The ALIGN() part seems to
be handled by __find_resource() already.
I'd say that should be made the default implementation in the PCI core.
I'm also pretty sure you don't need the EXPORT_SYMBOL, since the PCI
core cannot be a loadable module (yet).
> +int pcibios_enable_device(struct pci_dev *dev, int mask)
> +{
> + return pci_enable_resources(dev, mask);
> +}
> +
> +void pcibios_fixup_bridge_ranges(struct list_head *resources)
> +{
> +}
These are clearly the right implementations, but they should be weak
functions, too.
> +#define IO_SPACE_PAGES ((IO_SPACE_LIMIT + 1) / PAGE_SIZE)
> +static DECLARE_BITMAP(pci_iospace, IO_SPACE_PAGES);
> +
> +unsigned long pci_ioremap_io(const struct resource *res, phys_addr_t phys_addr)
> +{
> + unsigned long start, len, virt_start;
> + int err;
> +
> + if (res->end > IO_SPACE_LIMIT)
> + return -EINVAL;
> +
> + /*
> + * try finding free space for the whole size first,
> + * fall back to 64K if not available
> + */
> + len = resource_size(res);
> + start = bitmap_find_next_zero_area(pci_iospace, IO_SPACE_PAGES,
> + res->start / PAGE_SIZE, len / PAGE_SIZE, 0);
> + if (start == IO_SPACE_PAGES && len > SZ_64K) {
> + len = SZ_64K;
> + start = 0;
> + start = bitmap_find_next_zero_area(pci_iospace, IO_SPACE_PAGES,
> + start, len / PAGE_SIZE, 0);
> + }
> +
> + /* no 64K area found */
> + if (start == IO_SPACE_PAGES)
> + return -ENOMEM;
> +
> + /* ioremap physical aperture to virtual aperture */
> + virt_start = start * PAGE_SIZE + (unsigned long)PCI_IOBASE;
> + err = ioremap_page_range(virt_start, virt_start + len,
> + phys_addr, __pgprot(PROT_DEVICE_nGnRE));
> + if (err)
> + return err;
> +
> + bitmap_set(pci_iospace, start, len / PAGE_SIZE);
> +
> + /* return io_offset */
> + return start * PAGE_SIZE - res->start;
> +}
Maybe this can become an optional helper function with a separate Kconfig symbol
to enable it.
Arnd
WARNING: multiple messages have this Message-ID (diff)
From: Arnd Bergmann <arnd@arndb.de>
To: linaro-kernel@lists.linaro.org
Cc: "devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
linux-pci <linux-pci@vger.kernel.org>,
Liviu Dudau <Liviu.Dudau@arm.com>,
LKML <linux-kernel@vger.kernel.org>,
Will Deacon <Will.Deacon@arm.com>,
Catalin Marinas <Catalin.Marinas@arm.com>,
Bjorn Helgaas <bhelgaas@google.com>,
LAKML <linux-arm-kernel@lists.infradead.org>
Subject: Re: [PATCH v2 3/3] arm64: Add architecture support for PCI
Date: Thu, 27 Feb 2014 17:06:24 +0100 [thread overview]
Message-ID: <5402126.Dbh9PNPIjR@wuerfel> (raw)
In-Reply-To: <1393506599-11561-4-git-send-email-Liviu.Dudau@arm.com>
On Thursday 27 February 2014 13:09:59 Liviu Dudau wrote:
> +/*
> + * PCI address space differs from physical memory address space
> + */
> +#define PCI_DMA_BUS_IS_PHYS (0)
> +
> +extern int isa_dma_bridge_buggy;
I got curious about isa_dma_bridge_buggy: apparently this is a quirk for
some old x86 bridges. We don't have those on arm64, and we also don't have
ISA_DMA_API, so just define this to (0).
> +static inline int pci_domain_nr(struct pci_bus *bus)
> +{
> + struct pci_host_bridge *bridge = to_pci_host_bridge(bus->bridge);
> +
> + if (bridge)
> + return bridge->domain_nr;
> +
> + return 0;
> +}
> +
> +static inline int pci_proc_domain(struct pci_bus *bus)
> +{
> + return pci_domain_nr(bus);
> +}
And this one I would change to always return '1': we can deal with
domain numbers showing up in /procfs for all buses, since there is
no legacy software to worry about.
> diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
> new file mode 100644
> index 0000000..496df41
> --- /dev/null
> +++ b/arch/arm64/kernel/pci.c
> @@ -0,1 +1,126 @@
Ok, this is nice and short. Let's see if we can reduce it to nothing ;-)
> +/*
> + * Called after each bus is probed, but before its children are examined
> + */
> +void pcibios_fixup_bus(struct pci_bus *bus)
> +{
> + struct pci_dev *dev;
> + struct resource *res;
> + int i;
> +
> + if (!pci_is_root_bus(bus)) {
> + pci_read_bridge_bases(bus);
> +
> + pci_bus_for_each_resource(bus, res, i) {
> + if (!res || !res->flags || res->parent)
> + continue;
> +
> + /*
> + * If we are going to reassign everything, we can
> + * shrink the P2P resource to have zero size to
> + * save space
> + */
> + if (pci_has_flag(PCI_REASSIGN_ALL_RSRC)) {
> + res->flags |= IORESOURCE_UNSET;
> + res->start = 0;
> + res->end = -1;
> + continue;
> + }
> + }
> + }
> +
> + list_for_each_entry(dev, &bus->devices, bus_list) {
> + /* Ignore fully discovered devices */
> + if (dev->is_added)
> + continue;
> +
> + set_dev_node(&dev->dev, pcibus_to_node(dev->bus));
> +
> + /* Read default IRQs and fixup if necessary */
> + dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
> + }
> +}
> +EXPORT_SYMBOL(pcibios_fixup_bus);
Shrinking the P2P resources I suppose is optional, but everything
else is in fact needed for any DT based architecture. Could this
be turned into a generic helper function in the PCI core that we
can call from architecture code?
If you name it pci_generic_fixup_bus(), we can add a weak helper
like:
void __weak pcibios_fixup_bus(struct pci_bus *bus)
{
pci_generic_fixup_bus(bus);
}
for architectures like arm64 that don't actually need to do anything
else.
> +/*
> + * We don't have to worry about legacy ISA devices, so nothing to do here
> + */
> +resource_size_t pcibios_align_resource(void *data, const struct resource *res,
> + resource_size_t size, resource_size_t align)
> +{
> + return ALIGN(res->start, align);
> +}
> +EXPORT_SYMBOL(pcibios_align_resource);
Where did this come from? The most common implementation seems to be
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size, resource_size_t align)
{
return start;
}
EXPORT_SYMBOL(pcibios_align_resource);
if you don't have to worry about ISA devices. The ALIGN() part seems to
be handled by __find_resource() already.
I'd say that should be made the default implementation in the PCI core.
I'm also pretty sure you don't need the EXPORT_SYMBOL, since the PCI
core cannot be a loadable module (yet).
> +int pcibios_enable_device(struct pci_dev *dev, int mask)
> +{
> + return pci_enable_resources(dev, mask);
> +}
> +
> +void pcibios_fixup_bridge_ranges(struct list_head *resources)
> +{
> +}
These are clearly the right implementations, but they should be weak
functions, too.
> +#define IO_SPACE_PAGES ((IO_SPACE_LIMIT + 1) / PAGE_SIZE)
> +static DECLARE_BITMAP(pci_iospace, IO_SPACE_PAGES);
> +
> +unsigned long pci_ioremap_io(const struct resource *res, phys_addr_t phys_addr)
> +{
> + unsigned long start, len, virt_start;
> + int err;
> +
> + if (res->end > IO_SPACE_LIMIT)
> + return -EINVAL;
> +
> + /*
> + * try finding free space for the whole size first,
> + * fall back to 64K if not available
> + */
> + len = resource_size(res);
> + start = bitmap_find_next_zero_area(pci_iospace, IO_SPACE_PAGES,
> + res->start / PAGE_SIZE, len / PAGE_SIZE, 0);
> + if (start == IO_SPACE_PAGES && len > SZ_64K) {
> + len = SZ_64K;
> + start = 0;
> + start = bitmap_find_next_zero_area(pci_iospace, IO_SPACE_PAGES,
> + start, len / PAGE_SIZE, 0);
> + }
> +
> + /* no 64K area found */
> + if (start == IO_SPACE_PAGES)
> + return -ENOMEM;
> +
> + /* ioremap physical aperture to virtual aperture */
> + virt_start = start * PAGE_SIZE + (unsigned long)PCI_IOBASE;
> + err = ioremap_page_range(virt_start, virt_start + len,
> + phys_addr, __pgprot(PROT_DEVICE_nGnRE));
> + if (err)
> + return err;
> +
> + bitmap_set(pci_iospace, start, len / PAGE_SIZE);
> +
> + /* return io_offset */
> + return start * PAGE_SIZE - res->start;
> +}
Maybe this can become an optional helper function with a separate Kconfig symbol
to enable it.
Arnd
next prev parent reply other threads:[~2014-02-27 16:07 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-02-27 13:09 [PATCH v2 0/3] [RFC] Add support for PCI in AArch64 Liviu Dudau
2014-02-27 13:09 ` Liviu Dudau
2014-02-27 13:09 ` [PATCH v2 1/3] Fix ioport_map() for !CONFIG_GENERIC_IOMAP cases Liviu Dudau
2014-02-27 13:09 ` Liviu Dudau
2014-02-27 14:09 ` Arnd Bergmann
2014-02-27 14:09 ` Arnd Bergmann
2014-02-27 13:09 ` [PATCH v2 2/3] arm64: Extend the PCI I/O space to 16MB Liviu Dudau
2014-02-27 13:09 ` Liviu Dudau
2014-02-28 15:27 ` Catalin Marinas
2014-02-28 15:27 ` Catalin Marinas
2014-02-28 15:27 ` Catalin Marinas
2014-02-27 13:09 ` [PATCH v2 3/3] arm64: Add architecture support for PCI Liviu Dudau
2014-02-27 13:09 ` Liviu Dudau
2014-02-27 13:35 ` Andrew Murray
2014-02-27 13:35 ` Andrew Murray
2014-02-27 13:35 ` Andrew Murray
2014-02-27 13:41 ` Liviu Dudau
2014-02-27 16:06 ` Arnd Bergmann [this message]
2014-02-27 16:06 ` Arnd Bergmann
2014-02-27 16:06 ` Arnd Bergmann
2014-02-27 16:48 ` Liviu Dudau
2014-02-27 16:48 ` Liviu Dudau
2014-02-27 16:48 ` Liviu Dudau
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=5402126.Dbh9PNPIjR@wuerfel \
--to=arnd@arndb.de \
--cc=Catalin.Marinas@arm.com \
--cc=Liviu.Dudau@arm.com \
--cc=Will.Deacon@arm.com \
--cc=bhelgaas@google.com \
--cc=devicetree@vger.kernel.org \
--cc=linaro-kernel@lists.linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.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.