Skip to contentSkip to conversation

ARM: tegra: Add PCIe device tree support

PATCH Superseded Thierry Reding 6 participants 79 messages Jul 26, 2012 – Sep 18, 2012

Subsystems (8)
lore
Share & tools
lore
#0 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

This patch series adds support for device tree based probing of the PCIe controller found on Tegra SoCs.

Patches 1 and 2 keep the pci_fixup_irqs() and ARM-specific pci_common_init() functions around after init. This is required to support driver probe deferral, which may cause built-in drivers to be probed after __init data has already been freed.

Patch 3 allows a driver's probe function to pass per-controller private data when calling the pci_common_init() function.

Patch 4 is trivial and has already been Acked-by: Stephen Warren before.

Patch 5 adds a flag to mark a struct resource as defining a PCI configuration space. The flag will be used subsequently to differentiate between memory-mapped I/O regions and PCI configuration space.

Patch 6 rewrites PCIe support as a driver and switches the Harmony and TrimSlice boards to add the proper platform device instead of calling the tegra_pcie_init() function. Patch 7 adds MSI support as an IRQ domain.

Patches 8 and 9 add code to support the new PCIe controller binding used by patch 10 to instantiate the controller from DT.

Thierry Reding (10):
PCI: Keep pci_fixup_irqs() around after init
ARM: pci: Keep pci_common_init() around after init
ARM: pci: Allow passing per-controller private data
ARM: tegra: Move tegra_pcie_xclk_clamp() to PMC
resource: add PCI configuration space support
ARM: tegra: Rewrite PCIe support as a driver
ARM: tegra: pcie: Add MSI support of/address: Handle #address-cells > 2 specially
of: Add of_pci_parse_ranges()
ARM: tegra: pcie: Add device tree support

 .../bindings/pci/nvidia,tegra20-pcie.txt           |   94 ++
 arch/arm/boot/dts/tegra20.dtsi                     |   62 +
 arch/arm/include/asm/mach/pci.h                    |    1 +
 arch/arm/kernel/bios32.c                           |    7 +-
 arch/arm/mach-tegra/Kconfig                        |    1 +
 arch/arm/mach-tegra/board-dt-tegra20.c             |    7 +-
 arch/arm/mach-tegra/board-harmony-pcie.c           |   30 +-
 arch/arm/mach-tegra/board-harmony.c                |    1 +
 arch/arm/mach-tegra/board-harmony.h                |    1 +
 arch/arm/mach-tegra/board-trimslice.c              |   11 +-
 arch/arm/mach-tegra/board.h                        |    2 +-
 arch/arm/mach-tegra/devices.c                      |  142 ++
 arch/arm/mach-tegra/devices.h                      |    3 +
 arch/arm/mach-tegra/include/mach/iomap.h           |    3 -
 arch/arm/mach-tegra/include/mach/irqs.h            |    5 +-
 arch/arm/mach-tegra/include/mach/pci-tegra.h       |   38 +
 arch/arm/mach-tegra/pcie.c                         | 1406 ++++++++++++++------
 arch/arm/mach-tegra/pmc.c                          |   16 +
 arch/arm/mach-tegra/pmc.h                          |    1 +
 drivers/of/address.c                               |    8 +
 drivers/of/of_pci.c                                |   84 +-
 drivers/pci/setup-irq.c                            |    4 +-
 include/linux/ioport.h                             |    2 +-
 include/linux/of_pci.h                             |    2 +
 24 files changed, 1485 insertions(+), 446 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
 create mode 100644 arch/arm/mach-tegra/include/mach/pci-tegra.h
Signature · 1 line
1.7.11.2
#1 lore raw

PATCH v3 1/10 PCI: Keep pci_fixup_irqs() around after init

When using deferred driver probing, PCI host controller drivers may actually require this function after the init stage.

---
Changes in v3:
- none

Changes in v2:
- use __devinit annotations

 drivers/pci/setup-irq.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/pci/setup-irq.c +2 -2
index eb219a1..f0bcd56 100644
@@ -18,7 +18,7 @@
 #include <linux/cache.h>
 
 
-static void __init
+static void __devinit
 pdev_fixup_irq(struct pci_dev *dev,
 	       u8 (*swizzle)(struct pci_dev *, u8 *),
 	       int (*map_irq)(const struct pci_dev *, u8, u8))
@@ -54,7 +54,7 @@ pdev_fixup_irq(struct pci_dev *dev,
 	pcibios_update_irq(dev, irq);
 }
 
-void __init
+void __devinit
 pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
 	       int (*map_irq)(const struct pci_dev *, u8, u8))
 {
Signature · 1 line
1.7.11.2
maintainer
#2 lore raw

PATCH v3 1/10 PCI: Keep pci_fixup_irqs() around after init

Quoted 2 lines · Thierry Reding

When using deferred driver probing, PCI host controller drivers may actually require this function after the init stage.

Yes, this is a bug. Actually, there's still another bug here: if we hot-add a device, we won't do pdev_fixup_irq() for it. But your change is worthwhile even without fixing that other bug.

Normally I would include this in my PCI tree since it's under drivers/pci. That would make it easier for somebody to fix the hotplug problem in this cycle. Would having it in my PCI tree make things harder for you?

Quoted 1 line
Quoted 35 lines

---
Changes in v3:
- none

Changes in v2:
- use __devinit annotations

 drivers/pci/setup-irq.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/pci/setup-irq.c +2 -3
index eb219a1..f0bcd56 100644
@@ -18,7 +18,7 @@
 #include <linux/cache.h>
 
 
-static void __init
+static void __devinit
 pdev_fixup_irq(struct pci_dev *dev,
               u8 (*swizzle)(struct pci_dev *, u8 *),
               int (*map_irq)(const struct pci_dev *, u8, u8))
@@ -54,7 +54,7 @@ pdev_fixup_irq(struct pci_dev *dev,
        pcibios_update_irq(dev, irq);
 }
 
-void __init
+void __devinit
 pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
               int (*map_irq)(const struct pci_dev *, u8, u8))
 {
--

1.7.11.2

#3 lore raw

PATCH v3 1/10 PCI: Keep pci_fixup_irqs() around after init

Quoted 5 lines · Bjorn Helgaas
Quoted 2 lines · Thierry Reding

When using deferred driver probing, PCI host controller drivers may actually require this function after the init stage.

Quoted 8 lines

Yes, this is a bug. Actually, there's still another bug here: if we hot-add a device, we won't do pdev_fixup_irq() for it. But your change is worthwhile even without fixing that other bug.

Normally I would include this in my PCI tree since it's under drivers/pci. That would make it easier for somebody to fix the hotplug problem in this cycle. Would having it in my PCI tree make things harder for you?

No, not at all.

Quoted 3 lines
Quoted 1 line

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120814/aa4196d7/attachment.sig>

maintainer
#4 lore raw

PATCH v3 1/10 PCI: Keep pci_fixup_irqs() around after init

In reply to Thierry Reding
Quoted 10 lines · Thierry Reding

When using deferred driver probing, PCI host controller drivers may actually require this function after the init stage.

---
Changes in v3:
- none

Changes in v2:
- use __devinit annotations

Your original patch removed __init completely. Here you change it to __devinit. That means we decide whether to discard the function based on whether CONFIG_HOTPLUG is supported. But I think your point is not about hotplug; it's merely that we should be able to scan a PCI bus after init-time. We ought to be able to do a late PCI scan even if hotplug is not supported.

Therefore, I'd be inclined to remove __init completely unless you have another reason for preferring __devinit.

Quoted 28 lines
 drivers/pci/setup-irq.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/pci/setup-irq.c +2 -3
index eb219a1..f0bcd56 100644
@@ -18,7 +18,7 @@
 #include <linux/cache.h>
 
 
-static void __init
+static void __devinit
 pdev_fixup_irq(struct pci_dev *dev,
               u8 (*swizzle)(struct pci_dev *, u8 *),
               int (*map_irq)(const struct pci_dev *, u8, u8))
@@ -54,7 +54,7 @@ pdev_fixup_irq(struct pci_dev *dev,
        pcibios_update_irq(dev, irq);
 }
 
-void __init
+void __devinit
 pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
               int (*map_irq)(const struct pci_dev *, u8, u8))
 {
--

1.7.11.2

#5 lore raw

PATCH v3 1/10 PCI: Keep pci_fixup_irqs() around after init

Quoted 20 lines · Bjorn Helgaas
Quoted 10 lines · Thierry Reding

When using deferred driver probing, PCI host controller drivers may actually require this function after the init stage.

---
Changes in v3:
- none

Changes in v2:
- use __devinit annotations

Your original patch removed __init completely. Here you change it to __devinit. That means we decide whether to discard the function based on whether CONFIG_HOTPLUG is supported. But I think your point is not about hotplug; it's merely that we should be able to scan a PCI bus after init-time. We ought to be able to do a late PCI scan even if hotplug is not supported.

Quoted 2 lines

Therefore, I'd be inclined to remove __init completely unless you have another reason for preferring __devinit.

I thought __devinit would resolve to nothing if HOTPLUG is defined and __init otherwise. That seemed more appropriate. However you are right that it is useful to always have it available, so I'm fine with removing the annotations altogether. Do you want me to follow up with a patch? Or can you just take the first version? I'm not sure if it still applies.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120815/74a964da/attachment-0001.sig>

maintainer Applied
#6 lore raw

PATCH v3 1/10 PCI: Keep pci_fixup_irqs() around after init

Quoted 21 lines · Thierry Reding
Quoted 20 lines · Bjorn Helgaas
Quoted 10 lines · Thierry Reding

When using deferred driver probing, PCI host controller drivers may actually require this function after the init stage.

---
Changes in v3:
- none

Changes in v2:
- use __devinit annotations

Your original patch removed __init completely. Here you change it to __devinit. That means we decide whether to discard the function based on whether CONFIG_HOTPLUG is supported. But I think your point is not about hotplug; it's merely that we should be able to scan a PCI bus after init-time. We ought to be able to do a late PCI scan even if hotplug is not supported.

Quoted 8 lines
Quoted 2 lines

Therefore, I'd be inclined to remove __init completely unless you have another reason for preferring __devinit.

I thought __devinit would resolve to nothing if HOTPLUG is defined and __init otherwise. That seemed more appropriate. However you are right that it is useful to always have it available, so I'm fine with removing the annotations altogether. Do you want me to follow up with a patch? Or can you just take the first version? I'm not sure if it still applies.

You're right about how __devinit works. It's just that I don't think hotplug is actually relevant here. We're trying to make pci_fixup_irqs() work after init, whether it's because of hotplug or simply because the arch scans host bridges after init.

I applied this to my "next" branch. Thanks!

Bjorn

#7 lore raw

PATCH v3 1/10 PCI: Keep pci_fixup_irqs() around after init

Quoted 32 lines · Bjorn Helgaas
Quoted 21 lines · Thierry Reding
Quoted 20 lines · Bjorn Helgaas
Quoted 10 lines · Thierry Reding

When using deferred driver probing, PCI host controller drivers may actually require this function after the init stage.

---
Changes in v3:
- none

Changes in v2:
- use __devinit annotations

Your original patch removed __init completely. Here you change it to __devinit. That means we decide whether to discard the function based on whether CONFIG_HOTPLUG is supported. But I think your point is not about hotplug; it's merely that we should be able to scan a PCI bus after init-time. We ought to be able to do a late PCI scan even if hotplug is not supported.

Quoted 8 lines
Quoted 2 lines

Therefore, I'd be inclined to remove __init completely unless you have another reason for preferring __devinit.

I thought __devinit would resolve to nothing if HOTPLUG is defined and __init otherwise. That seemed more appropriate. However you are right that it is useful to always have it available, so I'm fine with removing the annotations altogether. Do you want me to follow up with a patch? Or can you just take the first version? I'm not sure if it still applies.

Quoted 6 lines

You're right about how __devinit works. It's just that I don't think hotplug is actually relevant here. We're trying to make pci_fixup_irqs() work after init, whether it's because of hotplug or simply because the arch scans host bridges after init.

I applied this to my "next" branch. Thanks!

Great! Thanks. It's nice to see the patch series shrink. =)

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120815/b25725ed/attachment.sig>

#8 lore raw

PATCH v3 1/10 PCI: Keep pci_fixup_irqs() around after init

In reply to Bjorn Helgaas
Quoted 32 lines · Bjorn Helgaas
Quoted 21 lines · Thierry Reding
Quoted 20 lines · Bjorn Helgaas
Quoted 10 lines · Thierry Reding

When using deferred driver probing, PCI host controller drivers may actually require this function after the init stage.

---
Changes in v3:
- none

Changes in v2:
- use __devinit annotations

Your original patch removed __init completely. Here you change it to __devinit. That means we decide whether to discard the function based on whether CONFIG_HOTPLUG is supported. But I think your point is not about hotplug; it's merely that we should be able to scan a PCI bus after init-time. We ought to be able to do a late PCI scan even if hotplug is not supported.

Quoted 8 lines
Quoted 2 lines

Therefore, I'd be inclined to remove __init completely unless you have another reason for preferring __devinit.

I thought __devinit would resolve to nothing if HOTPLUG is defined and __init otherwise. That seemed more appropriate. However you are right that it is useful to always have it available, so I'm fine with removing the annotations altogether. Do you want me to follow up with a patch? Or can you just take the first version? I'm not sure if it still applies.

Quoted 6 lines

You're right about how __devinit works. It's just that I don't think hotplug is actually relevant here. We're trying to make pci_fixup_irqs() work after init, whether it's because of hotplug or simply because the arch scans host bridges after init.

I applied this to my "next" branch. Thanks!

Bjorn, I don't see this patch in next-20120907. Did it get dropped for some reason?

For the full history, see: http://patchwork.ozlabs.org/patch/173495/.

Thanks.

#9 lore raw

PATCH v3 1/10 PCI: Keep pci_fixup_irqs() around after init

Quoted 38 lines · Stephen Warren
Quoted 37 lines · Bjorn Helgaas
Quoted 21 lines · Thierry Reding
Quoted 20 lines · Bjorn Helgaas
Quoted 10 lines · Thierry Reding

When using deferred driver probing, PCI host controller drivers may actually require this function after the init stage.

---
Changes in v3:
- none

Changes in v2:
- use __devinit annotations

Your original patch removed __init completely. Here you change it to __devinit. That means we decide whether to discard the function based on whether CONFIG_HOTPLUG is supported. But I think your point is not about hotplug; it's merely that we should be able to scan a PCI bus after init-time. We ought to be able to do a late PCI scan even if hotplug is not supported.

Quoted 8 lines
Quoted 2 lines

Therefore, I'd be inclined to remove __init completely unless you have another reason for preferring __devinit.

I thought __devinit would resolve to nothing if HOTPLUG is defined and __init otherwise. That seemed more appropriate. However you are right that it is useful to always have it available, so I'm fine with removing the annotations altogether. Do you want me to follow up with a patch? Or can you just take the first version? I'm not sure if it still applies.

You're right about how __devinit works. It's just that I don't think hotplug is actually relevant here. We're trying to make pci_fixup_irqs() work after init, whether it's because of hotplug or simply because the arch scans host bridges after init.

Quoted 4 lines
Quoted 1 line

I applied this to my "next" branch. Thanks!

Bjorn, I don't see this patch in next-20120907. Did it get dropped for some reason?

Yes, it turns out that dropping the annotations causes lots of section mismatches on other architectures. See here[0] for the details. I think the solution to the issue would be to either remove HOTPLUG altogether and drop __devinit and __devexit annotations or update all architectures to fix these warnings. I think Bjorn and I settled on the latter because it's obviously less intrusive. I've been busy building toolchains for all the PCI architectures and I think I have all of them. I'll just need some more time to build, find and fix any remaining section mismatches.

Thierry

[0]: http://www.linux-mips.org/archives/linux-mips/2012-08/msg00250.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120907/b2a2647a/attachment.sig>

maintainer
#10 lore raw

PATCH v3 1/10 PCI: Keep pci_fixup_irqs() around after init

Quoted 44 lines · Thierry Reding
Quoted 38 lines · Stephen Warren
Quoted 37 lines · Bjorn Helgaas
Quoted 21 lines · Thierry Reding
Quoted 20 lines · Bjorn Helgaas
Quoted 10 lines · Thierry Reding

When using deferred driver probing, PCI host controller drivers may actually require this function after the init stage.

---
Changes in v3:
- none

Changes in v2:
- use __devinit annotations

Your original patch removed __init completely. Here you change it to __devinit. That means we decide whether to discard the function based on whether CONFIG_HOTPLUG is supported. But I think your point is not about hotplug; it's merely that we should be able to scan a PCI bus after init-time. We ought to be able to do a late PCI scan even if hotplug is not supported.

Quoted 8 lines
Quoted 2 lines

Therefore, I'd be inclined to remove __init completely unless you have another reason for preferring __devinit.

I thought __devinit would resolve to nothing if HOTPLUG is defined and __init otherwise. That seemed more appropriate. However you are right that it is useful to always have it available, so I'm fine with removing the annotations altogether. Do you want me to follow up with a patch? Or can you just take the first version? I'm not sure if it still applies.

You're right about how __devinit works. It's just that I don't think hotplug is actually relevant here. We're trying to make pci_fixup_irqs() work after init, whether it's because of hotplug or simply because the arch scans host bridges after init.

Quoted 4 lines
Quoted 1 line

I applied this to my "next" branch. Thanks!

Bjorn, I don't see this patch in next-20120907. Did it get dropped for some reason?

Quoted 8 lines

Yes, it turns out that dropping the annotations causes lots of section mismatches on other architectures. See here[0] for the details. I think the solution to the issue would be to either remove HOTPLUG altogether and drop __devinit and __devexit annotations or update all architectures to fix these warnings. I think Bjorn and I settled on the latter because it's obviously less intrusive. I've been busy building toolchains for all the PCI architectures and I think I have all of them. I'll just need some more time to build, find and fix any remaining section mismatches.

Greg KH is actively removing CONFIG_HOTPLUG altogether -- see
https://lkml.org/lkml/2012/9/4/489

That will make __devinit resolve to nothing in all cases, and we'll eventually remove __devinit completely. So we don't want to convert __init to __devinit; we have to remove the __init altogether. I think that means we have to update all arches first to avoid the section mismatches.

So I think Thierry is on the right track:
1) Change all arch pcibios_update_irq() implementations (and
probably a few other things) to be non-__init
2) Change pci_fixup_irqs() to be non-__init

Bjorn

#11 lore raw

PATCH v3 1/10 PCI: Keep pci_fixup_irqs() around after init

Quoted 64 lines · Bjorn Helgaas
Quoted 44 lines · Thierry Reding
Quoted 38 lines · Stephen Warren
Quoted 37 lines · Bjorn Helgaas
Quoted 21 lines · Thierry Reding
Quoted 20 lines · Bjorn Helgaas
Quoted 10 lines · Thierry Reding

When using deferred driver probing, PCI host controller drivers may actually require this function after the init stage.

---
Changes in v3:
- none

Changes in v2:
- use __devinit annotations

Your original patch removed __init completely. Here you change it to __devinit. That means we decide whether to discard the function based on whether CONFIG_HOTPLUG is supported. But I think your point is not about hotplug; it's merely that we should be able to scan a PCI bus after init-time. We ought to be able to do a late PCI scan even if hotplug is not supported.

Quoted 8 lines
Quoted 2 lines

Therefore, I'd be inclined to remove __init completely unless you have another reason for preferring __devinit.

I thought __devinit would resolve to nothing if HOTPLUG is defined and __init otherwise. That seemed more appropriate. However you are right that it is useful to always have it available, so I'm fine with removing the annotations altogether. Do you want me to follow up with a patch? Or can you just take the first version? I'm not sure if it still applies.

You're right about how __devinit works. It's just that I don't think hotplug is actually relevant here. We're trying to make pci_fixup_irqs() work after init, whether it's because of hotplug or simply because the arch scans host bridges after init.

Quoted 4 lines
Quoted 1 line

I applied this to my "next" branch. Thanks!

Bjorn, I don't see this patch in next-20120907. Did it get dropped for some reason?

Quoted 8 lines

Yes, it turns out that dropping the annotations causes lots of section mismatches on other architectures. See here[0] for the details. I think the solution to the issue would be to either remove HOTPLUG altogether and drop __devinit and __devexit annotations or update all architectures to fix these warnings. I think Bjorn and I settled on the latter because it's obviously less intrusive. I've been busy building toolchains for all the PCI architectures and I think I have all of them. I'll just need some more time to build, find and fix any remaining section mismatches.

Greg KH is actively removing CONFIG_HOTPLUG altogether -- see
https://lkml.org/lkml/2012/9/4/489

That will make __devinit resolve to nothing in all cases, and we'll eventually remove __devinit completely. So we don't want to convert __init to __devinit; we have to remove the __init altogether. I think that means we have to update all arches first to avoid the section mismatches.

Quoted 4 lines

So I think Thierry is on the right track:
1) Change all arch pcibios_update_irq() implementations (and
probably a few other things) to be non-__init
2) Change pci_fixup_irqs() to be non-__init

Okay this wasn't as much work as I had thought. It turns out that there very few dependencies other than pcibios_update_irq(). Actually none at all. In addition some of the architectures already had these annotated with __devinit. Luckily those were the ones I wasn't able to build a cross-compiler for. Note that I resolved to converting all annotations from __init to __devinit first. I'll try to find out what exactly Greg is planning to do. If it turns out that the plan is to just remove the __devinit incrementally I could just drop all of these. Otherwise maybe a better option would be to leave them in and remove them all at once when the HOTPLUG symbol is removed.

Furthermore it seems like almost all implementations are the same, so I was going to include a patch that moves the common implementation to the PCI core and make it a weak symbol so architectures would still have the possibility to override it.

The only exception to this is 64-bit SPARC, which apparently doesn't do anything in pcibios_update_irq(). I wonder if it would hurt to just use the generic implementation anyway, which just sets a byte in the configuration space. That should work regardless of architecture, right?

Unicore32 and ARM also output a debugging message and maybe it would be okay to include that with the generic implementation as well. Do you have any objections?

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120914/17565769/attachment.sig>

maintainer
#12 lore raw

PATCH v3 1/10 PCI: Keep pci_fixup_irqs() around after init

Quoted 86 lines · Thierry Reding
Quoted 64 lines · Bjorn Helgaas
Quoted 44 lines · Thierry Reding
Quoted 38 lines · Stephen Warren
Quoted 37 lines · Bjorn Helgaas
Quoted 21 lines · Thierry Reding
Quoted 20 lines · Bjorn Helgaas
Quoted 10 lines · Thierry Reding

When using deferred driver probing, PCI host controller drivers may actually require this function after the init stage.

---
Changes in v3:
- none

Changes in v2:
- use __devinit annotations

Your original patch removed __init completely. Here you change it to __devinit. That means we decide whether to discard the function based on whether CONFIG_HOTPLUG is supported. But I think your point is not about hotplug; it's merely that we should be able to scan a PCI bus after init-time. We ought to be able to do a late PCI scan even if hotplug is not supported.

Quoted 8 lines
Quoted 2 lines

Therefore, I'd be inclined to remove __init completely unless you have another reason for preferring __devinit.

I thought __devinit would resolve to nothing if HOTPLUG is defined and __init otherwise. That seemed more appropriate. However you are right that it is useful to always have it available, so I'm fine with removing the annotations altogether. Do you want me to follow up with a patch? Or can you just take the first version? I'm not sure if it still applies.

You're right about how __devinit works. It's just that I don't think hotplug is actually relevant here. We're trying to make pci_fixup_irqs() work after init, whether it's because of hotplug or simply because the arch scans host bridges after init.

Quoted 4 lines
Quoted 1 line

I applied this to my "next" branch. Thanks!

Bjorn, I don't see this patch in next-20120907. Did it get dropped for some reason?

Quoted 8 lines

Yes, it turns out that dropping the annotations causes lots of section mismatches on other architectures. See here[0] for the details. I think the solution to the issue would be to either remove HOTPLUG altogether and drop __devinit and __devexit annotations or update all architectures to fix these warnings. I think Bjorn and I settled on the latter because it's obviously less intrusive. I've been busy building toolchains for all the PCI architectures and I think I have all of them. I'll just need some more time to build, find and fix any remaining section mismatches.

Greg KH is actively removing CONFIG_HOTPLUG altogether -- see
https://lkml.org/lkml/2012/9/4/489

That will make __devinit resolve to nothing in all cases, and we'll eventually remove __devinit completely. So we don't want to convert __init to __devinit; we have to remove the __init altogether. I think that means we have to update all arches first to avoid the section mismatches.

Quoted 4 lines

So I think Thierry is on the right track:
1) Change all arch pcibios_update_irq() implementations (and
probably a few other things) to be non-__init
2) Change pci_fixup_irqs() to be non-__init

Okay this wasn't as much work as I had thought. It turns out that there very few dependencies other than pcibios_update_irq(). Actually none at all. In addition some of the architectures already had these annotated with __devinit. Luckily those were the ones I wasn't able to build a cross-compiler for. Note that I resolved to converting all annotations from __init to __devinit first. I'll try to find out what exactly Greg is planning to do. If it turns out that the plan is to just remove the __devinit incrementally I could just drop all of these. Otherwise maybe a better option would be to leave them in and remove them all at once when the HOTPLUG symbol is removed.

Furthermore it seems like almost all implementations are the same, so I was going to include a patch that moves the common implementation to the PCI core and make it a weak symbol so architectures would still have the possibility to override it.

Quoted 8 lines

The only exception to this is 64-bit SPARC, which apparently doesn't do anything in pcibios_update_irq(). I wonder if it would hurt to just use the generic implementation anyway, which just sets a byte in the configuration space. That should work regardless of architecture, right?

Unicore32 and ARM also output a debugging message and maybe it would be okay to include that with the generic implementation as well. Do you have any objections?

Sounds good to me. DaveM is really responsive -- if you propose using the generic implementation on SPARC, I bet he'd either ack it or tell you why SPARC needs to be special.

#13 lore raw

PATCH v3 2/10 ARM: pci: Keep pci_common_init() around after init

In reply to Thierry Reding

When using deferred driver probing, PCI host controller drivers may actually require this function after the init stage.

---
Changes in v3:
- none

Changes in v2:
- use __devinit annotations

 arch/arm/kernel/bios32.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm/kernel/bios32.c +2 -2
index 70dabb9..5c3dd59 100644
@@ -456,7 +456,7 @@ static int __init pcibios_init_resources(int busnr, struct pci_sys_data *sys)
 	return 0;
 }
 
-static void __init pcibios_init_hw(struct hw_pci *hw, struct list_head *head)
+static void __devinit pcibios_init_hw(struct hw_pci *hw, struct list_head *head)
 {
 	struct pci_sys_data *sys = NULL;
 	int ret;
@@ -504,7 +504,7 @@ static void __init pcibios_init_hw(struct hw_pci *hw, struct list_head *head)
 	}
 }
 
-void __init pci_common_init(struct hw_pci *hw)
+void __devinit pci_common_init(struct hw_pci *hw)
 {
 	struct pci_sys_data *sys;
 	LIST_HEAD(head);
Signature · 1 line
1.7.11.2
#14 lore raw

PATCH v3 3/10 ARM: pci: Allow passing per-controller private data

In reply to Thierry Reding

In order to allow drivers to specify private data for each controller, this commit adds a private_data field to the struct hw_pci. This field is an array of nr_controllers pointers that will be used to initialize the private_data field of the corresponding controller's pci_sys_data structure.

---
Changes in v3:
- none

Changes in v2:
- new patch

 arch/arm/include/asm/mach/pci.h | 1 +
 arch/arm/kernel/bios32.c        | 3 +++
 2 files changed, 4 insertions(+)
arch/arm/include/asm/mach/pci.h +1 -0
index 188fd58..31fab93 100644
@@ -24,6 +24,7 @@ struct hw_pci {
 #endif
 	struct pci_ops	*ops;
 	int		nr_controllers;
+	void		**private_data;
 	int		(*setup)(int nr, struct pci_sys_data *);
 	struct pci_bus *(*scan)(int nr, struct pci_sys_data *);
 	void		(*preinit)(void);
arch/arm/kernel/bios32.c +3 -0
index 5c3dd59..897b21a 100644
@@ -475,6 +475,9 @@ static void __devinit pcibios_init_hw(struct hw_pci *hw, struct list_head *head)
 		sys->map_irq = hw->map_irq;
 		INIT_LIST_HEAD(&sys->resources);
 
+		if (hw->private_data)
+			sys->private_data = hw->private_data[nr];
+
 		ret = hw->setup(nr, sys);
 
 		if (ret > 0) {
Signature · 1 line
1.7.11.2
#15 lore raw

PATCH v3 4/10 ARM: tegra: Move tegra_pcie_xclk_clamp() to PMC

In reply to Thierry Reding

The PMC code already accesses to PMC registers so it makes sense to move this function there as well. While at it, rename the function to tegra_pmc_pcie_xclk_clamp() for consistency.

---
Changes in v3:
- none

Changes in v2:
- none

 arch/arm/mach-tegra/pcie.c | 30 ++++--------------------------
 arch/arm/mach-tegra/pmc.c  | 16 ++++++++++++++++
 arch/arm/mach-tegra/pmc.h  |  1 +
 3 files changed, 21 insertions(+), 26 deletions(-)
arch/arm/mach-tegra/pcie.c +4 -26
index 576347a..efe71dd 100644
@@ -42,6 +42,7 @@
 #include <mach/powergate.h>
 
 #include "board.h"
+#include "pmc.h"
 
 /* register definitions */
 #define AFI_OFFSET	0x3800
@@ -145,17 +146,6 @@
 #define  PADS_PLL_CTL_TXCLKREF_DIV10		(0 << 20)
 #define  PADS_PLL_CTL_TXCLKREF_DIV5		(1 << 20)
 
-/* PMC access is required for PCIE xclk (un)clamping */
-#define PMC_SCRATCH42		0x144
-#define PMC_SCRATCH42_PCX_CLAMP	(1 << 0)
-
-static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
-
-#define pmc_writel(value, reg) \
-	__raw_writel(value, reg_pmc_base + (reg))
-#define pmc_readl(reg) \
-	__raw_readl(reg_pmc_base + (reg))
-
 /*
  * Tegra2 defines 1GB in the AXI address map for PCIe.
  *
@@ -647,18 +637,6 @@ static int tegra_pcie_enable_controller(void)
 	return 0;
 }
 
-static void tegra_pcie_xclk_clamp(bool clamp)
-{
-	u32 reg;
-
-	reg = pmc_readl(PMC_SCRATCH42) & ~PMC_SCRATCH42_PCX_CLAMP;
-
-	if (clamp)
-		reg |= PMC_SCRATCH42_PCX_CLAMP;
-
-	pmc_writel(reg, PMC_SCRATCH42);
-}
-
 static void tegra_pcie_power_off(void)
 {
 	tegra_periph_reset_assert(tegra_pcie.pcie_xclk);
@@ -666,7 +644,7 @@ static void tegra_pcie_power_off(void)
 	tegra_periph_reset_assert(tegra_pcie.pex_clk);
 
 	tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
-	tegra_pcie_xclk_clamp(true);
+	tegra_pmc_pcie_xclk_clamp(true);
 }
 
 static int tegra_pcie_power_regate(void)
@@ -675,7 +653,7 @@ static int tegra_pcie_power_regate(void)
 
 	tegra_pcie_power_off();
 
-	tegra_pcie_xclk_clamp(true);
+	tegra_pmc_pcie_xclk_clamp(true);
 
 	tegra_periph_reset_assert(tegra_pcie.pcie_xclk);
 	tegra_periph_reset_assert(tegra_pcie.afi_clk);
@@ -689,7 +667,7 @@ static int tegra_pcie_power_regate(void)
 
 	tegra_periph_reset_deassert(tegra_pcie.afi_clk);
 
-	tegra_pcie_xclk_clamp(false);
+	tegra_pmc_pcie_xclk_clamp(false);
 
 	clk_prepare_enable(tegra_pcie.afi_clk);
 	clk_prepare_enable(tegra_pcie.pex_clk);
arch/arm/mach-tegra/pmc.c +16 -0
index 7af6a54..399dc3a 100644
@@ -24,6 +24,10 @@
 #define PMC_CTRL		0x0
 #define PMC_CTRL_INTR_LOW	(1 << 17)
 
+/* PMC access is required for PCIE xclk (un)clamping */
+#define PMC_SCRATCH42		0x144
+#define PMC_SCRATCH42_PCX_CLAMP	(1 << 0)
+
 static inline u32 tegra_pmc_readl(u32 reg)
 {
 	return readl(IO_ADDRESS(TEGRA_PMC_BASE + reg));
@@ -74,3 +78,15 @@ void __init tegra_pmc_init(void)
 		val &= ~PMC_CTRL_INTR_LOW;
 	tegra_pmc_writel(val, PMC_CTRL);
 }
+
+void tegra_pmc_pcie_xclk_clamp(bool clamp)
+{
+	u32 reg;
+
+	reg = tegra_pmc_readl(PMC_SCRATCH42) & ~PMC_SCRATCH42_PCX_CLAMP;
+
+	if (clamp)
+		reg |= PMC_SCRATCH42_PCX_CLAMP;
+
+	tegra_pmc_writel(reg, PMC_SCRATCH42);
+}
arch/arm/mach-tegra/pmc.h +1 -0
index 8995ee4..2631c9a 100644
@@ -19,5 +19,6 @@
 #define __MACH_TEGRA_PMC_H
 
 void tegra_pmc_init(void);
+void tegra_pmc_pcie_xclk_clamp(bool clamp);
 
 #endif
Signature · 1 line
1.7.11.2
#16 lore raw

PATCH v3 5/10 resource: add PCI configuration space support

In reply to Thierry Reding

This commit adds a new flag that allows marking resources as PCI configuration space.

---
Changes in v3:
- new patch

 include/linux/ioport.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/ioport.h +1 -1
index 589e0e7..3314843 100644
@@ -102,7 +102,7 @@ struct resource {
 
 /* PCI control bits.  Shares IORESOURCE_BITS with above PCI ROM.  */
 #define IORESOURCE_PCI_FIXED		(1<<4)	/* Do not move resource */
-
+#define IORESOURCE_PCI_CS		(1<<5)	/* PCI configuration space */
 
 /* helpers to define resources */
 #define DEFINE_RES_NAMED(_start, _size, _name, _flags)			\
Signature · 1 line
1.7.11.2
maintainer
#17 lore raw

PATCH v3 5/10 resource: add PCI configuration space support

Quoted 16 lines · Thierry Reding

This commit adds a new flag that allows marking resources as PCI configuration space.

---
Changes in v3:
- new patch

 include/linux/ioport.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/ioport.h +0 -0
index 589e0e7..3314843 100644

include/linux/ioport.h struct resource { · line 105

Quoted 5 lines
include/linux/ioport.h +1 -1
@@ -102,7 +102,7 @@ struct resource {
 
 /* PCI control bits.  Shares IORESOURCE_BITS with above PCI ROM.  */
 #define IORESOURCE_PCI_FIXED           (1<<4)  /* Do not move resource */
-
+#define IORESOURCE_PCI_CS              (1<<5)  /* PCI configuration space */

What is the purpose of this? It seems that you are marking regions that we call MMCONFIG on x86, or ECAM-type regions in the language of the PCIe spec. I see that you set it in several places, but I don't see anything that ever looks for it. Do you have plans to use it in the future? If it really does correspond to MMCONFIG/ECAM, we should handle those regions consistently across all architectures.

Quoted 5 lines
include/linux/ioport.h +0 -1
 /* helpers to define resources */
 #define DEFINE_RES_NAMED(_start, _size, _name, _flags)                 \
--

1.7.11.2

#18 lore raw

PATCH v3 5/10 resource: add PCI configuration space support

Quoted 19 lines · Bjorn Helgaas
Quoted 17 lines · Thierry Reding

This commit adds a new flag that allows marking resources as PCI configuration space.

---
Changes in v3:
- new patch

 include/linux/ioport.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/ioport.h +0 -0
index 589e0e7..3314843 100644
@@ -102,7 +102,7 @@ struct resource {
 
Quoted 11 lines

include/linux/ioport.h struct resource { · line 105

Quoted 4 lines
include/linux/ioport.h +1 -1
 /* PCI control bits.  Shares IORESOURCE_BITS with above PCI ROM.  */
 #define IORESOURCE_PCI_FIXED           (1<<4)  /* Do not move resource */
-
+#define IORESOURCE_PCI_CS              (1<<5)  /* PCI configuration space */

What is the purpose of this? It seems that you are marking regions that we call MMCONFIG on x86, or ECAM-type regions in the language of the PCIe spec. I see that you set it in several places, but I don't see anything that ever looks for it. Do you have plans to use it in the future? If it really does correspond to MMCONFIG/ECAM, we should handle those regions consistently across all architectures.

The purpose is ultimately to obtain the MMCONFIG/ECAM resources assigned to a PCI host controller. I've used this in the of_pci_parse_ranges() and in the static board setup code to mark ranges as such. Perhaps IORESOURCE_ECAM or IORESOURCE_MMCONFIG might have been better names. I also just noticed that I'm not using this anywhere, but the plan was to eventually use it with platform_get_resource(). However that doesn't seem to work either because the lower bits of the flags aren't use for comparison in that function.

Any other ideas how that could be handled? Basically what I need is a way to mark a resource as an MMCONFIG/ECAM range so that it can be used to program the PCI host controller accordingly. I don't know how these are assigned on x86. I was under the impression that the MMCONFIG/ECAM space was accessed through a single single address/data register pair.

On Tegra 20 this region can be anywhere in the upper 1 GiB of the 4 GiB address space, while on Tegra 30 it can be anywhere in the lower 1 GiB, so they can be freely assigned.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120814/ab8cbdaa/attachment.sig>

maintainer
#19 lore raw

PATCH v3 5/10 resource: add PCI configuration space support

Quoted 41 lines · Thierry Reding
Quoted 19 lines · Bjorn Helgaas
Quoted 17 lines · Thierry Reding

This commit adds a new flag that allows marking resources as PCI configuration space.

---
Changes in v3:
- new patch

 include/linux/ioport.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/ioport.h +0 -0
index 589e0e7..3314843 100644
@@ -102,7 +102,7 @@ struct resource {
 
Quoted 11 lines

include/linux/ioport.h struct resource { · line 105

Quoted 4 lines
include/linux/ioport.h +1 -1
 /* PCI control bits.  Shares IORESOURCE_BITS with above PCI ROM.  */
 #define IORESOURCE_PCI_FIXED           (1<<4)  /* Do not move resource */
-
+#define IORESOURCE_PCI_CS              (1<<5)  /* PCI configuration space */

What is the purpose of this? It seems that you are marking regions that we call MMCONFIG on x86, or ECAM-type regions in the language of the PCIe spec. I see that you set it in several places, but I don't see anything that ever looks for it. Do you have plans to use it in the future? If it really does correspond to MMCONFIG/ECAM, we should handle those regions consistently across all architectures.

The purpose is ultimately to obtain the MMCONFIG/ECAM resources assigned to a PCI host controller. I've used this in the of_pci_parse_ranges() and in the static board setup code to mark ranges as such. Perhaps IORESOURCE_ECAM or IORESOURCE_MMCONFIG might have been better names. I also just noticed that I'm not using this anywhere, but the plan was to eventually use it with platform_get_resource(). However that doesn't seem to work either because the lower bits of the flags aren't use for comparison in that function.

Quoted 5 lines

Any other ideas how that could be handled? Basically what I need is a way to mark a resource as an MMCONFIG/ECAM range so that it can be used to program the PCI host controller accordingly. I don't know how these are assigned on x86. I was under the impression that the MMCONFIG/ECAM space was accessed through a single single address/data register pair.

The legacy config access mechanism (CF8h/CFCh registers described in PCI 3.0 spec sec 3.2.2.3.2) is a single address/data pair, but this is mostly x86-specific. The ECAM mechanism (described in the PCIe 3.0 spec sec 7.2.2) is not a single address/data pair; instead, each byte of config space is directly mapped into the host's MMIO space.

Here's what we do on x86 (omitting some historical grunge that complicates things):

- Discover the host bridge via a PNP0A08 device in the ACPI namespace.
- Discover the bus number range behind the bridge using a _CRS
method in the PNP0A08 device.
- Discover the ECAM space for those buses via a _CBA method in the
PNP0A08 device.
- Tell the config accessors (struct pci_ops) that the ECAM space for
buses A-B is at address X.
- Enumerate the devices behind the host bridge by calling
pci_scan_root_bus(), passing the config accessors.

It sounds like you want a way to parse the resources at one point, saving them and marking the ECAM region, then at a later point, look up the ECAM from a saved list. We don't do that on x86 because the config accessors keep an internal list of the ECAM area for each bus.

We do of course want to put this ECAM space in the IORESOURCE_MEM tree because it consumes address space and we have to make sure we don't put anything else on top of it. But we don't have any reason to describe the MMIO -> config space function in that tree. From the point of view of the rest of the system, it's just MMIO space that's consumed by the PCI host bridge, just like any other device-specific MMIO area.

Bjorn

#20 lore raw

PATCH v3 5/10 resource: add PCI configuration space support

Quoted 73 lines · Bjorn Helgaas
Quoted 41 lines · Thierry Reding
Quoted 19 lines · Bjorn Helgaas
Quoted 17 lines · Thierry Reding

This commit adds a new flag that allows marking resources as PCI configuration space.

---
Changes in v3:
- new patch

 include/linux/ioport.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/ioport.h +0 -0
index 589e0e7..3314843 100644
@@ -102,7 +102,7 @@ struct resource {
 
Quoted 11 lines

include/linux/ioport.h struct resource { · line 105

Quoted 4 lines
include/linux/ioport.h +1 -1
 /* PCI control bits.  Shares IORESOURCE_BITS with above PCI ROM.  */
 #define IORESOURCE_PCI_FIXED           (1<<4)  /* Do not move resource */
-
+#define IORESOURCE_PCI_CS              (1<<5)  /* PCI configuration space */

What is the purpose of this? It seems that you are marking regions that we call MMCONFIG on x86, or ECAM-type regions in the language of the PCIe spec. I see that you set it in several places, but I don't see anything that ever looks for it. Do you have plans to use it in the future? If it really does correspond to MMCONFIG/ECAM, we should handle those regions consistently across all architectures.

The purpose is ultimately to obtain the MMCONFIG/ECAM resources assigned to a PCI host controller. I've used this in the of_pci_parse_ranges() and in the static board setup code to mark ranges as such. Perhaps IORESOURCE_ECAM or IORESOURCE_MMCONFIG might have been better names. I also just noticed that I'm not using this anywhere, but the plan was to eventually use it with platform_get_resource(). However that doesn't seem to work either because the lower bits of the flags aren't use for comparison in that function.

Quoted 5 lines

Any other ideas how that could be handled? Basically what I need is a way to mark a resource as an MMCONFIG/ECAM range so that it can be used to program the PCI host controller accordingly. I don't know how these are assigned on x86. I was under the impression that the MMCONFIG/ECAM space was accessed through a single single address/data register pair.

The legacy config access mechanism (CF8h/CFCh registers described in PCI 3.0 spec sec 3.2.2.3.2) is a single address/data pair, but this is mostly x86-specific. The ECAM mechanism (described in the PCIe 3.0 spec sec 7.2.2) is not a single address/data pair; instead, each byte of config space is directly mapped into the host's MMIO space.

Here's what we do on x86 (omitting some historical grunge that complicates things):

- Discover the host bridge via a PNP0A08 device in the ACPI namespace.
- Discover the bus number range behind the bridge using a _CRS
method in the PNP0A08 device.
- Discover the ECAM space for those buses via a _CBA method in the
PNP0A08 device.
- Tell the config accessors (struct pci_ops) that the ECAM space for
buses A-B is at address X.
- Enumerate the devices behind the host bridge by calling
pci_scan_root_bus(), passing the config accessors.

It sounds like you want a way to parse the resources at one point, saving them and marking the ECAM region, then at a later point, look up the ECAM from a saved list. We don't do that on x86 because the config accessors keep an internal list of the ECAM area for each bus.

Quoted 7 lines

We do of course want to put this ECAM space in the IORESOURCE_MEM tree because it consumes address space and we have to make sure we don't put anything else on top of it. But we don't have any reason to describe the MMIO -> config space function in that tree. From the point of view of the rest of the system, it's just MMIO space that's consumed by the PCI host bridge, just like any other device-specific MMIO area.

What I currently do is pass the ECAM space as a resource to the PCI host bridge platform device. Regular and extended configuration spaces are given by the third and fourth resources, respectively. If I understand correctly, you're saying that nothing beyond that needs to be encoded. In other words it is enough for the PCI host bridge driver to know where to take the data from.

I'll have to see what this means for the DT binding. There are other issues that I need to think about, like for example how to pass the ECAM space from the PCI host controller to each of the two bridges via the ranges property. This no longer makes sense in the current form, as the ECAM covers the configuration spaces for devices of both bridges and cannot really be split among them.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120814/f2443c66/attachment.sig>

maintainer
#21 lore raw

PATCH v3 5/10 resource: add PCI configuration space support

Quoted 82 lines · Thierry Reding
Quoted 73 lines · Bjorn Helgaas
Quoted 41 lines · Thierry Reding
Quoted 19 lines · Bjorn Helgaas
Quoted 17 lines · Thierry Reding

This commit adds a new flag that allows marking resources as PCI configuration space.

---
Changes in v3:
- new patch

 include/linux/ioport.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/ioport.h +0 -0
index 589e0e7..3314843 100644
@@ -102,7 +102,7 @@ struct resource {
 
Quoted 11 lines

include/linux/ioport.h struct resource { · line 105

Quoted 4 lines
include/linux/ioport.h +1 -1
 /* PCI control bits.  Shares IORESOURCE_BITS with above PCI ROM.  */
 #define IORESOURCE_PCI_FIXED           (1<<4)  /* Do not move resource */
-
+#define IORESOURCE_PCI_CS              (1<<5)  /* PCI configuration space */

What is the purpose of this? It seems that you are marking regions that we call MMCONFIG on x86, or ECAM-type regions in the language of the PCIe spec. I see that you set it in several places, but I don't see anything that ever looks for it. Do you have plans to use it in the future? If it really does correspond to MMCONFIG/ECAM, we should handle those regions consistently across all architectures.

The purpose is ultimately to obtain the MMCONFIG/ECAM resources assigned to a PCI host controller. I've used this in the of_pci_parse_ranges() and in the static board setup code to mark ranges as such. Perhaps IORESOURCE_ECAM or IORESOURCE_MMCONFIG might have been better names. I also just noticed that I'm not using this anywhere, but the plan was to eventually use it with platform_get_resource(). However that doesn't seem to work either because the lower bits of the flags aren't use for comparison in that function.

Quoted 5 lines

Any other ideas how that could be handled? Basically what I need is a way to mark a resource as an MMCONFIG/ECAM range so that it can be used to program the PCI host controller accordingly. I don't know how these are assigned on x86. I was under the impression that the MMCONFIG/ECAM space was accessed through a single single address/data register pair.

The legacy config access mechanism (CF8h/CFCh registers described in PCI 3.0 spec sec 3.2.2.3.2) is a single address/data pair, but this is mostly x86-specific. The ECAM mechanism (described in the PCIe 3.0 spec sec 7.2.2) is not a single address/data pair; instead, each byte of config space is directly mapped into the host's MMIO space.

Here's what we do on x86 (omitting some historical grunge that complicates things):

- Discover the host bridge via a PNP0A08 device in the ACPI namespace.
- Discover the bus number range behind the bridge using a _CRS
method in the PNP0A08 device.
- Discover the ECAM space for those buses via a _CBA method in the
PNP0A08 device.
- Tell the config accessors (struct pci_ops) that the ECAM space for
buses A-B is at address X.
- Enumerate the devices behind the host bridge by calling
pci_scan_root_bus(), passing the config accessors.

It sounds like you want a way to parse the resources at one point, saving them and marking the ECAM region, then at a later point, look up the ECAM from a saved list. We don't do that on x86 because the config accessors keep an internal list of the ECAM area for each bus.

Quoted 7 lines

We do of course want to put this ECAM space in the IORESOURCE_MEM tree because it consumes address space and we have to make sure we don't put anything else on top of it. But we don't have any reason to describe the MMIO -> config space function in that tree. From the point of view of the rest of the system, it's just MMIO space that's consumed by the PCI host bridge, just like any other device-specific MMIO area.

Quoted 6 lines

What I currently do is pass the ECAM space as a resource to the PCI host bridge platform device. Regular and extended configuration spaces are given by the third and fourth resources, respectively. If I understand correctly, you're saying that nothing beyond that needs to be encoded. In other words it is enough for the PCI host bridge driver to know where to take the data from.

Yes, I think so.

I'd like to someday make ECAM support generic, since it's specified by the PCIe spec. The spec doesn't differentiate between PCI configuration space (offsets 0-0xff) and PCI Express *extended* configuration space (offsets 0x100-0xfff). But it sounds like Tegra might have a memory-mapped configuration mechanism that is similar to ECAM but with a different address map, since you mention two resources (third and fourth). That's not a problem, since you're doing a Tegra-specific solution right now anyway, but something to keep in the back of your mind if we ever do make a generic ECAM solution.

Quoted 6 lines

I'll have to see what this means for the DT binding. There are other issues that I need to think about, like for example how to pass the ECAM space from the PCI host controller to each of the two bridges via the ranges property. This no longer makes sense in the current form, as the ECAM covers the configuration spaces for devices of both bridges and cannot really be split among them.

We have the same situation on x86. Part of the historical grunge that I omitted is that there's a static ACPI table (MCFG) that can tell you the ECAM range for a bus number range. Often that bus number range includes several host bridges. On x86, we have a single set of ECAM config accessors (see pci_mmcfg), and they maintain a list of "bus number -> ECAM addr" mappings internally, independent of which host bridge leads to the buses.

Bjorn

#22 lore raw

PATCH v3 5/10 resource: add PCI configuration space support

Quoted 93 lines · Bjorn Helgaas
Quoted 82 lines · Thierry Reding
Quoted 73 lines · Bjorn Helgaas
Quoted 41 lines · Thierry Reding
Quoted 19 lines · Bjorn Helgaas
Quoted 17 lines · Thierry Reding

This commit adds a new flag that allows marking resources as PCI configuration space.

---
Changes in v3:
- new patch

 include/linux/ioport.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/ioport.h +0 -0
index 589e0e7..3314843 100644
@@ -102,7 +102,7 @@ struct resource {
 
Quoted 11 lines

include/linux/ioport.h struct resource { · line 105

Quoted 4 lines
include/linux/ioport.h +1 -1
 /* PCI control bits.  Shares IORESOURCE_BITS with above PCI ROM.  */
 #define IORESOURCE_PCI_FIXED           (1<<4)  /* Do not move resource */
-
+#define IORESOURCE_PCI_CS              (1<<5)  /* PCI configuration space */

What is the purpose of this? It seems that you are marking regions that we call MMCONFIG on x86, or ECAM-type regions in the language of the PCIe spec. I see that you set it in several places, but I don't see anything that ever looks for it. Do you have plans to use it in the future? If it really does correspond to MMCONFIG/ECAM, we should handle those regions consistently across all architectures.

The purpose is ultimately to obtain the MMCONFIG/ECAM resources assigned to a PCI host controller. I've used this in the of_pci_parse_ranges() and in the static board setup code to mark ranges as such. Perhaps IORESOURCE_ECAM or IORESOURCE_MMCONFIG might have been better names. I also just noticed that I'm not using this anywhere, but the plan was to eventually use it with platform_get_resource(). However that doesn't seem to work either because the lower bits of the flags aren't use for comparison in that function.

Quoted 5 lines

Any other ideas how that could be handled? Basically what I need is a way to mark a resource as an MMCONFIG/ECAM range so that it can be used to program the PCI host controller accordingly. I don't know how these are assigned on x86. I was under the impression that the MMCONFIG/ECAM space was accessed through a single single address/data register pair.

The legacy config access mechanism (CF8h/CFCh registers described in PCI 3.0 spec sec 3.2.2.3.2) is a single address/data pair, but this is mostly x86-specific. The ECAM mechanism (described in the PCIe 3.0 spec sec 7.2.2) is not a single address/data pair; instead, each byte of config space is directly mapped into the host's MMIO space.

Here's what we do on x86 (omitting some historical grunge that complicates things):

- Discover the host bridge via a PNP0A08 device in the ACPI namespace.
- Discover the bus number range behind the bridge using a _CRS
method in the PNP0A08 device.
- Discover the ECAM space for those buses via a _CBA method in the
PNP0A08 device.
- Tell the config accessors (struct pci_ops) that the ECAM space for
buses A-B is at address X.
- Enumerate the devices behind the host bridge by calling
pci_scan_root_bus(), passing the config accessors.

It sounds like you want a way to parse the resources at one point, saving them and marking the ECAM region, then at a later point, look up the ECAM from a saved list. We don't do that on x86 because the config accessors keep an internal list of the ECAM area for each bus.

Quoted 7 lines

We do of course want to put this ECAM space in the IORESOURCE_MEM tree because it consumes address space and we have to make sure we don't put anything else on top of it. But we don't have any reason to describe the MMIO -> config space function in that tree. From the point of view of the rest of the system, it's just MMIO space that's consumed by the PCI host bridge, just like any other device-specific MMIO area.

Quoted 6 lines

What I currently do is pass the ECAM space as a resource to the PCI host bridge platform device. Regular and extended configuration spaces are given by the third and fourth resources, respectively. If I understand correctly, you're saying that nothing beyond that needs to be encoded. In other words it is enough for the PCI host bridge driver to know where to take the data from.

Yes, I think so.

Quoted 9 lines

I'd like to someday make ECAM support generic, since it's specified by the PCIe spec. The spec doesn't differentiate between PCI configuration space (offsets 0-0xff) and PCI Express *extended* configuration space (offsets 0x100-0xfff). But it sounds like Tegra might have a memory-mapped configuration mechanism that is similar to ECAM but with a different address map, since you mention two resources (third and fourth). That's not a problem, since you're doing a Tegra-specific solution right now anyway, but something to keep in the back of your mind if we ever do make a generic ECAM solution.

Something that's kept me wondering is why there actually need to be two separate regions. Since the extended configuration space is a superset of the regular configuration space it should be possible to access the regular registers via the extended configuration space as well.

Stephen: Could you try to find out whether the regular configuration space translation can just be omitted if we already set up the one for the extended configuration space? In tegra_pcie_setup_translations(), BAR 0 is setup for regular configuration space (which requires a 16 MiB region), while BAR 1 is setup for the extended configuration space (requiring a full 256 MiB region). However, if I understand correctly, each of the registers that can be accessed via the BAR 0 translation can also be accessed via the BAR 1 translation. That seems like we're wasting the 16 MiB set aside for the BAR 0 mapping.

Quoted 7 lines
Quoted 6 lines

I'll have to see what this means for the DT binding. There are other issues that I need to think about, like for example how to pass the ECAM space from the PCI host controller to each of the two bridges via the ranges property. This no longer makes sense in the current form, as the ECAM covers the configuration spaces for devices of both bridges and cannot really be split among them.

Quoted 7 lines

We have the same situation on x86. Part of the historical grunge that I omitted is that there's a static ACPI table (MCFG) that can tell you the ECAM range for a bus number range. Often that bus number range includes several host bridges. On x86, we have a single set of ECAM config accessors (see pci_mmcfg), and they maintain a list of "bus number -> ECAM addr" mappings internally, independent of which host bridge leads to the buses.

That's very similar to how things work on Tegra. Configuration space accesses to the host bridges are done via their respective memory-mapped register spaces. All other accesses use either the BAR 0 or BAR 1 translations as I described above. These translations however are unique and only a single set of accessors are provided.

Given that and what I said in the other mail about the implementation of ECAM on Tegra any CS range we pass to the host bridges via the DT ranges property is actually wrong.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120815/c7b07907/attachment.sig>

#23 lore raw

PATCH v3 5/10 resource: add PCI configuration space support

On 08/15/2012 12:49 AM, Thierry Reding wrote:
...

Quoted 10 lines

Stephen: Could you try to find out whether the regular configuration space translation can just be omitted if we already set up the one for the extended configuration space? In tegra_pcie_setup_translations(), BAR 0 is setup for regular configuration space (which requires a 16 MiB region), while BAR 1 is setup for the extended configuration space (requiring a full 256 MiB region). However, if I understand correctly, each of the registers that can be accessed via the BAR 0 translation can also be accessed via the BAR 1 translation. That seems like we're wasting the 16 MiB set aside for the BAR 0 mapping.

I have confirmed that in theory, the EXTCFG space can indeed be used to access any register, making the regular config space redundant. However, using the HW this way has apparently received less validation.

#24 lore raw

PATCH v3 5/10 resource: add PCI configuration space support

Quoted 13 lines · Stephen Warren

On 08/15/2012 12:49 AM, Thierry Reding wrote:
...

Quoted 10 lines

Stephen: Could you try to find out whether the regular configuration space translation can just be omitted if we already set up the one for the extended configuration space? In tegra_pcie_setup_translations(), BAR 0 is setup for regular configuration space (which requires a 16 MiB region), while BAR 1 is setup for the extended configuration space (requiring a full 256 MiB region). However, if I understand correctly, each of the registers that can be accessed via the BAR 0 translation can also be accessed via the BAR 1 translation. That seems like we're wasting the 16 MiB set aside for the BAR 0 mapping.

Quoted 3 lines

I have confirmed that in theory, the EXTCFG space can indeed be used to access any register, making the regular config space redundant. However, using the HW this way has apparently received less validation.

Okay. I wasn't expecting anything else really. I'll give this a try next time I get my hands on some Tegra hardware. If that works maybe we should make up for the missing validation by testing this more thoroughly.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120816/f0f90297/attachment-0001.sig>

#25 lore raw

PATCH v3 6/10 ARM: tegra: Rewrite PCIe support as a driver

In reply to Thierry Reding

This commit adds a platform device driver for the PCIe controller on Tegra SOCs. Current users of the old code (TrimSlice and Harmony) are converted and now initialize and register a corresponding platform device.

---
Changes in v3:
- use devm_request_and_ioremap() and devm_clk_get()
- make root ports separate devices
- fix extended configuration space access

Changes in v2:
- use struct hw_pci's new private_data field
- fix DT initialization for TrimSlice

 arch/arm/mach-tegra/board-harmony-pcie.c     |  30 +-
 arch/arm/mach-tegra/board-harmony.c          |   1 +
 arch/arm/mach-tegra/board-harmony.h          |   1 +
 arch/arm/mach-tegra/board-trimslice.c        |  11 +-
 arch/arm/mach-tegra/board.h                  |   2 +-
 arch/arm/mach-tegra/devices.c                | 135 ++++
 arch/arm/mach-tegra/devices.h                |   3 +
 arch/arm/mach-tegra/include/mach/iomap.h     |   3 -
 arch/arm/mach-tegra/include/mach/pci-tegra.h |  38 ++
 arch/arm/mach-tegra/pcie.c                   | 926 ++++++++++++++++-----------
 10 files changed, 732 insertions(+), 418 deletions(-)
 create mode 100644 arch/arm/mach-tegra/include/mach/pci-tegra.h
arch/arm/mach-tegra/board-harmony-pcie.c +13 -17
index e8c3fda..712f3bd 100644
@@ -22,12 +22,14 @@
 
 #include <asm/mach-types.h>
 
+#include <mach/pci-tegra.h>
+
 #include "board.h"
+#include "devices.h"
 #include "board-harmony.h"
 
 #ifdef CONFIG_TEGRA_PCI
-
-int __init harmony_pcie_init(void)
+static int harmony_pcie_board_init(struct platform_device *pdev)
 {
 	struct regulator *regulator = NULL;
 	int err;
@@ -44,30 +46,24 @@ int __init harmony_pcie_init(void)
 
 	regulator_enable(regulator);
 
-	err = tegra_pcie_init(true, true);
-	if (err)
-		goto err_pcie;
-
 	return 0;
 
-err_pcie:
-	regulator_disable(regulator);
-	regulator_put(regulator);
 err_reg:
 	gpio_free(TEGRA_GPIO_EN_VDD_1V05_GPIO);
 
 	return err;
 }
 
-static int __init harmony_pcie_initcall(void)
+int __init harmony_pcie_init(void)
 {
-	if (!machine_is_harmony())
-		return 0;
+	tegra_pcie_pdata.init = harmony_pcie_board_init;
+	platform_device_register(&tegra_pcie_device);
 
-	return harmony_pcie_init();
+	return 0;
+}
+#else
+int __init harmony_pcie_init(void)
+{
+	return 0;
 }
-
-/* PCI should be initialized after I2C, mfd and regulators */
-subsys_initcall_sync(harmony_pcie_initcall);
-
 #endif
arch/arm/mach-tegra/board-harmony.c +1 -0
index e5f3352..063c7d5 100644
@@ -204,6 +204,7 @@ static void __init tegra_harmony_init(void)
 	pwm_add_table(harmony_pwm_lookup, ARRAY_SIZE(harmony_pwm_lookup));
 	harmony_i2c_init();
 	harmony_regulator_init();
+	harmony_pcie_init();
 }
 
 MACHINE_START(HARMONY, "harmony")
arch/arm/mach-tegra/board-harmony.h +1 -0
index 139d96c..afa68e2 100644
@@ -37,5 +37,6 @@
 
 void harmony_pinmux_init(void);
 int harmony_regulator_init(void);
+int harmony_pcie_init(void);
 
 #endif
arch/arm/mach-tegra/board-trimslice.c +5 -6
index 776aa95..2667fe9 100644
@@ -34,6 +34,7 @@
 #include <asm/setup.h>
 
 #include <mach/iomap.h>
+#include <mach/pci-tegra.h>
 #include <mach/sdhci.h>
 
 #include "board.h"
@@ -145,14 +146,11 @@ static __initdata struct tegra_clk_init_table trimslice_clk_init_table[] = {
 	{ NULL,		NULL,		0,		0},
 };
 
-static int __init tegra_trimslice_pci_init(void)
+static int __init trimslice_pci_init(void)
 {
-	if (!machine_is_trimslice())
-		return 0;
-
-	return tegra_pcie_init(true, true);
+	platform_device_register(&tegra_pcie_device);
+	return 0;
 }
-subsys_initcall(tegra_trimslice_pci_init);
 
 static void __init tegra_trimslice_init(void)
 {
@@ -167,6 +165,7 @@ static void __init tegra_trimslice_init(void)
 
 	trimslice_i2c_init();
 	trimslice_usb_init();
+	trimslice_pci_init();
 }
 
 MACHINE_START(TRIMSLICE, "trimslice")
arch/arm/mach-tegra/board.h +1 -1
index f88e514..3a2a7e9 100644
@@ -30,7 +30,6 @@ void __init tegra30_init_early(void);
 void __init tegra_map_common_io(void);
 void __init tegra_init_irq(void);
 void __init tegra_dt_init_irq(void);
-int __init tegra_pcie_init(bool init_port0, bool init_port1);
 
 void tegra_init_late(void);
 
@@ -56,4 +55,5 @@ static inline int harmony_pcie_init(void) { return 0; }
 void __init tegra_paz00_wifikill_init(void);
 
 extern struct sys_timer tegra_timer;
+
 #endif
arch/arm/mach-tegra/devices.c +135 -0

144 lines not on this page · raw message

arch/arm/mach-tegra/devices.h +3 -0
index f054d10..eb28671 100644
@@ -58,4 +58,7 @@ extern struct platform_device tegra_i2s_device2;
 extern struct platform_device tegra_das_device;
 extern struct platform_device tegra_pwm_device;
 
+extern struct tegra_pcie_pdata tegra_pcie_pdata;
+extern struct platform_device tegra_pcie_device;
+
 #endif
arch/arm/mach-tegra/include/mach/iomap.h +0 -3
index fee3a94..7e76da7 100644
@@ -303,9 +303,6 @@
 #define IO_APB_VIRT	IOMEM(0xFE300000)
 #define IO_APB_SIZE	SZ_1M
 
-#define TEGRA_PCIE_BASE		0x80000000
-#define TEGRA_PCIE_IO_BASE	(TEGRA_PCIE_BASE + SZ_4M)
-
 #define IO_TO_VIRT_BETWEEN(p, st, sz)	((p) >= (st) && (p) < ((st) + (sz)))
 #define IO_TO_VIRT_XLATE(p, pst, vst)	(((p) - (pst) + (vst)))
 
arch/arm/mach-tegra/include/mach/pci-tegra.h new file +38 -0
new file mode 100644
index 0000000..e6d9fc3
@@ -0,0 +1,38 @@
+/*
+ * arch/arm/mach-tegra/include/mach/tegra-pcie.h
+ *
+ * Copyright (C) 2012 Avionic Design GmbH
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 for more details.
+ */
+
+#ifndef __MACH_TEGRA_PCIE_H
+#define __MACH_TEGRA_PCIE_H
+
+#include <linux/platform_device.h>
+
+struct tegra_pcie_rp {
+	unsigned int index;
+	struct resource *resources;
+	unsigned int num_resources;
+	struct resource *ranges;
+	unsigned int num_ranges;
+	unsigned int num_lanes;
+};
+
+struct tegra_pcie_pdata {
+	int (*init)(struct platform_device *pdev);
+	int (*exit)(struct platform_device *pdev);
+
+	struct tegra_pcie_rp *ports;
+	unsigned int num_ports;
+};
+
+#endif
arch/arm/mach-tegra/pcie.c +535 -391

1,214 lines not on this page · raw message

Signature · 1 line
1.7.11.2
#26 lore raw

PATCH v3 7/10 ARM: tegra: pcie: Add MSI support

In reply to Thierry Reding

This commit adds support for message signaled interrupts to the Tegra PCIe controller. Based on code by Krishna Kishore <[email protected]>.

---
Changes in v3:
- clear interrupts before handling them
- free pages used as MSI region

Changes in v2:
- improve compile coverage by using the IS_ENABLED() macro
- move MSI-related fields to a separate structure
- free pages used for the AFI/FPCI region
- properly remove IRQ domain on module removal
- disable MSI interrupt on module removal
- use linear IRQ domain

 arch/arm/mach-tegra/Kconfig             |   1 +
 arch/arm/mach-tegra/devices.c           |   7 +
 arch/arm/mach-tegra/include/mach/irqs.h |   5 +-
 arch/arm/mach-tegra/pcie.c              | 277 +++++++++++++++++++++++++++++++-
 4 files changed, 288 insertions(+), 2 deletions(-)
arch/arm/mach-tegra/Kconfig +1 -0
index 3f6ea1e..dba0702 100644
@@ -48,6 +48,7 @@ config ARCH_TEGRA_3x_SOC
 config TEGRA_PCI
 	bool "PCI Express support"
 	depends on ARCH_TEGRA_2x_SOC
+	select ARCH_SUPPORTS_MSI
 	select PCI
 
 config TEGRA_AHB
arch/arm/mach-tegra/devices.c +7 -0
index 203af2e..308515a 100644
@@ -767,6 +767,13 @@ static struct resource tegra_pcie_resources[] = {
 		.end = INT_PCIE_INTR,
 		.flags = IORESOURCE_IRQ,
 	},
+#ifdef CONFIG_PCI_MSI
+	[5] = {
+		.start = INT_PCIE_MSI,
+		.end = INT_PCIE_MSI,
+		.flags = IORESOURCE_IRQ,
+	},
+#endif
 };
 
 static struct resource tegra_pcie_rp0_resources[] = {
arch/arm/mach-tegra/include/mach/irqs.h +4 -1
index 0a0dcac..a282524 100644
@@ -172,7 +172,10 @@
 /* Tegra30 has 8 banks of 32 GPIOs */
 #define INT_GPIO_NR			(32 * 8)
 
-#define TEGRA_NR_IRQS			(INT_GPIO_BASE + INT_GPIO_NR)
+#define INT_PCI_MSI_BASE		(INT_GPIO_BASE + INT_GPIO_NR)
+#define INT_PCI_MSI_NR			(32 * 8)
+
+#define TEGRA_NR_IRQS			(INT_PCI_MSI_BASE + INT_PCI_MSI_NR)
 
 #define INT_BOARD_BASE			TEGRA_NR_IRQS
 #define NR_BOARD_IRQS			128
arch/arm/mach-tegra/pcie.c +276 -1

329 lines not on this page · raw message

Signature · 1 line
1.7.11.2
#27 lore raw

PATCH v3 8/10 of/address: Handle #address-cells > 2 specially

In reply to Thierry Reding

When a bus specifies #address-cells > 2, of_bus_default_map() now assumes that the mapping isn't for a physical address but rather an identifier that needs to match exactly.

This is required by bindings that use multiple cells to translate a resource to the parent bus (device index, type, ...).

See here for the discussion:

	https://lists.ozlabs.org/pipermail/devicetree-discuss/2012-June/016577.html

---
Changes in v3:
- new patch

 drivers/of/address.c | 8 ++++++++
 1 file changed, 8 insertions(+)
drivers/of/address.c +8 -0
index 7e262a6..2776119 100644
@@ -69,6 +69,14 @@ static u64 of_bus_default_map(u32 *addr, const __be32 *range,
 		 (unsigned long long)cp, (unsigned long long)s,
 		 (unsigned long long)da);
 
+	/*
+	 * If the number of address cells is larger than 2 we assume the
+	 * mapping doesn't specify a physical address. Rather, the address
+	 * specifies an identifier that must match exactly.
+	 */
+	if (na > 2 && memcmp(range, addr, na * 4) != 0)
+		return OF_BAD_ADDR;
+
 	if (da < cp || da >= (cp + s))
 		return OF_BAD_ADDR;
 	return da - cp;
Signature · 1 line
1.7.11.2
#28 lore raw

PATCH v3 8/10 of/address: Handle #address-cells > 2 specially

Quoted 7 lines · Thierry Reding

When a bus specifies #address-cells > 2, of_bus_default_map() now assumes that the mapping isn't for a physical address but rather an identifier that needs to match exactly.

This is required by bindings that use multiple cells to translate a resource to the parent bus (device index, type, ...).

Quoted 6 lines

See here for the discussion:

	https://lists.ozlabs.org/pipermail/devicetree-discuss/2012-June/016577.html
Quoted 27 lines

---
Changes in v3:
- new patch

 drivers/of/address.c | 8 ++++++++
 1 file changed, 8 insertions(+)
drivers/of/address.c +8 -0
index 7e262a6..2776119 100644
@@ -69,6 +69,14 @@ static u64 of_bus_default_map(u32 *addr, const __be32 *range,
 		 (unsigned long long)cp, (unsigned long long)s,
 		 (unsigned long long)da);
 
+	/*
+	 * If the number of address cells is larger than 2 we assume the
+	 * mapping doesn't specify a physical address. Rather, the address
+	 * specifies an identifier that must match exactly.
+	 */
+	if (na > 2 && memcmp(range, addr, na * 4) != 0)
+		return OF_BAD_ADDR;
+
 	if (da < cp || da >= (cp + s))
 		return OF_BAD_ADDR;
 	return da - cp;
#29 lore raw

PATCH v3 8/10 of/address: Handle #address-cells > 2 specially

Quoted 8 lines · Rob Herring
Quoted 7 lines · Thierry Reding

When a bus specifies #address-cells > 2, of_bus_default_map() now assumes that the mapping isn't for a physical address but rather an identifier that needs to match exactly.

This is required by bindings that use multiple cells to translate a resource to the parent bus (device index, type, ...).

Quoted 8 lines
Quoted 6 lines

See here for the discussion:

	https://lists.ozlabs.org/pipermail/devicetree-discuss/2012-June/016577.html

Hi Rob,

Were you going to take this through your DT tree? I'm trying to reduce the number of patches in this series to make it more manageable and split it into smaller chunks. There are also a couple of issues that need to be resolved so I don't know if I can get the whole series into shape for 3.7.

However if you don't think this patch is useful to be applied by itself I can also carry it until the complete series is ready.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120815/88eafd00/attachment.sig>

#30 lore raw

PATCH v3 8/10 of/address: Handle #address-cells > 2 specially

Quoted 10 lines · Thierry Reding
Quoted 9 lines · Rob Herring
Quoted 8 lines · Thierry Reding

When a bus specifies #address-cells > 2, of_bus_default_map() now assumes that the mapping isn't for a physical address but rather an identifier that needs to match exactly.

This is required by bindings that use multiple cells to translate a resource to the parent bus (device index, type, ...).

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

See here for the discussion:

https://lists.ozlabs.org/pipermail/devicetree-discuss/2012-June/016577.html

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

Signed-off-by: Thierry Reding
<[email protected]>

Hi Rob,

Quoted 8 lines

Were you going to take this through your DT tree? I'm trying to reduce the number of patches in this series to make it more manageable and split it into smaller chunks. There are also a couple of issues that need to be resolved so I don't know if I can get the whole series into shape for 3.7.

However if you don't think this patch is useful to be applied by itself I can also carry it until the complete series is ready.

Rob,

Are you able to take this patch now for 3.7, or should it be held off until the Tegra PCIe driver is re-written and requires this functionality (in which case I'd expect to take this through the Tegra tree at that time).

For reference, it's at http://patchwork.ozlabs.org/patch/173497/.

Thanks.

#31 lore raw

PATCH v3 8/10 of/address: Handle #address-cells > 2 specially

Quoted 34 lines · Stephen Warren
Quoted 10 lines · Thierry Reding
Quoted 9 lines · Rob Herring
Quoted 8 lines · Thierry Reding

When a bus specifies #address-cells > 2, of_bus_default_map() now assumes that the mapping isn't for a physical address but rather an identifier that needs to match exactly.

This is required by bindings that use multiple cells to translate a resource to the parent bus (device index, type, ...).

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

See here for the discussion:

https://lists.ozlabs.org/pipermail/devicetree-discuss/2012-June/016577.html

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

Signed-off-by: Thierry Reding
<[email protected]>

Hi Rob,

Quoted 8 lines

Were you going to take this through your DT tree? I'm trying to reduce the number of patches in this series to make it more manageable and split it into smaller chunks. There are also a couple of issues that need to be resolved so I don't know if I can get the whole series into shape for 3.7.

However if you don't think this patch is useful to be applied by itself I can also carry it until the complete series is ready.

Quoted 8 lines

Rob,

Are you able to take this patch now for 3.7, or should it be held off until the Tegra PCIe driver is re-written and requires this functionality (in which case I'd expect to take this through the Tegra tree at that time).

For reference, it's at http://patchwork.ozlabs.org/patch/173497/.

Applied for 3.7.

Rob

#32 lore raw

PATCH v3 9/10 of: Add of_pci_parse_ranges()

In reply to Thierry Reding

This new function parses the ranges property of PCI device nodes into an array of struct resource elements. It is useful in multiple-port PCI host controller drivers to collect information about the ranges that it needs to forward to the respective ports.

---
Changes in v3:
- new patch

 drivers/of/of_pci.c    | 84 +++++++++++++++++++++++++++++++++++++++++++++++++-
 include/linux/of_pci.h |  2 ++
 2 files changed, 85 insertions(+), 1 deletion(-)
drivers/of/of_pci.c +83 -1
index 13e37e2..bcff301 100644
@@ -1,7 +1,8 @@
 #include <linux/kernel.h>
 #include <linux/export.h>
-#include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_pci.h>
+#include <linux/slab.h>
 #include <asm/prom.h>
 
 static inline int __of_pci_pci_compare(struct device_node *node,
@@ -40,3 +41,84 @@ struct device_node *of_pci_find_child_device(struct device_node *parent,
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(of_pci_find_child_device);
+
+struct resource *of_pci_parse_ranges(struct device_node *node,
+				     unsigned int *countp)
+{
+	unsigned int count, i = 0;
+	struct resource *ranges;
+	const __be32 *values;
+	int len, pna, np;
+
+	values = of_get_property(node, "ranges", &len);
+	if (!values)
+		return NULL;
+
+	pna = of_n_addr_cells(node);
+	np = pna + 5;
+
+	count = len / (np * sizeof(*values));
+
+	ranges = kzalloc(sizeof(*ranges) * count, GFP_KERNEL);
+	if (!ranges)
+		return NULL;
+
+	pr_debug("PCI ranges:\n");
+
+	while ((len -= np * sizeof(*values)) >= 0) {
+		u64 addr = of_translate_address(node, values + 3);
+		u64 size = of_read_number(values + 3 + pna, 2);
+		u32 type = be32_to_cpup(values);
+		const char *suffix = "";
+		struct resource range;
+
+		memset(&range, 0, sizeof(range));
+		range.start = addr;
+		range.end = addr + size - 1;
+
+		switch ((type >> 24) & 0x3) {
+		case 0:
+			range.flags = IORESOURCE_MEM | IORESOURCE_PCI_CS;
+			pr_debug("  CS  %#x-%#x\n", range.start, range.end);
+			break;
+
+		case 1:
+			range.flags = IORESOURCE_IO;
+			pr_debug("  IO  %#x-%#x\n", range.start, range.end);
+			break;
+
+		case 2:
+			range.flags = IORESOURCE_MEM;
+
+			if (type & 0x40000000) {
+				range.flags |= IORESOURCE_PREFETCH;
+				suffix = "prefetch";
+			}
+
+			pr_debug("  MEM %#x-%#x %s\n", range.start, range.end,
+				 suffix);
+			break;
+
+		case 3:
+			range.flags = IORESOURCE_MEM | IORESOURCE_MEM_64;
+
+			if (type & 0x40000000) {
+				range.flags |= IORESOURCE_PREFETCH;
+				suffix = "prefetch";
+			}
+
+			pr_debug("  MEM %#x-%#x 64-bit %s\n", range.start,
+				 range.end, suffix);
+			break;
+		}
+
+		memcpy(&ranges[i++], &range, sizeof(range));
+		values += np;
+	}
+
+	if (countp)
+		*countp = count;
+
+	return ranges;
+}
+EXPORT_SYMBOL_GPL(of_pci_parse_ranges);
include/linux/of_pci.h +2 -0
index bb115de..c0db6ea 100644
@@ -10,5 +10,7 @@ int of_irq_map_pci(const struct pci_dev *pdev, struct of_irq *out_irq);
 struct device_node;
 struct device_node *of_pci_find_child_device(struct device_node *parent,
 					     unsigned int devfn);
+struct resource *of_pci_parse_ranges(struct device_node *node,
+				     unsigned int *countp);
 
 #endif
Signature · 1 line
1.7.11.2
#33 lore raw

PATCH v3 9/10 of: Add of_pci_parse_ranges()

Quoted 4 lines · Thierry Reding

This new function parses the ranges property of PCI device nodes into an array of struct resource elements. It is useful in multiple-port PCI host controller drivers to collect information about the ranges that it needs to forward to the respective ports.

It seems to me that some of the DT PCI code in arch/powerpc/kernel/pci* like pci_process_bridge_OF_ranges() should apply for ARM as well.

Each arch defining their own pci controller structs complicates this, but I would think at least the DT parsing can be common.

Quoted 24 lines

---
Changes in v3:
- new patch

 drivers/of/of_pci.c    | 84 +++++++++++++++++++++++++++++++++++++++++++++++++-
 include/linux/of_pci.h |  2 ++
 2 files changed, 85 insertions(+), 1 deletion(-)
drivers/of/of_pci.c +2 -1
index 13e37e2..bcff301 100644
@@ -1,7 +1,8 @@
 #include <linux/kernel.h>
 #include <linux/export.h>
-#include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_pci.h>
+#include <linux/slab.h>
 #include <asm/prom.h>
 
 static inline int __of_pci_pci_compare(struct device_node *node,

drivers/of/of_pci.c struct device_node *of_pci_find_child_device(struct device_node *parent, · line 49

Quoted 9 lines
drivers/of/of_pci.c +6 -0
@@ -40,3 +41,84 @@ struct device_node *of_pci_find_child_device(struct device_node *parent,
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(of_pci_find_child_device);
+
+struct resource *of_pci_parse_ranges(struct device_node *node,
+				     unsigned int *countp)
+{
+	unsigned int count, i = 0;
+	struct resource *ranges;

I think res or pci_res would be clearer than ranges that this is a struct resource.

Quoted 14 lines
drivers/of/of_pci.c +14 -0
+	const __be32 *values;
+	int len, pna, np;
+
+	values = of_get_property(node, "ranges", &len);
+	if (!values)
+		return NULL;
+
+	pna = of_n_addr_cells(node);
+	np = pna + 5;
+
+	count = len / (np * sizeof(*values));
+
+	ranges = kzalloc(sizeof(*ranges) * count, GFP_KERNEL);
+	if (!ranges)

drivers/of/of_pci.c struct device_node *of_pci_find_child_device(struct device_node *parent, · line 73

Quoted 10 lines
drivers/of/of_pci.c +10 -0
+		return NULL;
+
+	pr_debug("PCI ranges:\n");
+
+	while ((len -= np * sizeof(*values)) >= 0) {
+		u64 addr = of_translate_address(node, values + 3);
+		u64 size = of_read_number(values + 3 + pna, 2);
+		u32 type = be32_to_cpup(values);
+		const char *suffix = "";
+		struct resource range;

Same here.

Rob

Quoted 64 lines
drivers/of/of_pci.c +51 -0
+
+		memset(&range, 0, sizeof(range));
+		range.start = addr;
+		range.end = addr + size - 1;
+
+		switch ((type >> 24) & 0x3) {
+		case 0:
+			range.flags = IORESOURCE_MEM | IORESOURCE_PCI_CS;
+			pr_debug("  CS  %#x-%#x\n", range.start, range.end);
+			break;
+
+		case 1:
+			range.flags = IORESOURCE_IO;
+			pr_debug("  IO  %#x-%#x\n", range.start, range.end);
+			break;
+
+		case 2:
+			range.flags = IORESOURCE_MEM;
+
+			if (type & 0x40000000) {
+				range.flags |= IORESOURCE_PREFETCH;
+				suffix = "prefetch";
+			}
+
+			pr_debug("  MEM %#x-%#x %s\n", range.start, range.end,
+				 suffix);
+			break;
+
+		case 3:
+			range.flags = IORESOURCE_MEM | IORESOURCE_MEM_64;
+
+			if (type & 0x40000000) {
+				range.flags |= IORESOURCE_PREFETCH;
+				suffix = "prefetch";
+			}
+
+			pr_debug("  MEM %#x-%#x 64-bit %s\n", range.start,
+				 range.end, suffix);
+			break;
+		}
+
+		memcpy(&ranges[i++], &range, sizeof(range));
+		values += np;
+	}
+
+	if (countp)
+		*countp = count;
+
+	return ranges;
+}
+EXPORT_SYMBOL_GPL(of_pci_parse_ranges);
include/linux/of_pci.h +2 -0
index bb115de..c0db6ea 100644
@@ -10,5 +10,7 @@ int of_irq_map_pci(const struct pci_dev *pdev, struct of_irq *out_irq);
 struct device_node;
 struct device_node *of_pci_find_child_device(struct device_node *parent,
 					     unsigned int devfn);
+struct resource *of_pci_parse_ranges(struct device_node *node,
+				     unsigned int *countp);
 
 #endif
#34 lore raw

PATCH v3 9/10 of: Add of_pci_parse_ranges()

Quoted 11 lines · Rob Herring
Quoted 4 lines · Thierry Reding

This new function parses the ranges property of PCI device nodes into an array of struct resource elements. It is useful in multiple-port PCI host controller drivers to collect information about the ranges that it needs to forward to the respective ports.

It seems to me that some of the DT PCI code in arch/powerpc/kernel/pci* like pci_process_bridge_OF_ranges() should apply for ARM as well.

Each arch defining their own pci controller structs complicates this, but I would think at least the DT parsing can be common.

Yes, there's quite a lot of room for refactoring. When I first started work on this there had been some discussion about whether it would make sense to move PCI controller drivers into a common location to make it easier to refactor but the consensus at the time was that this should not be done.

I still think this might be worthwhile, but I have other things that I need to finish first.

Quoted 22 lines
Quoted 22 lines

---
Changes in v3:
- new patch

 drivers/of/of_pci.c    | 84 +++++++++++++++++++++++++++++++++++++++++++++++++-
 include/linux/of_pci.h |  2 ++
 2 files changed, 85 insertions(+), 1 deletion(-)
drivers/of/of_pci.c +2 -1
index 13e37e2..bcff301 100644
@@ -1,7 +1,8 @@
 #include <linux/kernel.h>
 #include <linux/export.h>
-#include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_pci.h>
+#include <linux/slab.h>
 #include <asm/prom.h>
 
Quoted 14 lines

drivers/of/of_pci.c struct device_node *of_pci_find_child_device(struct device_node *parent, · line 49

Quoted 11 lines
drivers/of/of_pci.c +6 -0
 static inline int __of_pci_pci_compare(struct device_node *node,
@@ -40,3 +41,84 @@ struct device_node *of_pci_find_child_device(struct device_node *parent,
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(of_pci_find_child_device);
+
+struct resource *of_pci_parse_ranges(struct device_node *node,
+				     unsigned int *countp)
+{
+	unsigned int count, i = 0;
+	struct resource *ranges;

I think res or pci_res would be clearer than ranges that this is a struct resource.

"range" is the term used by the PCI specifications to denote these regions. I don't see what's wrong with using it as a variable name.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120801/7826e0d5/attachment.sig>

#35 lore raw

PATCH v3 9/10 of: Add of_pci_parse_ranges()

Quoted 12 lines · Thierry Reding
Quoted 11 lines · Rob Herring
Quoted 5 lines · Thierry Reding

This new function parses the ranges property of PCI device nodes into an array of struct resource elements. It is useful in multiple-port PCI host controller drivers to collect information about the ranges that it needs to forward to the respective ports.

It seems to me that some of the DT PCI code in arch/powerpc/kernel/pci* like pci_process_bridge_OF_ranges() should apply for ARM as well.

Quoted 8 lines
Quoted 2 lines

Each arch defining their own pci controller structs complicates this, but I would think at least the DT parsing can be common.

Yes, there's quite a lot of room for refactoring. When I first started work on this there had been some discussion about whether it would make sense to move PCI controller drivers into a common location to make it easier to refactor but the consensus at the time was that this should not be done.

In the long term, if we end up with a separate arch/aarch64/, I think we'll have to move the PCIe (and any other) drivers to a common location. Still, I imagine there is plenty of time until that's mandatory.

#36 lore raw

PATCH v3 10/10 ARM: tegra: pcie: Add device tree support

In reply to Thierry Reding

This commit adds support for instantiating the Tegra PCIe controller from a device tree.

---
Changes in v3:
- rewrite the DT binding and adapt driver correspondingly

Changes in v2:
- increase compile coverage by using the IS_ENABLED() macro
- disable node by default

 .../bindings/pci/nvidia,tegra20-pcie.txt           |  94 ++++++++++
 arch/arm/boot/dts/tegra20.dtsi                     |  62 +++++++
 arch/arm/mach-tegra/board-dt-tegra20.c             |   7 +-
 arch/arm/mach-tegra/pcie.c                         | 195 +++++++++++++++++++++
 4 files changed, 353 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt new file +94 -0
new file mode 100644
index 0000000..b181d4c
@@ -0,0 +1,94 @@
+NVIDIA Tegra PCIe controller
+
+Required properties:
+- compatible: "nvidia,tegra20-pcie"
+- reg: physical base address and length of the controller's registers
+- interrupts: the interrupt outputs of the controller
+- pex-clk-supply: supply voltage for internal reference clock
+- vdd-supply: power supply for controller (1.05V)
+- ranges: describes the translation of addresses for root ports
+- #address-cells: address representation for root ports (must be 3)
+  - cell 0 specifies the port index
+  - cell 1 denotes the address type
+      0: root port register space
+      1: PCI configuration space
+      2: PCI extended configuration space
+      3: downstream I/O
+      4: non-prefetchable memory
+      5: prefetchable memory
+  - cell 2 provides a number space that can include the size (should be 0)
+- #size-cells: size representation for root ports (must be 1)
+
+Root ports are defined as subnodes of the PCIe controller node.
+
+Required properties:
+- device_type: must be "pciex"
+- reg: address and size of the port configuration registers
+- #address-cells: must be 3
+- #size-cells: must be 2
+- ranges: sub-ranges distributed from the PCIe controller node
+- nvidia,num-lanes: number of lanes to use for this port
+
+Example:
+
+	pcie-controller {
+		compatible = "nvidia,tegra20-pcie";
+		reg = <0x80003000 0x00000800   /* PADS registers */
+		       0x80003800 0x00000200   /* AFI registers */
+		       0x81000000 0x01000000   /* configuration space */
+		       0x90000000 0x10000000>; /* extended configuration space */
+		interrupts = <0 98 0x04   /* controller interrupt */
+		              0 99 0x04>; /* MSI interrupt */
+		status = "disabled";
+
+		ranges = <0 0 0  0x80000000 0x00001000   /* root port 0 */
+			  0 1 0  0x81000000 0x00800000   /* port 0 config space */
+			  0 2 0  0x90000000 0x08000000   /* port 0 ext config space */
+			  0 3 0  0x82000000 0x00008000   /* port 0 downstream I/O */
+			  0 4 0  0xa0000000 0x08000000   /* port 0 non-prefetchable memory */
+			  0 5 0  0xb0000000 0x08000000   /* port 0 prefetchable memory */
+
+			  1 0 0  0x80001000 0x00001000   /* root port 1 */
+			  1 1 0  0x81800000 0x00800000   /* port 1 config space */
+			  1 2 0  0x98000000 0x08000000   /* port 1 ext config space */
+			  1 3 0  0x82008000 0x00008000   /* port 1 downstream I/O */
+			  1 4 0  0xa8000000 0x08000000   /* port 1 non-prefetchable memory */
+			  1 5 0  0xb8000000 0x08000000>; /* port 1 prefetchable memory */
+
+		#address-cells = <3>;
+		#size-cells = <1>;
+
+		pci at 0 {
+			device_type = "pciex";
+			reg = <0 0 0 0x1000>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+
+			ranges = <0x80000000 0 0  0 1 0  0 0x00800000   /* config space */
+				  0x90000000 0 0  0 2 0  0 0x08000000   /* ext config space */
+				  0x81000000 0 0  0 3 0  0 0x00008000   /* I/O */
+				  0x82000000 0 0  0 4 0  0 0x08000000   /* non-prefetchable memory */
+				  0xc2000000 0 0  0 5 0  0 0x08000000>; /* prefetchable memory */
+
+			nvidia,num-lanes = <2>;
+		};
+
+		pci at 1 {
+			device_type = "pciex";
+			reg = <1 0 0 0x1000>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+
+			ranges = <0x80000000 0 0  1 1 0  0 0x00800000   /* config space */
+				  0x90000000 0 0  1 2 0  0 0x08000000   /* ext config space */
+				  0x81000000 0 0  1 3 0  0 0x00008000   /* I/O */
+				  0x82000000 0 0  1 4 0  0 0x08000000   /* non-prefetchable memory */
+				  0xc2000000 0 0  1 5 0  0 0x08000000>; /* prefetchable memory */
+
+			nvidia,num-lanes = <2>;
+		};
+	};
arch/arm/boot/dts/tegra20.dtsi +62 -0

68 lines not on this page · raw message

arch/arm/mach-tegra/board-dt-tegra20.c +2 -5
index a8a05c1..caa377a 100644
@@ -40,6 +40,7 @@
 
 #include <mach/iomap.h>
 #include <mach/irqs.h>
+#include <mach/pci-tegra.h>
 
 #include "board.h"
 #include "board-harmony.h"
@@ -114,11 +115,7 @@ static void __init tegra_dt_init(void)
 #ifdef CONFIG_MACH_TRIMSLICE
 static void __init trimslice_init(void)
 {
-	int ret;
-
-	ret = tegra_pcie_init(true, true);
-	if (ret)
-		pr_err("tegra_pci_init() failed: %d\n", ret);
+	platform_device_register(&tegra_pcie_device);
 }
 #endif
 
arch/arm/mach-tegra/pcie.c +195 -0

229 lines not on this page · raw message

Signature · 1 line
1.7.11.2
#37 lore raw

PATCH v3 10/10 ARM: tegra: pcie: Add device tree support

Quoted 21 lines · Thierry Reding
arch/arm/boot/dts/tegra20.dtsi +13 -0
index a094c97..c886dff 100644
@@ -199,6 +199,68 @@
 		#size-cells = <0>;
 	};
 
+	pcie-controller {
+		compatible = "nvidia,tegra20-pcie";
+		reg = <0x80003000 0x00000800   /* PADS registers */
+		       0x80003800 0x00000200   /* AFI registers */
+		       0x81000000 0x01000000   /* configuration space */
+		       0x90000000 0x10000000>; /* extended configuration space */
+		interrupts = <0 98 0x04   /* controller interrupt */
+		              0 99 0x04>; /* MSI interrupt */
+		status = "disabled";
+
+		ranges = <0 0 0  0x80000000 0x00001000   /* root port 0 */
+			  0 1 0  0x81000000 0x00800000   /* port 0 config space */
+			  0 2 0  0x90000000 0x08000000   /* port 0 ext config space */

arch/arm/boot/dts/tegra20.dtsi line 224

Quoted 10 lines
arch/arm/boot/dts/tegra20.dtsi +10 -0
+			  0 3 0  0x82000000 0x00010000   /* port 0 downstream I/O */
+			  0 4 0  0xa0000000 0x08000000   /* port 0 non-prefetchable memory */
+			  0 5 0  0xb0000000 0x08000000   /* port 0 prefetchable memory */
+
+			  1 0 0  0x80001000 0x00001000   /* root port 1 */
+			  1 1 0  0x81800000 0x00800000   /* port 1 config space */
+			  1 2 0  0x98000000 0x08000000   /* port 1 ext config space */
+			  1 3 0  0x82010000 0x00010000   /* port 1 downstream I/O */
+			  1 4 0  0xa8000000 0x08000000   /* port 1 non-prefetchable memory */
+			  1 5 0  0xb8000000 0x08000000>; /* port 1 prefetchable memory */

I've been thinking about this some more. The translations for both the regular and extended configuration spaces are configured in the top- level PCIe controller. It is therefore wrong how they are passed to the PCI host bridges via the ranges property.

I remember Mitch saying that it should be passed down to the children because it is partitioned among them, but since the layout is compatible with ECAM, the partitioning isn't as simple as what's in the tree. In fact the partitions will be dependent on the number of devices attached to the host bridges.

Quoted 28 lines
arch/arm/boot/dts/tegra20.dtsi +28 -0
+
+		#address-cells = <3>;
+		#size-cells = <1>;
+
+		pci at 0 {
+			device_type = "pciex";
+			reg = <0 0 0 0x1000>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+
+			ranges = <0x80000000 0 0  0 1 0  0 0x00800000   /* config space */
+				  0x90000000 0 0  0 2 0  0 0x08000000   /* ext config space */
+				  0x81000000 0 0  0 3 0  0 0x00010000   /* I/O */
+				  0x82000000 0 0  0 4 0  0 0x08000000   /* non-prefetchable memory */
+				  0xc2000000 0 0  0 5 0  0 0x08000000>; /* prefetchable memory */
+
+			nvidia,num-lanes = <2>;
+		};
+
+		pci at 1 {
+			device_type = "pciex";
+			reg = <1 0 0 0x1000>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;

arch/arm/boot/dts/tegra20.dtsi line 262

Quoted 10 lines
arch/arm/boot/dts/tegra20.dtsi +10 -0
+
+			ranges = <0x80000000 0 0  1 1 0  0 0x00800000   /* config space */
+				  0x90000000 0 0  1 2 0  0 0x08000000   /* ext config space */
+				  0x81000000 0 0  1 3 0  0 0x00010000   /* I/O */
+				  0x82000000 0 0  1 4 0  0 0x08000000   /* non-prefetchable memory */
+				  0xc2000000 0 0  1 5 0  0 0x08000000>; /* prefetchable memory */
+
+			nvidia,num-lanes = <2>;
+		};
+	};

The same is true for the ranges properties of the PCI host bridge nodes. Which part of the configuration spaces maps to the children of the respective host bridge depends on the actual device hierarchy.

Would it be possible to alternatively pass the complete range to the children without further partitioning?

The driver doesn't actually care about the ranges property and only uses the values specified in the reg property of the pcie-controller node.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120814/fc1966f8/attachment-0001.sig>

maintainer
#38 lore raw

PATCH v3 10/10 ARM: tegra: pcie: Add device tree support

Quoted 38 lines · Thierry Reding
Quoted 21 lines · Thierry Reding
arch/arm/boot/dts/tegra20.dtsi +13 -0
index a094c97..c886dff 100644
@@ -199,6 +199,68 @@
              #size-cells = <0>;
      };
 
+     pcie-controller {
+             compatible = "nvidia,tegra20-pcie";
+             reg = <0x80003000 0x00000800   /* PADS registers */
+                    0x80003800 0x00000200   /* AFI registers */
+                    0x81000000 0x01000000   /* configuration space */
+                    0x90000000 0x10000000>; /* extended configuration space */
+             interrupts = <0 98 0x04   /* controller interrupt */
+                           0 99 0x04>; /* MSI interrupt */
+             status = "disabled";
+
+             ranges = <0 0 0  0x80000000 0x00001000   /* root port 0 */
+                       0 1 0  0x81000000 0x00800000   /* port 0 config space */
+                       0 2 0  0x90000000 0x08000000   /* port 0 ext config space */

arch/arm/boot/dts/tegra20.dtsi line 224

Quoted 10 lines
arch/arm/boot/dts/tegra20.dtsi +10 -0
+                       0 3 0  0x82000000 0x00010000   /* port 0 downstream I/O */
+                       0 4 0  0xa0000000 0x08000000   /* port 0 non-prefetchable memory */
+                       0 5 0  0xb0000000 0x08000000   /* port 0 prefetchable memory */
+
+                       1 0 0  0x80001000 0x00001000   /* root port 1 */
+                       1 1 0  0x81800000 0x00800000   /* port 1 config space */
+                       1 2 0  0x98000000 0x08000000   /* port 1 ext config space */
+                       1 3 0  0x82010000 0x00010000   /* port 1 downstream I/O */
+                       1 4 0  0xa8000000 0x08000000   /* port 1 non-prefetchable memory */
+                       1 5 0  0xb8000000 0x08000000>; /* port 1 prefetchable memory */

I've been thinking about this some more. The translations for both the regular and extended configuration spaces are configured in the top- level PCIe controller. It is therefore wrong how they are passed to the PCI host bridges via the ranges property.

Quoted 5 lines

I remember Mitch saying that it should be passed down to the children because it is partitioned among them, but since the layout is compatible with ECAM, the partitioning isn't as simple as what's in the tree. In fact the partitions will be dependent on the number of devices attached to the host bridges.

I don't understand this last bit about the number of devices attached to the host bridges. Logically, the host bridge has a bus number aperture that you can know up front, even before you know anything about what devices are below it. On x86, for example, the ACPI _CRS method has something like "[bus 00-7f]" in it, which means that any buses in that range are below this bridge. That doesn't tell us anything about which buses actually have devices on them, of course; it's just analogous to the secondary and subordinate bus number registers in a P2P bridge.

Quoted 50 lines
Quoted 28 lines
arch/arm/boot/dts/tegra20.dtsi +28 -0
+
+             #address-cells = <3>;
+             #size-cells = <1>;
+
+             pci at 0 {
+                     device_type = "pciex";
+                     reg = <0 0 0 0x1000>;
+                     status = "disabled";
+
+                     #address-cells = <3>;
+                     #size-cells = <2>;
+
+                     ranges = <0x80000000 0 0  0 1 0  0 0x00800000   /* config space */
+                               0x90000000 0 0  0 2 0  0 0x08000000   /* ext config space */
+                               0x81000000 0 0  0 3 0  0 0x00010000   /* I/O */
+                               0x82000000 0 0  0 4 0  0 0x08000000   /* non-prefetchable memory */
+                               0xc2000000 0 0  0 5 0  0 0x08000000>; /* prefetchable memory */
+
+                     nvidia,num-lanes = <2>;
+             };
+
+             pci at 1 {
+                     device_type = "pciex";
+                     reg = <1 0 0 0x1000>;
+                     status = "disabled";
+
+                     #address-cells = <3>;
+                     #size-cells = <2>;

arch/arm/boot/dts/tegra20.dtsi line 262

Quoted 10 lines
arch/arm/boot/dts/tegra20.dtsi +10 -0
+
+                     ranges = <0x80000000 0 0  1 1 0  0 0x00800000   /* config space */
+                               0x90000000 0 0  1 2 0  0 0x08000000   /* ext config space */
+                               0x81000000 0 0  1 3 0  0 0x00010000   /* I/O */
+                               0x82000000 0 0  1 4 0  0 0x08000000   /* non-prefetchable memory */
+                               0xc2000000 0 0  1 5 0  0 0x08000000>; /* prefetchable memory */
+
+                     nvidia,num-lanes = <2>;
+             };
+     };

The same is true for the ranges properties of the PCI host bridge nodes. Which part of the configuration spaces maps to the children of the respective host bridge depends on the actual device hierarchy.

Would it be possible to alternatively pass the complete range to the children without further partitioning?

The driver doesn't actually care about the ranges property and only uses the values specified in the reg property of the pcie-controller node.

Thierry

#39 lore raw

PATCH v3 10/10 ARM: tegra: pcie: Add device tree support

Quoted 46 lines · Bjorn Helgaas
Quoted 38 lines · Thierry Reding
Quoted 21 lines · Thierry Reding
arch/arm/boot/dts/tegra20.dtsi +13 -0
index a094c97..c886dff 100644
@@ -199,6 +199,68 @@
              #size-cells = <0>;
      };
 
+     pcie-controller {
+             compatible = "nvidia,tegra20-pcie";
+             reg = <0x80003000 0x00000800   /* PADS registers */
+                    0x80003800 0x00000200   /* AFI registers */
+                    0x81000000 0x01000000   /* configuration space */
+                    0x90000000 0x10000000>; /* extended configuration space */
+             interrupts = <0 98 0x04   /* controller interrupt */
+                           0 99 0x04>; /* MSI interrupt */
+             status = "disabled";
+
+             ranges = <0 0 0  0x80000000 0x00001000   /* root port 0 */
+                       0 1 0  0x81000000 0x00800000   /* port 0 config space */
+                       0 2 0  0x90000000 0x08000000   /* port 0 ext config space */

arch/arm/boot/dts/tegra20.dtsi line 224

Quoted 10 lines
arch/arm/boot/dts/tegra20.dtsi +10 -0
+                       0 3 0  0x82000000 0x00010000   /* port 0 downstream I/O */
+                       0 4 0  0xa0000000 0x08000000   /* port 0 non-prefetchable memory */
+                       0 5 0  0xb0000000 0x08000000   /* port 0 prefetchable memory */
+
+                       1 0 0  0x80001000 0x00001000   /* root port 1 */
+                       1 1 0  0x81800000 0x00800000   /* port 1 config space */
+                       1 2 0  0x98000000 0x08000000   /* port 1 ext config space */
+                       1 3 0  0x82010000 0x00010000   /* port 1 downstream I/O */
+                       1 4 0  0xa8000000 0x08000000   /* port 1 non-prefetchable memory */
+                       1 5 0  0xb8000000 0x08000000>; /* port 1 prefetchable memory */

I've been thinking about this some more. The translations for both the regular and extended configuration spaces are configured in the top- level PCIe controller. It is therefore wrong how they are passed to the PCI host bridges via the ranges property.

Quoted 5 lines

I remember Mitch saying that it should be passed down to the children because it is partitioned among them, but since the layout is compatible with ECAM, the partitioning isn't as simple as what's in the tree. In fact the partitions will be dependent on the number of devices attached to the host bridges.

Quoted 9 lines

I don't understand this last bit about the number of devices attached to the host bridges. Logically, the host bridge has a bus number aperture that you can know up front, even before you know anything about what devices are below it. On x86, for example, the ACPI _CRS method has something like "[bus 00-7f]" in it, which means that any buses in that range are below this bridge. That doesn't tell us anything about which buses actually have devices on them, of course; it's just analogous to the secondary and subordinate bus number registers in a P2P bridge.

That's one of the issues I still need to take care of. Currently no bus resource is attached to the individual bridges (nor the PCI controller for that matter), so the PCI core will assign them dynamically. If this range is known at boot time we could assign ECAM ranges based on the bus numbers. Standard ECAM ranges, that is. On Tegra this won't work because as Stephen mentioned in a previous mail, the bus field is not the top field in the ECAM addresses. Basically what you have is this:

	[27:24] upper 4 bits of the register address for extended
	        configuration space
	[23:16] bus number
	[15:11] device number
	[10: 8] device function
	[ 8: 0] register

So the ECAM space cannot be partitioned by bus number.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120815/97fdcb5f/attachment.sig>

maintainer
#40 lore raw

PATCH v3 10/10 ARM: tegra: pcie: Add device tree support

Quoted 57 lines · Thierry Reding
Quoted 46 lines · Bjorn Helgaas
Quoted 38 lines · Thierry Reding
Quoted 21 lines · Thierry Reding
arch/arm/boot/dts/tegra20.dtsi +13 -0
index a094c97..c886dff 100644
@@ -199,6 +199,68 @@
              #size-cells = <0>;
      };
 
+     pcie-controller {
+             compatible = "nvidia,tegra20-pcie";
+             reg = <0x80003000 0x00000800   /* PADS registers */
+                    0x80003800 0x00000200   /* AFI registers */
+                    0x81000000 0x01000000   /* configuration space */
+                    0x90000000 0x10000000>; /* extended configuration space */
+             interrupts = <0 98 0x04   /* controller interrupt */
+                           0 99 0x04>; /* MSI interrupt */
+             status = "disabled";
+
+             ranges = <0 0 0  0x80000000 0x00001000   /* root port 0 */
+                       0 1 0  0x81000000 0x00800000   /* port 0 config space */
+                       0 2 0  0x90000000 0x08000000   /* port 0 ext config space */

arch/arm/boot/dts/tegra20.dtsi line 224

Quoted 10 lines
arch/arm/boot/dts/tegra20.dtsi +10 -0
+                       0 3 0  0x82000000 0x00010000   /* port 0 downstream I/O */
+                       0 4 0  0xa0000000 0x08000000   /* port 0 non-prefetchable memory */
+                       0 5 0  0xb0000000 0x08000000   /* port 0 prefetchable memory */
+
+                       1 0 0  0x80001000 0x00001000   /* root port 1 */
+                       1 1 0  0x81800000 0x00800000   /* port 1 config space */
+                       1 2 0  0x98000000 0x08000000   /* port 1 ext config space */
+                       1 3 0  0x82010000 0x00010000   /* port 1 downstream I/O */
+                       1 4 0  0xa8000000 0x08000000   /* port 1 non-prefetchable memory */
+                       1 5 0  0xb8000000 0x08000000>; /* port 1 prefetchable memory */

I've been thinking about this some more. The translations for both the regular and extended configuration spaces are configured in the top- level PCIe controller. It is therefore wrong how they are passed to the PCI host bridges via the ranges property.

Quoted 5 lines

I remember Mitch saying that it should be passed down to the children because it is partitioned among them, but since the layout is compatible with ECAM, the partitioning isn't as simple as what's in the tree. In fact the partitions will be dependent on the number of devices attached to the host bridges.

Quoted 9 lines

I don't understand this last bit about the number of devices attached to the host bridges. Logically, the host bridge has a bus number aperture that you can know up front, even before you know anything about what devices are below it. On x86, for example, the ACPI _CRS method has something like "[bus 00-7f]" in it, which means that any buses in that range are below this bridge. That doesn't tell us anything about which buses actually have devices on them, of course; it's just analogous to the secondary and subordinate bus number registers in a P2P bridge.

Quoted 3 lines

That's one of the issues I still need to take care of. Currently no bus resource is attached to the individual bridges (nor the PCI controller for that matter), so the PCI core will assign them dynamically.

So your PCI controller driver knows how to program the controller bus number aperture? Sometimes people start by assuming that two host bridges both have [bus 00-ff] apertures, then they enumerate below the first and adjust the bus number apertures based on what they found. For example, if they found buses 00-12 behind the first bridge, they make the apertures [bus 00-12] for the first bridge and [bus 13-ff] for the second. That might be the case, depending on what firmware set up, but it seems like a dubious way to do it, and of course it precludes a lot of hot-plug scenarios.

Quoted 6 lines

If this
range is known at boot time we could assign ECAM ranges based on the bus numbers. Standard ECAM ranges, that is. On Tegra this won't work because as Stephen mentioned in a previous mail, the bus field is not the top field in the ECAM addresses. Basically what you have is this:

Quoted 8 lines
        [27:24] upper 4 bits of the register address for extended
                configuration space
        [23:16] bus number
        [15:11] device number
        [10: 8] device function
        [ 8: 0] register

So the ECAM space cannot be partitioned by bus number.

Ah, OK, so definitely not standard PCIe ECAM.

Bjorn

#41 lore raw

PATCH v3 10/10 ARM: tegra: pcie: Add device tree support

Quoted 63 lines · Bjorn Helgaas
Quoted 57 lines · Thierry Reding
Quoted 46 lines · Bjorn Helgaas
Quoted 38 lines · Thierry Reding
Quoted 21 lines · Thierry Reding
arch/arm/boot/dts/tegra20.dtsi +13 -0
index a094c97..c886dff 100644
@@ -199,6 +199,68 @@
              #size-cells = <0>;
      };
 
+     pcie-controller {
+             compatible = "nvidia,tegra20-pcie";
+             reg = <0x80003000 0x00000800   /* PADS registers */
+                    0x80003800 0x00000200   /* AFI registers */
+                    0x81000000 0x01000000   /* configuration space */
+                    0x90000000 0x10000000>; /* extended configuration space */
+             interrupts = <0 98 0x04   /* controller interrupt */
+                           0 99 0x04>; /* MSI interrupt */
+             status = "disabled";
+
+             ranges = <0 0 0  0x80000000 0x00001000   /* root port 0 */
+                       0 1 0  0x81000000 0x00800000   /* port 0 config space */
+                       0 2 0  0x90000000 0x08000000   /* port 0 ext config space */

arch/arm/boot/dts/tegra20.dtsi line 224

Quoted 10 lines
arch/arm/boot/dts/tegra20.dtsi +10 -0
+                       0 3 0  0x82000000 0x00010000   /* port 0 downstream I/O */
+                       0 4 0  0xa0000000 0x08000000   /* port 0 non-prefetchable memory */
+                       0 5 0  0xb0000000 0x08000000   /* port 0 prefetchable memory */
+
+                       1 0 0  0x80001000 0x00001000   /* root port 1 */
+                       1 1 0  0x81800000 0x00800000   /* port 1 config space */
+                       1 2 0  0x98000000 0x08000000   /* port 1 ext config space */
+                       1 3 0  0x82010000 0x00010000   /* port 1 downstream I/O */
+                       1 4 0  0xa8000000 0x08000000   /* port 1 non-prefetchable memory */
+                       1 5 0  0xb8000000 0x08000000>; /* port 1 prefetchable memory */

I've been thinking about this some more. The translations for both the regular and extended configuration spaces are configured in the top- level PCIe controller. It is therefore wrong how they are passed to the PCI host bridges via the ranges property.

Quoted 5 lines

I remember Mitch saying that it should be passed down to the children because it is partitioned among them, but since the layout is compatible with ECAM, the partitioning isn't as simple as what's in the tree. In fact the partitions will be dependent on the number of devices attached to the host bridges.

Quoted 9 lines

I don't understand this last bit about the number of devices attached to the host bridges. Logically, the host bridge has a bus number aperture that you can know up front, even before you know anything about what devices are below it. On x86, for example, the ACPI _CRS method has something like "[bus 00-7f]" in it, which means that any buses in that range are below this bridge. That doesn't tell us anything about which buses actually have devices on them, of course; it's just analogous to the secondary and subordinate bus number registers in a P2P bridge.

Quoted 3 lines

That's one of the issues I still need to take care of. Currently no bus resource is attached to the individual bridges (nor the PCI controller for that matter), so the PCI core will assign them dynamically.

Quoted 9 lines

So your PCI controller driver knows how to program the controller bus number aperture? Sometimes people start by assuming that two host bridges both have [bus 00-ff] apertures, then they enumerate below the first and adjust the bus number apertures based on what they found. For example, if they found buses 00-12 behind the first bridge, they make the apertures [bus 00-12] for the first bridge and [bus 13-ff] for the second. That might be the case, depending on what firmware set up, but it seems like a dubious way to do it, and of course it precludes a lot of hot-plug scenarios.

No, that's not what I meant. What happens is that no pre-assigned bus range is specified for either of the host bridges, so that the range 0x00-0xff will be assigned by default in pci_scan_root_bus(). If I understand correctly, what needs to be done is partition the bus range between the two bridges (equally?). That would allow hot-plug scenarios and be more in line with how other architectures do things.

I don't know if the Tegra PCIe controller supports hot-plug, though, so maybe that wouldn't even be an issue and dynamic assignment would be okay.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120815/f7da3f7e/attachment.sig>

maintainer
#42 lore raw

PATCH v3 10/10 ARM: tegra: pcie: Add device tree support

Quoted 74 lines · Thierry Reding
Quoted 63 lines · Bjorn Helgaas
Quoted 57 lines · Thierry Reding
Quoted 46 lines · Bjorn Helgaas
Quoted 38 lines · Thierry Reding
Quoted 21 lines · Thierry Reding
arch/arm/boot/dts/tegra20.dtsi +13 -0
index a094c97..c886dff 100644
@@ -199,6 +199,68 @@
              #size-cells = <0>;
      };
 
+     pcie-controller {
+             compatible = "nvidia,tegra20-pcie";
+             reg = <0x80003000 0x00000800   /* PADS registers */
+                    0x80003800 0x00000200   /* AFI registers */
+                    0x81000000 0x01000000   /* configuration space */
+                    0x90000000 0x10000000>; /* extended configuration space */
+             interrupts = <0 98 0x04   /* controller interrupt */
+                           0 99 0x04>; /* MSI interrupt */
+             status = "disabled";
+
+             ranges = <0 0 0  0x80000000 0x00001000   /* root port 0 */
+                       0 1 0  0x81000000 0x00800000   /* port 0 config space */
+                       0 2 0  0x90000000 0x08000000   /* port 0 ext config space */

arch/arm/boot/dts/tegra20.dtsi line 224

Quoted 10 lines
arch/arm/boot/dts/tegra20.dtsi +10 -0
+                       0 3 0  0x82000000 0x00010000   /* port 0 downstream I/O */
+                       0 4 0  0xa0000000 0x08000000   /* port 0 non-prefetchable memory */
+                       0 5 0  0xb0000000 0x08000000   /* port 0 prefetchable memory */
+
+                       1 0 0  0x80001000 0x00001000   /* root port 1 */
+                       1 1 0  0x81800000 0x00800000   /* port 1 config space */
+                       1 2 0  0x98000000 0x08000000   /* port 1 ext config space */
+                       1 3 0  0x82010000 0x00010000   /* port 1 downstream I/O */
+                       1 4 0  0xa8000000 0x08000000   /* port 1 non-prefetchable memory */
+                       1 5 0  0xb8000000 0x08000000>; /* port 1 prefetchable memory */

I've been thinking about this some more. The translations for both the regular and extended configuration spaces are configured in the top- level PCIe controller. It is therefore wrong how they are passed to the PCI host bridges via the ranges property.

Quoted 5 lines

I remember Mitch saying that it should be passed down to the children because it is partitioned among them, but since the layout is compatible with ECAM, the partitioning isn't as simple as what's in the tree. In fact the partitions will be dependent on the number of devices attached to the host bridges.

Quoted 9 lines

I don't understand this last bit about the number of devices attached to the host bridges. Logically, the host bridge has a bus number aperture that you can know up front, even before you know anything about what devices are below it. On x86, for example, the ACPI _CRS method has something like "[bus 00-7f]" in it, which means that any buses in that range are below this bridge. That doesn't tell us anything about which buses actually have devices on them, of course; it's just analogous to the secondary and subordinate bus number registers in a P2P bridge.

Quoted 3 lines

That's one of the issues I still need to take care of. Currently no bus resource is attached to the individual bridges (nor the PCI controller for that matter), so the PCI core will assign them dynamically.

Quoted 9 lines

So your PCI controller driver knows how to program the controller bus number aperture? Sometimes people start by assuming that two host bridges both have [bus 00-ff] apertures, then they enumerate below the first and adjust the bus number apertures based on what they found. For example, if they found buses 00-12 behind the first bridge, they make the apertures [bus 00-12] for the first bridge and [bus 13-ff] for the second. That might be the case, depending on what firmware set up, but it seems like a dubious way to do it, and of course it precludes a lot of hot-plug scenarios.

Quoted 3 lines

No, that's not what I meant. What happens is that no pre-assigned bus range is specified for either of the host bridges, so that the range 0x00-0xff will be assigned by default in pci_scan_root_bus().

My concern is about making the kernel's idea of the host bridge bus number aperture match what the hardware is doing. I'm pretty sure that the default [bus 00-ff] range assigned by pci_scan_root_bus() doesn't actually match the hardware in most cases, at least when we have multiple host bridges in the same PCI domain.

For example, if you don't supply a bus number range, pci_scan_root_bus() will assume [bus 00-ff] for both host bridges. But if you could put an analyzer on each of the root buses and then read bus 0 config space, will you see that config transaction on *both* buses? I doubt it.

You have to know at least the bus number of the root bus up front before you can even start enumerating it. The only way to learn that is by reading registers in the host bridge or by some external mechanism like ACPI or device tree. That's the beginning of the bus number aperture. The end of the aperture is similar: we can't reliably determine it by enumerating devices below the host bridge, so we have to know it up front. You can enumerate starting with the root bus number and assigning new subordinate bus numbers as necessary, but unless you know the host bridge aperture to begin with, you could inadvertently assign a new bus number that actually belongs to a different host bridge.

Bjorn

#43 lore raw

PATCH v3 10/10 ARM: tegra: pcie: Add device tree support

Quoted 92 lines · Bjorn Helgaas
Quoted 74 lines · Thierry Reding
Quoted 63 lines · Bjorn Helgaas
Quoted 57 lines · Thierry Reding
Quoted 46 lines · Bjorn Helgaas
Quoted 38 lines · Thierry Reding
Quoted 21 lines · Thierry Reding
arch/arm/boot/dts/tegra20.dtsi +13 -0
index a094c97..c886dff 100644
@@ -199,6 +199,68 @@
              #size-cells = <0>;
      };
 
+     pcie-controller {
+             compatible = "nvidia,tegra20-pcie";
+             reg = <0x80003000 0x00000800   /* PADS registers */
+                    0x80003800 0x00000200   /* AFI registers */
+                    0x81000000 0x01000000   /* configuration space */
+                    0x90000000 0x10000000>; /* extended configuration space */
+             interrupts = <0 98 0x04   /* controller interrupt */
+                           0 99 0x04>; /* MSI interrupt */
+             status = "disabled";
+
+             ranges = <0 0 0  0x80000000 0x00001000   /* root port 0 */
+                       0 1 0  0x81000000 0x00800000   /* port 0 config space */
+                       0 2 0  0x90000000 0x08000000   /* port 0 ext config space */

arch/arm/boot/dts/tegra20.dtsi line 224

Quoted 10 lines
arch/arm/boot/dts/tegra20.dtsi +10 -0
+                       0 3 0  0x82000000 0x00010000   /* port 0 downstream I/O */
+                       0 4 0  0xa0000000 0x08000000   /* port 0 non-prefetchable memory */
+                       0 5 0  0xb0000000 0x08000000   /* port 0 prefetchable memory */
+
+                       1 0 0  0x80001000 0x00001000   /* root port 1 */
+                       1 1 0  0x81800000 0x00800000   /* port 1 config space */
+                       1 2 0  0x98000000 0x08000000   /* port 1 ext config space */
+                       1 3 0  0x82010000 0x00010000   /* port 1 downstream I/O */
+                       1 4 0  0xa8000000 0x08000000   /* port 1 non-prefetchable memory */
+                       1 5 0  0xb8000000 0x08000000>; /* port 1 prefetchable memory */

I've been thinking about this some more. The translations for both the regular and extended configuration spaces are configured in the top- level PCIe controller. It is therefore wrong how they are passed to the PCI host bridges via the ranges property.

Quoted 5 lines

I remember Mitch saying that it should be passed down to the children because it is partitioned among them, but since the layout is compatible with ECAM, the partitioning isn't as simple as what's in the tree. In fact the partitions will be dependent on the number of devices attached to the host bridges.

Quoted 9 lines

I don't understand this last bit about the number of devices attached to the host bridges. Logically, the host bridge has a bus number aperture that you can know up front, even before you know anything about what devices are below it. On x86, for example, the ACPI _CRS method has something like "[bus 00-7f]" in it, which means that any buses in that range are below this bridge. That doesn't tell us anything about which buses actually have devices on them, of course; it's just analogous to the secondary and subordinate bus number registers in a P2P bridge.

Quoted 3 lines

That's one of the issues I still need to take care of. Currently no bus resource is attached to the individual bridges (nor the PCI controller for that matter), so the PCI core will assign them dynamically.

Quoted 9 lines

So your PCI controller driver knows how to program the controller bus number aperture? Sometimes people start by assuming that two host bridges both have [bus 00-ff] apertures, then they enumerate below the first and adjust the bus number apertures based on what they found. For example, if they found buses 00-12 behind the first bridge, they make the apertures [bus 00-12] for the first bridge and [bus 13-ff] for the second. That might be the case, depending on what firmware set up, but it seems like a dubious way to do it, and of course it precludes a lot of hot-plug scenarios.

Quoted 3 lines

No, that's not what I meant. What happens is that no pre-assigned bus range is specified for either of the host bridges, so that the range 0x00-0xff will be assigned by default in pci_scan_root_bus().

My concern is about making the kernel's idea of the host bridge bus number aperture match what the hardware is doing. I'm pretty sure that the default [bus 00-ff] range assigned by pci_scan_root_bus() doesn't actually match the hardware in most cases, at least when we have multiple host bridges in the same PCI domain.

For example, if you don't supply a bus number range, pci_scan_root_bus() will assume [bus 00-ff] for both host bridges. But if you could put an analyzer on each of the root buses and then read bus 0 config space, will you see that config transaction on *both* buses? I doubt it.

Quoted 11 lines

You have to know at least the bus number of the root bus up front before you can even start enumerating it. The only way to learn that is by reading registers in the host bridge or by some external mechanism like ACPI or device tree. That's the beginning of the bus number aperture. The end of the aperture is similar: we can't reliably determine it by enumerating devices below the host bridge, so we have to know it up front. You can enumerate starting with the root bus number and assigning new subordinate bus numbers as necessary, but unless you know the host bridge aperture to begin with, you could inadvertently assign a new bus number that actually belongs to a different host bridge.

Yes, that was my understanding as well. So currently I haven't seen any problems with this because I only use one of the two host bridges. But I suppose I should add code to initialize the bus number aperture properly either via platform device resources (for the non-DT case) and the device tree otherwise.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120815/fecfe7f0/attachment.sig>

#44 lore raw

PATCH v3 10/10 ARM: tegra: pcie: Add device tree support

Quoted 5 lines · Thierry Reding

Yes, that was my understanding as well. So currently I haven't seen any problems with this because I only use one of the two host bridges. But I suppose I should add code to initialize the bus number aperture properly either via platform device resources (for the non-DT case) and the device tree otherwise.

I think when we last discussed this, the assumption was that each root port has its own config space range and its own pci domain, so you don't have to worry about bus apertures because each root port can then have all 255 bus numbers. Has that turned out to be incorrect now?

Arnd

maintainer
#45 lore raw

PATCH v3 10/10 ARM: tegra: pcie: Add device tree support

Quoted 7 lines · Arnd Bergmann
Quoted 5 lines · Thierry Reding

Yes, that was my understanding as well. So currently I haven't seen any problems with this because I only use one of the two host bridges. But I suppose I should add code to initialize the bus number aperture properly either via platform device resources (for the non-DT case) and the device tree otherwise.

Quoted 5 lines

I think when we last discussed this, the assumption was that each root port has its own config space range and its own pci domain, so you don't have to worry about bus apertures because each root port can then have all 255 bus numbers. Has that turned out to be incorrect now?

If that's the case, there's no problem. I just want to be explicit about the host bridge bus number aperture because I'd like to make pci_scan_root_bus() fail if no aperture is supplied or if the aperture overlaps with something we've already seen. I don't know if that means you want to add a domain and [bus 00-ff] range in device tree, or if you want to make some device tree rule about every host bridge being in its own domain, or what.

Bjorn

#46 lore raw

PATCH v3 10/10 ARM: tegra: pcie: Add device tree support

In reply to Arnd Bergmann
Quoted 7 lines · Arnd Bergmann
Quoted 5 lines · Thierry Reding

Yes, that was my understanding as well. So currently I haven't seen any problems with this because I only use one of the two host bridges. But I suppose I should add code to initialize the bus number aperture properly either via platform device resources (for the non-DT case) and the device tree otherwise.

Quoted 5 lines

I think when we last discussed this, the assumption was that each root port has its own config space range and its own pci domain, so you don't have to worry about bus apertures because each root port can then have all 255 bus numbers. Has that turned out to be incorrect now?

At least for the config space this is incorrect. There's a single region to access the configuration space for all devices below the PCIe controller. So it is shared by both (Tegra20) or all three (Tegra30) root ports.

I'm not sure about PCI domains. Do you have any good pointers as to where I could read up on them? If they need special hardware support, then I think Tegra doesn't support them either. At least I haven't come across any mention of domains while going through the, admittedly some- what sparse on PCIe, Tegra documentation.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120816/6f0fb24f/attachment.sig>

#47 lore raw

PATCH v3 10/10 ARM: tegra: pcie: Add device tree support

Quoted 10 lines · Thierry Reding

At least for the config space this is incorrect. There's a single region to access the configuration space for all devices below the PCIe controller. So it is shared by both (Tegra20) or all three (Tegra30) root ports.

I'm not sure about PCI domains. Do you have any good pointers as to where I could read up on them? If they need special hardware support, then I think Tegra doesn't support them either. At least I haven't come across any mention of domains while going through the, admittedly some- what sparse on PCIe, Tegra documentation.

I was referring to the same thing here: if you had a separate config space for each root port, they would by definition be separate PCI domain. So you don't have them.

Arnd

#48 lore raw

PATCH v3 10/10 ARM: tegra: pcie: Add device tree support

Quoted 12 lines · Arnd Bergmann
Quoted 10 lines · Thierry Reding

At least for the config space this is incorrect. There's a single region to access the configuration space for all devices below the PCIe controller. So it is shared by both (Tegra20) or all three (Tegra30) root ports.

I'm not sure about PCI domains. Do you have any good pointers as to where I could read up on them? If they need special hardware support, then I think Tegra doesn't support them either. At least I haven't come across any mention of domains while going through the, admittedly some- what sparse on PCIe, Tegra documentation.

Quoted 3 lines

I was referring to the same thing here: if you had a separate config space for each root port, they would by definition be separate PCI domain. So you don't have them.

I see, that makes sense. Thanks for explaining.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120816/6871e1aa/attachment.sig>

#49 lore raw

PATCH v3 10/10 ARM: tegra: pcie: Add device tree support

In reply to Bjorn Helgaas
Quoted 86 lines · Bjorn Helgaas
Quoted 57 lines · Thierry Reding
Quoted 46 lines · Bjorn Helgaas
Quoted 38 lines · Thierry Reding
Quoted 21 lines · Thierry Reding
arch/arm/boot/dts/tegra20.dtsi +13 -0
index a094c97..c886dff 100644
@@ -199,6 +199,68 @@
              #size-cells = <0>;
      };
 
+     pcie-controller {
+             compatible = "nvidia,tegra20-pcie";
+             reg = <0x80003000 0x00000800   /* PADS registers */
+                    0x80003800 0x00000200   /* AFI registers */
+                    0x81000000 0x01000000   /* configuration space */
+                    0x90000000 0x10000000>; /* extended configuration space */
+             interrupts = <0 98 0x04   /* controller interrupt */
+                           0 99 0x04>; /* MSI interrupt */
+             status = "disabled";
+
+             ranges = <0 0 0  0x80000000 0x00001000   /* root port 0 */
+                       0 1 0  0x81000000 0x00800000   /* port 0 config space */
+                       0 2 0  0x90000000 0x08000000   /* port 0 ext config space */

arch/arm/boot/dts/tegra20.dtsi line 224

Quoted 10 lines
arch/arm/boot/dts/tegra20.dtsi +10 -0
+                       0 3 0  0x82000000 0x00010000   /* port 0 downstream I/O */
+                       0 4 0  0xa0000000 0x08000000   /* port 0 non-prefetchable memory */
+                       0 5 0  0xb0000000 0x08000000   /* port 0 prefetchable memory */
+
+                       1 0 0  0x80001000 0x00001000   /* root port 1 */
+                       1 1 0  0x81800000 0x00800000   /* port 1 config space */
+                       1 2 0  0x98000000 0x08000000   /* port 1 ext config space */
+                       1 3 0  0x82010000 0x00010000   /* port 1 downstream I/O */
+                       1 4 0  0xa8000000 0x08000000   /* port 1 non-prefetchable memory */
+                       1 5 0  0xb8000000 0x08000000>; /* port 1 prefetchable memory */

I've been thinking about this some more. The translations for both the regular and extended configuration spaces are configured in the top- level PCIe controller. It is therefore wrong how they are passed to the PCI host bridges via the ranges property.

Quoted 5 lines

I remember Mitch saying that it should be passed down to the children because it is partitioned among them, but since the layout is compatible with ECAM, the partitioning isn't as simple as what's in the tree. In fact the partitions will be dependent on the number of devices attached to the host bridges.

Quoted 9 lines

I don't understand this last bit about the number of devices attached to the host bridges. Logically, the host bridge has a bus number aperture that you can know up front, even before you know anything about what devices are below it. On x86, for example, the ACPI _CRS method has something like "[bus 00-7f]" in it, which means that any buses in that range are below this bridge. That doesn't tell us anything about which buses actually have devices on them, of course; it's just analogous to the secondary and subordinate bus number registers in a P2P bridge.

Quoted 3 lines

That's one of the issues I still need to take care of. Currently no bus resource is attached to the individual bridges (nor the PCI controller for that matter), so the PCI core will assign them dynamically.

So your PCI controller driver knows how to program the controller bus number aperture? Sometimes people start by assuming that two host bridges both have [bus 00-ff] apertures, then they enumerate below the first and adjust the bus number apertures based on what they found. For example, if they found buses 00-12 behind the first bridge, they make the apertures [bus 00-12] for the first bridge and [bus 13-ff] for the second. That might be the case, depending on what firmware set up, but it seems like a dubious way to do it, and of course it precludes a lot of hot-plug scenarios.

Quoted 13 lines

If this
range is known at boot time we could assign ECAM ranges based on the bus numbers. Standard ECAM ranges, that is. On Tegra this won't work because as Stephen mentioned in a previous mail, the bus field is not the top field in the ECAM addresses. Basically what you have is this:

        [27:24] upper 4 bits of the register address for extended
                configuration space
        [23:16] bus number
        [15:11] device number
        [10: 8] device function
        [ 8: 0] register
Quoted 3 lines
Quoted 1 line

So the ECAM space cannot be partitioned by bus number.

Ah, OK, so definitely not standard PCIe ECAM.

I had an idea about how we could maybe implement a generic ECAM mechanism that provides for this kind of mapping as well. Basically, every mechanism that can be covered by such an implementation would in one way or another specify the above five fields, so how about designing it in a way that the driver could define the fields that encode the information, so for Tegra, something along these lines:

	struct pci_ecam_map pci_ecam_tegra = {
		.register = {  0,  7 },
		.extended = { 24, 27 },
		.function = {  8, 10 },
		.device   = { 11, 15 },
		.bus      = { 16, 23 },
	}

For standard ECAM, something like this:

	struct pci_ecam_map pci_ecam_standard = {
		.register = {  0,  7 },
		.extended = {  8, 11 },
		.function = { 12, 14 },
		.device   = { 15, 19 },
		.bus      = { 20, 27 },
	};

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120816/5b473c13/attachment.sig>

#50 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

In reply to Thierry Reding
Quoted 2 lines · Thierry Reding

This patch series adds support for device tree based probing of the PCIe controller found on Tegra SoCs.

Thierry,

I think one thing that would help here would be to split up this series into one per subsystem, and to get all the dependencies merged by the respective maintainers. Preferably, each subsystem would export a stable branch (perhaps consisting of just these patches) that I can then merge into the Tegra tree and use as a basis for the PCIe driver itself. Hopefully this approach will get more traction on all the non-Tegra changes. Does that sound like a good plan?

Or, I can just take it all through the Tegra tree, but I'll definitely need acks on all/most of the non-Tegra patches, since although the patches themselves are quite small, I'd like to be sure that maintainers are OK with the conceptual changes, like initializing PCI controllers later than at present etc.

#51 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 6 lines · Stephen Warren
Quoted 2 lines · Thierry Reding

This patch series adds support for device tree based probing of the PCIe controller found on Tegra SoCs.

Thierry,

Quoted 7 lines

I think one thing that would help here would be to split up this series into one per subsystem, and to get all the dependencies merged by the respective maintainers. Preferably, each subsystem would export a stable branch (perhaps consisting of just these patches) that I can then merge into the Tegra tree and use as a basis for the PCIe driver itself. Hopefully this approach will get more traction on all the non-Tegra changes. Does that sound like a good plan?

I don't understand. The series is already split up into per-subsystem patches. I just didn't want to post them separately so everybody on Cc would be able to see the big picture and the reason why the patch was required.

Quoted 5 lines

Or, I can just take it all through the Tegra tree, but I'll definitely need acks on all/most of the non-Tegra patches, since although the patches themselves are quite small, I'd like to be sure that maintainers are OK with the conceptual changes, like initializing PCI controllers later than at present etc.

Taking the patches through the individual trees should be fine. Only so far other subsystem maintainers haven't commented on this.

As to when the PCI controller is initialized, there really aren't many options. On Harmony (and TEC, which in this respect, and others, is very similar) the VDD is supplied by a GPIO of the PMU, so it is currently necessary to probe it at least after the PMU. And unless we want to work around these issues using different initcall ordering we need to rely on deferred probing, which turns out to be done after the init phase often (always?).

Also I had been toying with making the Tegra PCIe driver work as a module, but that doesn't work currently with MSI support. However it might be nice to allow MSI controllers to register at runtime generally, which wouldn't be all that difficult to do I think. Of course somebody more knowledgeable may disagree.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120801/e010e09f/attachment.sig>

#52 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 16 lines · Thierry Reding
Quoted 6 lines · Stephen Warren
Quoted 2 lines · Thierry Reding

This patch series adds support for device tree based probing of the PCIe controller found on Tegra SoCs.

Thierry,

Quoted 8 lines

I think one thing that would help here would be to split up this series into one per subsystem, and to get all the dependencies merged by the respective maintainers. Preferably, each subsystem would export a stable branch (perhaps consisting of just these patches) that I can then merge into the Tegra tree and use as a basis for the PCIe driver itself. Hopefully this approach will get more traction on all the non-Tegra changes. Does that sound like a good plan?

Quoted 4 lines

I don't understand. The series is already split up into per-subsystem patches. I just didn't want to post them separately so everybody on Cc would be able to see the big picture and the reason why the patch was required.

There are separate patches that touch the different subsystems, but they're all scattered throughout the one series, rather than having e.g.:

* a series for the PCI tree
* a series for the ARM core tree
* a series for the OF/DT tree
* a series for the Tegra tree, which indicates it depends on all of those.

I'm wondering if the reason you haven't seen much discussion/Acks from the maintainers of the non-Tegra trees is because this is a big scary series that touches a lot of stuff, and it's not necessarily clear for people unfamiliar with it why they're being CCd on it.

#53 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 30 lines · Stephen Warren
Quoted 16 lines · Thierry Reding
Quoted 6 lines · Stephen Warren
Quoted 2 lines · Thierry Reding

This patch series adds support for device tree based probing of the PCIe controller found on Tegra SoCs.

Thierry,

Quoted 8 lines

I think one thing that would help here would be to split up this series into one per subsystem, and to get all the dependencies merged by the respective maintainers. Preferably, each subsystem would export a stable branch (perhaps consisting of just these patches) that I can then merge into the Tegra tree and use as a basis for the PCIe driver itself. Hopefully this approach will get more traction on all the non-Tegra changes. Does that sound like a good plan?

Quoted 4 lines

I don't understand. The series is already split up into per-subsystem patches. I just didn't want to post them separately so everybody on Cc would be able to see the big picture and the reason why the patch was required.

There are separate patches that touch the different subsystems, but they're all scattered throughout the one series, rather than having e.g.:

* a series for the PCI tree
* a series for the ARM core tree
* a series for the OF/DT tree
* a series for the Tegra tree, which indicates it depends on all of those.

Quoted 4 lines

I'm wondering if the reason you haven't seen much discussion/Acks from the maintainers of the non-Tegra trees is because this is a big scary series that touches a lot of stuff, and it's not necessarily clear for people unfamiliar with it why they're being CCd on it.

I see. If you think it'll help I can certainly split them up as you suggested. I just thought it might be useful for everybody to know the context. At least from my own experience I get annoyed when I'm Cc'ed on a single patch in a larger series because it means I need to look through other archives for the context.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120802/c440c02f/attachment.sig>

#54 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

In reply to Thierry Reding
Quoted 2 lines · Thierry Reding

This patch series adds support for device tree based probing of the PCIe controller found on Tegra SoCs.

Thierry, I just tested all Tegra boards in v3.6-rc1, and noticed that PCIe doesn't work on TrimSlice when booting use device tree. I think I found the cause, and I can't see why the same problem doesn't affect this series. Perhaps you can enlighten me?

When booting TrimSlice (or Harmony) using board files, Tegra's PCIe is initialized using a subsys_initcall to tegra_pcie_init() directly (or for Harmony to harmony_pcie_init() which then calls tegra_pcie_init()).

The final thing tegra_pcie_init() does is call pci_common_init(). This calls pcibios_init_hw() which calls hw->scan() which calls pci_scan_root_bus() which adds a device object for each device on the PCIe bus. However, since this happens very early in the boot sequence, I believe the enumerated PCIe devices don't immediately get probed. Instead, control gets returned to pci_common_init() which I believe then calls pci_bus_assign_resources() which actually sets up the resources for those devices. Later, the PCIe devices actually get probed, and everything works.

However, when booting using device tree, with the code currently in v3.6-rc1, tegra_pcie_init() is called late in the boot sequence, and so in the sequence described above, as soon as pci_scan_root_bus() adds a device, it gets probed, before the device object's resources have been set up, which results in the following failure:

PCI: Device 0000:01:00.0 not available because of resource collisions

... because of the following code in pcibios_enable_device():

Quoted 9 lines
	for (idx = 0; idx < 6; idx++) {
		/* Only set up the requested stuff */
		if (!(mask & (1 << idx)))
			continue;

		r = dev->resource + idx;
		if (!r->start && r->end) {
			printk(KERN_ERR "PCI: Device %s not available because"
			       " of resource collisions\n", pci_name(dev));

Doesn't this same problem exist when instantiating the PCIe device itself from device tree as in your patch series? If not, can you explain why?

Now, the obvious solution in v3.6 would be to simply have tegra_pcie_init() be called at the same early stage in the boot process when booting using device tree as it is when booting using board files. This works for TrimSlice.

However, on Harmony, it doesn't work, because PCIe on Harmony depends on regulators, and the regulators are accessed using an I2C bus that is instantiated from DT, and the instantiation of the I2C bus happens fairly late in the boot process so can't be found early during the boot sequence. See harmony_regulator_init() for the failing code.

Does anyone have any good ideas (small, self-contained patches) for solving this in v3.6 in such a way that PCIe works on both TrimSlice and Harmony?

Thanks.

#55 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 38 lines · Stephen Warren
Quoted 2 lines · Thierry Reding

This patch series adds support for device tree based probing of the PCIe controller found on Tegra SoCs.

Thierry, I just tested all Tegra boards in v3.6-rc1, and noticed that PCIe doesn't work on TrimSlice when booting use device tree. I think I found the cause, and I can't see why the same problem doesn't affect this series. Perhaps you can enlighten me?

When booting TrimSlice (or Harmony) using board files, Tegra's PCIe is initialized using a subsys_initcall to tegra_pcie_init() directly (or for Harmony to harmony_pcie_init() which then calls tegra_pcie_init()).

The final thing tegra_pcie_init() does is call pci_common_init(). This calls pcibios_init_hw() which calls hw->scan() which calls pci_scan_root_bus() which adds a device object for each device on the PCIe bus. However, since this happens very early in the boot sequence, I believe the enumerated PCIe devices don't immediately get probed. Instead, control gets returned to pci_common_init() which I believe then calls pci_bus_assign_resources() which actually sets up the resources for those devices. Later, the PCIe devices actually get probed, and everything works.

However, when booting using device tree, with the code currently in v3.6-rc1, tegra_pcie_init() is called late in the boot sequence, and so in the sequence described above, as soon as pci_scan_root_bus() adds a device, it gets probed, before the device object's resources have been set up, which results in the following failure:

PCI: Device 0000:01:00.0 not available because of resource collisions

... because of the following code in pcibios_enable_device():

Quoted 5 lines
	for (idx = 0; idx < 6; idx++) {
		/* Only set up the requested stuff */
		if (!(mask & (1 << idx)))
			continue;
Quoted 8 lines
Quoted 4 lines
		r = dev->resource + idx;
		if (!r->start && r->end) {
			printk(KERN_ERR "PCI: Device %s not available because"
			       " of resource collisions\n", pci_name(dev));

Doesn't this same problem exist when instantiating the PCIe device itself from device tree as in your patch series? If not, can you explain why?

I think I've seen this before as well but hadn't had the time to investigate further. The devices that failed to initialize were serial ports I think. Perhaps the ordering here is the key. All the drivers that I use for the PCI devices are loaded as modules, so they'll probe the devices much later anyway. The serial driver is an exception here as it is builtin.

Quoted 11 lines

Now, the obvious solution in v3.6 would be to simply have tegra_pcie_init() be called at the same early stage in the boot process when booting using device tree as it is when booting using board files. This works for TrimSlice.

However, on Harmony, it doesn't work, because PCIe on Harmony depends on regulators, and the regulators are accessed using an I2C bus that is instantiated from DT, and the instantiation of the I2C bus happens fairly late in the boot process so can't be found early during the boot sequence. See harmony_regulator_init() for the failing code.

Quoted 3 lines

Does anyone have any good ideas (small, self-contained patches) for solving this in v3.6 in such a way that PCIe works on both TrimSlice and Harmony?

To me this looks like a problem in the probing code. Drivers' .probe() shouldn't be called on devices that haven't had their resources assigned yet. Perhaps nobody has ever seen this before because the ordering always ensured that the PCI controller driver was loaded first.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120807/edcbb095/attachment.sig>

#56 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

In reply to Stephen Warren
Quoted 58 lines · Stephen Warren
Quoted 2 lines · Thierry Reding

This patch series adds support for device tree based probing of the PCIe controller found on Tegra SoCs.

Thierry, I just tested all Tegra boards in v3.6-rc1, and noticed that PCIe doesn't work on TrimSlice when booting use device tree. I think I found the cause, and I can't see why the same problem doesn't affect this series. Perhaps you can enlighten me?

When booting TrimSlice (or Harmony) using board files, Tegra's PCIe is initialized using a subsys_initcall to tegra_pcie_init() directly (or for Harmony to harmony_pcie_init() which then calls tegra_pcie_init()).

The final thing tegra_pcie_init() does is call pci_common_init(). This calls pcibios_init_hw() which calls hw->scan() which calls pci_scan_root_bus() which adds a device object for each device on the PCIe bus. However, since this happens very early in the boot sequence, I believe the enumerated PCIe devices don't immediately get probed. Instead, control gets returned to pci_common_init() which I believe then calls pci_bus_assign_resources() which actually sets up the resources for those devices. Later, the PCIe devices actually get probed, and everything works.

However, when booting using device tree, with the code currently in v3.6-rc1, tegra_pcie_init() is called late in the boot sequence, and so in the sequence described above, as soon as pci_scan_root_bus() adds a device, it gets probed, before the device object's resources have been set up, which results in the following failure:

PCI: Device 0000:01:00.0 not available because of resource collisions

... because of the following code in pcibios_enable_device():

Quoted 9 lines
	for (idx = 0; idx < 6; idx++) {
		/* Only set up the requested stuff */
		if (!(mask & (1 << idx)))
			continue;

		r = dev->resource + idx;
		if (!r->start && r->end) {
			printk(KERN_ERR "PCI: Device %s not available because"
			       " of resource collisions\n", pci_name(dev));

Doesn't this same problem exist when instantiating the PCIe device itself from device tree as in your patch series? If not, can you explain why?

Now, the obvious solution in v3.6 would be to simply have tegra_pcie_init() be called at the same early stage in the boot process when booting using device tree as it is when booting using board files. This works for TrimSlice.

However, on Harmony, it doesn't work, because PCIe on Harmony depends on regulators, and the regulators are accessed using an I2C bus that is instantiated from DT, and the instantiation of the I2C bus happens fairly late in the boot process so can't be found early during the boot sequence. See harmony_regulator_init() for the failing code.

Quoted 5 lines

Does anyone have any good ideas (small, self-contained patches) for solving this in v3.6 in such a way that PCIe works on both TrimSlice and Harmony?

Thanks.

I've looked into this a bit, and it seems like ARM is using an open- coded version of the pci_enable_resources() function here, with the only difference being the unconditional enabling of both I/O and memory- mapped access for bridges. On Tegra there is already a PCI fixup to do this, so pci_enable_resources() can be used as-is. I came up with the attached patch but haven't been able to test it yet.

Thierry
-------------- next part --------------

Quoted 1 line

From ebd69ae0a3d076e574da74d963cb3834b71dc6ad Mon Sep 17 00:00:00 2001

From: Thierry Reding <[email protected]>
Date: Mon, 13 Aug 2012 18:49:28 +0200
Subject: [PATCH] ARM: PCI: refactor pcibios_enable_device()

The implementation is an open-coded version on pci_enable_resources() with a special case to enable I/O and memory-mapped functionality on bridges. This commit reuses the existing PCI core implementation of the pci_enable_resources() function. This also means that bridges no longer enable I/O and memory-mapped functionality unconditionally. Platforms where this is really required can add a corresponding fixup.

---
 arch/arm/kernel/bios32.c | 36 +-----------------------------------
 1 file changed, 1 insertion(+), 35 deletions(-)
arch/arm/kernel/bios32.c +1 -35
index 13fd97b..dfe25f7 100644
@@ -601,41 +601,7 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
  */
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
-	u16 cmd, old_cmd;
-	int idx;
-	struct resource *r;
-
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	old_cmd = cmd;
-	for (idx = 0; idx < 6; idx++) {
-		/* Only set up the requested stuff */
-		if (!(mask & (1 << idx)))
-			continue;
-
-		r = dev->resource + idx;
-		if (!r->start && r->end) {
-			printk(KERN_ERR "PCI: Device %s not available because"
-			       " of resource collisions\n", pci_name(dev));
-			return -EINVAL;
-		}
-		if (r->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (r->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-
-	/*
-	 * Bridges (eg, cardbus bridges) need to be fully enabled
-	 */
-	if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
-		cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
-
-	if (cmd != old_cmd) {
-		printk("PCI: enabling device %s (%04x -> %04x)\n",
-		       pci_name(dev), old_cmd, cmd);
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-	return 0;
+	return pci_enable_resources(dev, mask);
 }
 
 int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
Signature · 9 lines
1.7.11.4

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120813/05e25d04/attachment.sig>
#57 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 9 lines · Thierry Reding
Quoted 8 lines · Stephen Warren
Quoted 2 lines · Thierry Reding

This patch series adds support for device tree based probing of the PCIe controller found on Tegra SoCs.

Thierry, I just tested all Tegra boards in v3.6-rc1, and noticed that PCIe doesn't work on TrimSlice when booting use device tree. I think I found the cause, and I can't see why the same problem doesn't affect this series. Perhaps you can enlighten me?

...

Quoted 2 lines
Quoted 2 lines

PCI: Device 0000:01:00.0 not available because of resource collisions

...

Quoted 7 lines

I've looked into this a bit, and it seems like ARM is using an open- coded version of the pci_enable_resources() function here, with the only difference being the unconditional enabling of both I/O and memory- mapped access for bridges. On Tegra there is already a PCI fixup to do this, so pci_enable_resources() can be used as-is. I came up with the attached patch but haven't been able to test it yet.

Thanks very much for looking into this.

The patch did alter the behavior a little for TrimSlice, but didn't solve the problem. The old error messages:

Quoted 3 lines
[    2.173971] PCI: Device 0000:01:00.0 not available because of resource collisions
[    2.181453] r8169 0000:01:00.0: (unregistered net_device): enable failure
[    2.188254] r8169: probe of 0000:01:00.0 failed with error -22

Were replaced with the following with your patch:

Quoted 3 lines
[    2.174010] r8169 0000:01:00.0: device not available (can't reserve [io  0x0000-0x00ff])
[    2.182098] r8169 0000:01:00.0: (unregistered net_device): enable failure
[    2.188900] r8169: probe of 0000:01:00.0 failed with error -22

This message appears from drivers/pci/setup-res.c pci_enable_resources() due to:

Quoted 5 lines
		if (!r->parent) {
			dev_err(&dev->dev, "device not available "
				"(can't reserve %pR)\n", r);
			return -EINVAL;
		}

That check doesn't appear in ARM's custom pcibios_enable_device(). Disabling that check yields:

Quoted 4 lines
[    2.174192] r8169 0000:01:00.0: enabling device (0140 -> 0143)
[    2.180041] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.188386] r8169 0000:01:00.0: (unregistered net_device): could not request regions
[    2.196140] r8169: probe of 0000:01:00.0 failed with error -16

I think that's because the pci_dev's resources are initially assigned PCI-aperture-relative addresses, and then these are later patched up to take account of where the aperture is mapped into the CPU's address space.

Boot log using board files:

Quoted 4 lines
[    1.146145] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    1.151745] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    1.159007] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    1.166270] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

...

Quoted 4 lines
[    1.217829] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    1.225264] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    1.233236] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    1.241206] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]

... (I added some extra printks:)

Quoted 3 lines
[    1.488007] r8169 0000:01:00.0: BAR 0: requesting [io  0x1000-0x10ff]
[    1.501483] r8169 0000:01:00.0: BAR 2: requesting [mem 0xa0024000-0xa0024fff 64bit pref]
[    1.516611] r8169 0000:01:00.0: BAR 4: requesting [mem 0xa0020000-0xa0023fff 64bit pref]

whereas for a device tree boot:

(same):

Quoted 4 lines
[    2.112217] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    2.117635] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    2.124690] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    2.131731] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

... (request region happens early)

Quoted 4 lines
[    2.179838] r8169 0000:01:00.0: BAR 0: requesting [io  0x0000-0x00ff]
[    2.193312] r8169 0000:01:00.0: BAR 2: requesting [mem 0x00000000-0x00000fff 64bit pref]
[    2.201397] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.209742] r8169 0000:01:00.0: (unregistered net_device): could not request regions

... (same, just happens too late)

Quoted 4 lines
[    2.236818] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    2.244027] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    2.251794] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    2.259542] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]

I suspect this is all still related to the PCI devices themselves being probed much earlier in the overall PCI initialization sequence when the PCI controller is probed later in the boot sequence, whereas PCI device probe is deferred until the overall PCI initialization sequence is complete if the PCI controller is probed very early in the boot sequence.

Does anyone know where/what that "probe now" vs. "probe later" decision point is? I'll try and track it down if nobody beats me to it.

#58 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 31 lines · Stephen Warren
Quoted 9 lines · Thierry Reding
Quoted 8 lines · Stephen Warren
Quoted 2 lines · Thierry Reding

This patch series adds support for device tree based probing of the PCIe controller found on Tegra SoCs.

Thierry, I just tested all Tegra boards in v3.6-rc1, and noticed that PCIe doesn't work on TrimSlice when booting use device tree. I think I found the cause, and I can't see why the same problem doesn't affect this series. Perhaps you can enlighten me?

...

Quoted 2 lines
Quoted 2 lines

PCI: Device 0000:01:00.0 not available because of resource collisions

...

Quoted 7 lines

I've looked into this a bit, and it seems like ARM is using an open- coded version of the pci_enable_resources() function here, with the only difference being the unconditional enabling of both I/O and memory- mapped access for bridges. On Tegra there is already a PCI fixup to do this, so pci_enable_resources() can be used as-is. I came up with the attached patch but haven't been able to test it yet.

Thanks very much for looking into this.

The patch did alter the behavior a little for TrimSlice, but didn't solve the problem. The old error messages:

Quoted 3 lines
[    2.173971] PCI: Device 0000:01:00.0 not available because of resource collisions
[    2.181453] r8169 0000:01:00.0: (unregistered net_device): enable failure
[    2.188254] r8169: probe of 0000:01:00.0 failed with error -22
Quoted 14 lines

Were replaced with the following with your patch:

Quoted 3 lines
[    2.174010] r8169 0000:01:00.0: device not available (can't reserve [io  0x0000-0x00ff])
[    2.182098] r8169 0000:01:00.0: (unregistered net_device): enable failure
[    2.188900] r8169: probe of 0000:01:00.0 failed with error -22

This message appears from drivers/pci/setup-res.c pci_enable_resources() due to:

Quoted 5 lines
		if (!r->parent) {
			dev_err(&dev->dev, "device not available "
				"(can't reserve %pR)\n", r);
			return -EINVAL;
		}

Looking at the code some more, this may be caused by the pci_remap_io() patch series, so you might want to revert that patch and see if it fixes the I/O resources.

Quoted 46 lines

That check doesn't appear in ARM's custom pcibios_enable_device(). Disabling that check yields:

Quoted 4 lines
[    2.174192] r8169 0000:01:00.0: enabling device (0140 -> 0143)
[    2.180041] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.188386] r8169 0000:01:00.0: (unregistered net_device): could not request regions
[    2.196140] r8169: probe of 0000:01:00.0 failed with error -16

I think that's because the pci_dev's resources are initially assigned PCI-aperture-relative addresses, and then these are later patched up to take account of where the aperture is mapped into the CPU's address space.

Boot log using board files:

Quoted 4 lines
[    1.146145] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    1.151745] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    1.159007] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    1.166270] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

...

Quoted 4 lines
[    1.217829] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    1.225264] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    1.233236] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    1.241206] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]

... (I added some extra printks:)

Quoted 3 lines
[    1.488007] r8169 0000:01:00.0: BAR 0: requesting [io  0x1000-0x10ff]
[    1.501483] r8169 0000:01:00.0: BAR 2: requesting [mem 0xa0024000-0xa0024fff 64bit pref]
[    1.516611] r8169 0000:01:00.0: BAR 4: requesting [mem 0xa0020000-0xa0023fff 64bit pref]

whereas for a device tree boot:

(same):

Quoted 4 lines
[    2.112217] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    2.117635] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    2.124690] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    2.131731] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

... (request region happens early)

Quoted 4 lines
[    2.179838] r8169 0000:01:00.0: BAR 0: requesting [io  0x0000-0x00ff]
[    2.193312] r8169 0000:01:00.0: BAR 2: requesting [mem 0x00000000-0x00000fff 64bit pref]
[    2.201397] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.209742] r8169 0000:01:00.0: (unregistered net_device): could not request regions

... (same, just happens too late)

Quoted 4 lines
[    2.236818] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    2.244027] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    2.251794] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    2.259542] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]
Quoted 8 lines

I suspect this is all still related to the PCI devices themselves being probed much earlier in the overall PCI initialization sequence when the PCI controller is probed later in the boot sequence, whereas PCI device probe is deferred until the overall PCI initialization sequence is complete if the PCI controller is probed very early in the boot sequence.

Does anyone know where/what that "probe now" vs. "probe later" decision point is? I'll try and track it down if nobody beats me to it.

There's the io_offset and mem_offset fields that I've completely ignored up to now. Can you try the patch below to see if it changes anything? I'm sorry but I can't test any of this myself right now.

Thierry
-------------- next part --------------

arch/arm/mach-tegra/pcie.c +2 -2
index 3463fb5..9b9b3e0 100644
@@ -395,7 +395,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
 	pp->res[0].flags = IORESOURCE_MEM;
 	if (request_resource(&iomem_resource, &pp->res[0]))
 		panic("Request PCIe Memory resource failed\n");
-	pci_add_resource_offset(&sys->resources, &pp->res[0], sys->mem_offset);
+	pci_add_resource_offset(&sys->resources, &pp->res[0], pp->res[0].start);
 
 	/*
 	 * IORESOURCE_MEM | IORESOURCE_PREFETCH
@@ -414,7 +414,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
 	pp->res[1].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
 	if (request_resource(&iomem_resource, &pp->res[1]))
 		panic("Request PCIe Prefetch Memory resource failed\n");
-	pci_add_resource_offset(&sys->resources, &pp->res[1], sys->mem_offset);
+	pci_add_resource_offset(&sys->resources, &pp->res[1], pp->res[1].start);
 
 	return 1;
 }

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120813/0adeb105/attachment-0001.sig>

#59 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 47 lines · Thierry Reding
Quoted 31 lines · Stephen Warren
Quoted 9 lines · Thierry Reding
Quoted 8 lines · Stephen Warren
Quoted 2 lines · Thierry Reding

This patch series adds support for device tree based probing of the PCIe controller found on Tegra SoCs.

Thierry, I just tested all Tegra boards in v3.6-rc1, and noticed that PCIe doesn't work on TrimSlice when booting use device tree. I think I found the cause, and I can't see why the same problem doesn't affect this series. Perhaps you can enlighten me?

...

Quoted 2 lines
Quoted 2 lines

PCI: Device 0000:01:00.0 not available because of resource collisions

...

Quoted 7 lines

I've looked into this a bit, and it seems like ARM is using an open- coded version of the pci_enable_resources() function here, with the only difference being the unconditional enabling of both I/O and memory- mapped access for bridges. On Tegra there is already a PCI fixup to do this, so pci_enable_resources() can be used as-is. I came up with the attached patch but haven't been able to test it yet.

Thanks very much for looking into this.

The patch did alter the behavior a little for TrimSlice, but didn't solve the problem. The old error messages:

Quoted 3 lines
[    2.173971] PCI: Device 0000:01:00.0 not available because of resource collisions
[    2.181453] r8169 0000:01:00.0: (unregistered net_device): enable failure
[    2.188254] r8169: probe of 0000:01:00.0 failed with error -22
Quoted 14 lines

Were replaced with the following with your patch:

Quoted 3 lines
[    2.174010] r8169 0000:01:00.0: device not available (can't reserve [io  0x0000-0x00ff])
[    2.182098] r8169 0000:01:00.0: (unregistered net_device): enable failure
[    2.188900] r8169: probe of 0000:01:00.0 failed with error -22

This message appears from drivers/pci/setup-res.c pci_enable_resources() due to:

Quoted 5 lines
		if (!r->parent) {
			dev_err(&dev->dev, "device not available "
				"(can't reserve %pR)\n", r);
			return -EINVAL;
		}
Quoted 4 lines

Looking at the code some more, this may be caused by the pci_remap_io() patch series, so you might want to revert that patch and see if it fixes the I/O resources.

Humm... But this patch deals with the i/o space and it is failing below on the memory space.

Quoted 52 lines
Quoted 52 lines

That check doesn't appear in ARM's custom pcibios_enable_device(). Disabling that check yields:

Quoted 4 lines
[    2.174192] r8169 0000:01:00.0: enabling device (0140 -> 0143)
[    2.180041] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.188386] r8169 0000:01:00.0: (unregistered net_device): could not request regions
[    2.196140] r8169: probe of 0000:01:00.0 failed with error -16

I think that's because the pci_dev's resources are initially assigned PCI-aperture-relative addresses, and then these are later patched up to take account of where the aperture is mapped into the CPU's address space.

Boot log using board files:

Quoted 4 lines
[    1.146145] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    1.151745] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    1.159007] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    1.166270] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

...

Quoted 4 lines
[    1.217829] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    1.225264] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    1.233236] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    1.241206] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]

... (I added some extra printks:)

Quoted 3 lines
[    1.488007] r8169 0000:01:00.0: BAR 0: requesting [io  0x1000-0x10ff]
[    1.501483] r8169 0000:01:00.0: BAR 2: requesting [mem 0xa0024000-0xa0024fff 64bit pref]
[    1.516611] r8169 0000:01:00.0: BAR 4: requesting [mem 0xa0020000-0xa0023fff 64bit pref]

whereas for a device tree boot:

(same):

Quoted 4 lines
[    2.112217] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    2.117635] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    2.124690] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    2.131731] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

... (request region happens early)

Quoted 4 lines
[    2.179838] r8169 0000:01:00.0: BAR 0: requesting [io  0x0000-0x00ff]
[    2.193312] r8169 0000:01:00.0: BAR 2: requesting [mem 0x00000000-0x00000fff 64bit pref]
[    2.201397] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.209742] r8169 0000:01:00.0: (unregistered net_device): could not request regions

... (same, just happens too late)

Quoted 4 lines
[    2.236818] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    2.244027] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    2.251794] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    2.259542] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]

I suspect this is all still related to the PCI devices themselves being probed much earlier in the overall PCI initialization sequence when the PCI controller is probed later in the boot sequence, whereas PCI device probe is deferred until the overall PCI initialization sequence is complete if the PCI controller is probed very early in the boot sequence.

Quoted 6 lines
Quoted 2 lines

Does anyone know where/what that "probe now" vs. "probe later" decision point is? I'll try and track it down if nobody beats me to it.

There's the io_offset and mem_offset fields that I've completely ignored up to now. Can you try the patch below to see if it changes anything? I'm sorry but I can't test any of this myself right now.

Arnd and I discussed io_offset some. I don't think either of us can figure out when it should be anything but 0 at least if pci i/o bus addresses start at 0.

I don't think mem_offset is the issue. I think perhaps you need to set pcibios_min_mem to the memory window base (0xa0000000), but that's just a guess.

Rob

Quoted 10 lines

Thierry

_______________________________________________
devicetree-discuss mailing list
devicetree-discuss at lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss

#60 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 48 lines · Rob Herring
Quoted 47 lines · Thierry Reding
Quoted 45 lines · Stephen Warren
Quoted 9 lines · Thierry Reding
Quoted 8 lines · Stephen Warren
Quoted 2 lines · Thierry Reding

This patch series adds support for device tree based probing of the PCIe controller found on Tegra SoCs.

Thierry, I just tested all Tegra boards in v3.6-rc1, and noticed that PCIe doesn't work on TrimSlice when booting use device tree. I think I found the cause, and I can't see why the same problem doesn't affect this series. Perhaps you can enlighten me?

...

Quoted 2 lines
Quoted 2 lines

PCI: Device 0000:01:00.0 not available because of resource collisions

...

Quoted 7 lines

I've looked into this a bit, and it seems like ARM is using an open- coded version of the pci_enable_resources() function here, with the only difference being the unconditional enabling of both I/O and memory- mapped access for bridges. On Tegra there is already a PCI fixup to do this, so pci_enable_resources() can be used as-is. I came up with the attached patch but haven't been able to test it yet.

Thanks very much for looking into this.

The patch did alter the behavior a little for TrimSlice, but didn't solve the problem. The old error messages:

Quoted 3 lines
[    2.173971] PCI: Device 0000:01:00.0 not available because of resource collisions
[    2.181453] r8169 0000:01:00.0: (unregistered net_device): enable failure
[    2.188254] r8169: probe of 0000:01:00.0 failed with error -22

Were replaced with the following with your patch:

Quoted 3 lines
[    2.174010] r8169 0000:01:00.0: device not available (can't reserve [io  0x0000-0x00ff])
[    2.182098] r8169 0000:01:00.0: (unregistered net_device): enable failure
[    2.188900] r8169: probe of 0000:01:00.0 failed with error -22

This message appears from drivers/pci/setup-res.c pci_enable_resources() due to:

Quoted 5 lines
		if (!r->parent) {
			dev_err(&dev->dev, "device not available "
				"(can't reserve %pR)\n", r);
			return -EINVAL;
		}
Quoted 7 lines
Quoted 4 lines

Looking at the code some more, this may be caused by the pci_remap_io() patch series, so you might want to revert that patch and see if it fixes the I/O resources.

Humm... But this patch deals with the i/o space and it is failing below on the memory space.

But above it also fails for I/O. Looking at this some more, it seems like your patch isn't at fault. Rather there seems to be a general resource assignment problem.

Quoted 60 lines
Quoted 53 lines
Quoted 53 lines

That check doesn't appear in ARM's custom pcibios_enable_device(). Disabling that check yields:

Quoted 4 lines
[    2.174192] r8169 0000:01:00.0: enabling device (0140 -> 0143)
[    2.180041] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.188386] r8169 0000:01:00.0: (unregistered net_device): could not request regions
[    2.196140] r8169: probe of 0000:01:00.0 failed with error -16

I think that's because the pci_dev's resources are initially assigned PCI-aperture-relative addresses, and then these are later patched up to take account of where the aperture is mapped into the CPU's address space.

Boot log using board files:

Quoted 4 lines
[    1.146145] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    1.151745] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    1.159007] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    1.166270] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

...

Quoted 4 lines
[    1.217829] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    1.225264] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    1.233236] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    1.241206] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]

... (I added some extra printks:)

Quoted 3 lines
[    1.488007] r8169 0000:01:00.0: BAR 0: requesting [io  0x1000-0x10ff]
[    1.501483] r8169 0000:01:00.0: BAR 2: requesting [mem 0xa0024000-0xa0024fff 64bit pref]
[    1.516611] r8169 0000:01:00.0: BAR 4: requesting [mem 0xa0020000-0xa0023fff 64bit pref]

whereas for a device tree boot:

(same):

Quoted 4 lines
[    2.112217] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    2.117635] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    2.124690] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    2.131731] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

... (request region happens early)

Quoted 4 lines
[    2.179838] r8169 0000:01:00.0: BAR 0: requesting [io  0x0000-0x00ff]
[    2.193312] r8169 0000:01:00.0: BAR 2: requesting [mem 0x00000000-0x00000fff 64bit pref]
[    2.201397] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.209742] r8169 0000:01:00.0: (unregistered net_device): could not request regions

... (same, just happens too late)

Quoted 4 lines
[    2.236818] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    2.244027] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    2.251794] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    2.259542] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]

I suspect this is all still related to the PCI devices themselves being probed much earlier in the overall PCI initialization sequence when the PCI controller is probed later in the boot sequence, whereas PCI device probe is deferred until the overall PCI initialization sequence is complete if the PCI controller is probed very early in the boot sequence.

Quoted 6 lines
Quoted 2 lines

Does anyone know where/what that "probe now" vs. "probe later" decision point is? I'll try and track it down if nobody beats me to it.

There's the io_offset and mem_offset fields that I've completely ignored up to now. Can you try the patch below to see if it changes anything? I'm sorry but I can't test any of this myself right now.

Quoted 7 lines

Arnd and I discussed io_offset some. I don't think either of us can figure out when it should be anything but 0 at least if pci i/o bus addresses start at 0.

I don't think mem_offset is the issue. I think perhaps you need to set pcibios_min_mem to the memory window base (0xa0000000), but that's just a guess.

I'm having trouble understanding how that's supposed to work for regions of prefetchable memory. At least on Tegra these can arbitrarily assigned and I thought I had seen other platforms where this was also the case.

However the pcibios_min_mem (or the equivalent macro PCIBIOS_MIN_MEM) is used while assigning the resources in the __pci_assign_resources() in drivers/pci/setup-res.c, so it may influence things.

But I think the more fundamental issue here is that BARs are assigned properly, only they are assigned too late in the DT case as opposed to the board files case. I don't understand why that happens.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120814/321e3127/attachment-0001.sig>

maintainer
#61 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

In reply to Stephen Warren
Quoted 13 lines · Stephen Warren
Quoted 9 lines · Thierry Reding
Quoted 8 lines · Stephen Warren
Quoted 2 lines · Thierry Reding

This patch series adds support for device tree based probing of the PCIe controller found on Tegra SoCs.

Thierry, I just tested all Tegra boards in v3.6-rc1, and noticed that PCIe doesn't work on TrimSlice when booting use device tree. I think I found the cause, and I can't see why the same problem doesn't affect this series. Perhaps you can enlighten me?

...

Quoted 2 lines
Quoted 2 lines

PCI: Device 0000:01:00.0 not available because of resource collisions

Quoted 7 lines

...

Quoted 6 lines

I've looked into this a bit, and it seems like ARM is using an open- coded version of the pci_enable_resources() function here, with the only difference being the unconditional enabling of both I/O and memory- mapped access for bridges. On Tegra there is already a PCI fixup to do this, so pci_enable_resources() can be used as-is.

I'd prefer that bridge I/O & memory access enabling be done in a mainline path, not in a fixup. Fixups are intended for working around defects in specific devices, not for the normal path. I know various architectures have fixups that are used in the normal path, but I've been working on eliminating them.

Quoted 25 lines

The patch did alter the behavior a little for TrimSlice, but didn't solve the problem. The old error messages:

Quoted 3 lines
[    2.173971] PCI: Device 0000:01:00.0 not available because of resource collisions
[    2.181453] r8169 0000:01:00.0: (unregistered net_device): enable failure
[    2.188254] r8169: probe of 0000:01:00.0 failed with error -22

Were replaced with the following with your patch:

Quoted 3 lines
[    2.174010] r8169 0000:01:00.0: device not available (can't reserve [io  0x0000-0x00ff])
[    2.182098] r8169 0000:01:00.0: (unregistered net_device): enable failure
[    2.188900] r8169: probe of 0000:01:00.0 failed with error -22

This message appears from drivers/pci/setup-res.c pci_enable_resources() due to:

Quoted 5 lines
              if (!r->parent) {
                      dev_err(&dev->dev, "device not available "
                              "(can't reserve %pR)\n", r);
                      return -EINVAL;
              }

That check doesn't appear in ARM's custom pcibios_enable_device(). Disabling that check yields:

Quoted 8 lines
Quoted 4 lines
[    2.174192] r8169 0000:01:00.0: enabling device (0140 -> 0143)
[    2.180041] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.188386] r8169 0000:01:00.0: (unregistered net_device): could not request regions
[    2.196140] r8169: probe of 0000:01:00.0 failed with error -16

I think that's because the pci_dev's resources are initially assigned PCI-aperture-relative addresses, and then these are later patched up to take account of where the aperture is mapped into the CPU's address space.

We definitely shouldn't be calling the driver probe routine before the device BARs are assigned.

Quoted 34 lines

Boot log using board files:

Quoted 4 lines
[    1.146145] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    1.151745] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    1.159007] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    1.166270] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

...

Quoted 4 lines
[    1.217829] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    1.225264] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    1.233236] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    1.241206] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]

... (I added some extra printks:)

Quoted 3 lines
[    1.488007] r8169 0000:01:00.0: BAR 0: requesting [io  0x1000-0x10ff]
[    1.501483] r8169 0000:01:00.0: BAR 2: requesting [mem 0xa0024000-0xa0024fff 64bit pref]
[    1.516611] r8169 0000:01:00.0: BAR 4: requesting [mem 0xa0020000-0xa0023fff 64bit pref]

whereas for a device tree boot:

(same):

Quoted 4 lines
[    2.112217] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    2.117635] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    2.124690] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    2.131731] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

... (request region happens early)

Quoted 4 lines
[    2.179838] r8169 0000:01:00.0: BAR 0: requesting [io  0x0000-0x00ff]
[    2.193312] r8169 0000:01:00.0: BAR 2: requesting [mem 0x00000000-0x00000fff 64bit pref]
[    2.201397] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.209742] r8169 0000:01:00.0: (unregistered net_device): could not request regions

... (same, just happens too late)

Quoted 4 lines
[    2.236818] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    2.244027] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    2.251794] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    2.259542] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]
Quoted 5 lines

I suspect this is all still related to the PCI devices themselves being probed much earlier in the overall PCI initialization sequence when the PCI controller is probed later in the boot sequence, whereas PCI device probe is deferred until the overall PCI initialization sequence is complete if the PCI controller is probed very early in the boot sequence.

I don't know what to apply your patches to (they don't apply cleanly to v3.6-rc2), so I can't see exactly what you're doing. But it looks like you might be calling pci_bus_add_devices() before pci_bus_assign_resource(), which isn't going to work.

I don't know what it means to probe PCI devices before probing the PCI controller (the host bridge) -- that shouldn't happen either. In order to probe PCI devices, we have to first know about the host bridge so we know how to do config accesses and what the bridge apertures are.

#62 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 22 lines · Bjorn Helgaas
Quoted 13 lines · Stephen Warren
Quoted 9 lines · Thierry Reding
Quoted 8 lines · Stephen Warren
Quoted 2 lines · Thierry Reding

This patch series adds support for device tree based probing of the PCIe controller found on Tegra SoCs.

Thierry, I just tested all Tegra boards in v3.6-rc1, and noticed that PCIe doesn't work on TrimSlice when booting use device tree. I think I found the cause, and I can't see why the same problem doesn't affect this series. Perhaps you can enlighten me?

...

Quoted 2 lines
Quoted 2 lines

PCI: Device 0000:01:00.0 not available because of resource collisions

Quoted 7 lines

...

Quoted 6 lines

I've looked into this a bit, and it seems like ARM is using an open- coded version of the pci_enable_resources() function here, with the only difference being the unconditional enabling of both I/O and memory- mapped access for bridges. On Tegra there is already a PCI fixup to do this, so pci_enable_resources() can be used as-is.

Quoted 5 lines

I'd prefer that bridge I/O & memory access enabling be done in a mainline path, not in a fixup. Fixups are intended for working around defects in specific devices, not for the normal path. I know various architectures have fixups that are used in the normal path, but I've been working on eliminating them.

I understand. Perhaps it should be added to the pci_enable_resources() function?

Quoted 77 lines
Quoted 25 lines

The patch did alter the behavior a little for TrimSlice, but didn't solve the problem. The old error messages:

Quoted 3 lines
[    2.173971] PCI: Device 0000:01:00.0 not available because of resource collisions
[    2.181453] r8169 0000:01:00.0: (unregistered net_device): enable failure
[    2.188254] r8169: probe of 0000:01:00.0 failed with error -22

Were replaced with the following with your patch:

Quoted 3 lines
[    2.174010] r8169 0000:01:00.0: device not available (can't reserve [io  0x0000-0x00ff])
[    2.182098] r8169 0000:01:00.0: (unregistered net_device): enable failure
[    2.188900] r8169: probe of 0000:01:00.0 failed with error -22

This message appears from drivers/pci/setup-res.c pci_enable_resources() due to:

Quoted 5 lines
              if (!r->parent) {
                      dev_err(&dev->dev, "device not available "
                              "(can't reserve %pR)\n", r);
                      return -EINVAL;
              }

That check doesn't appear in ARM's custom pcibios_enable_device(). Disabling that check yields:

Quoted 8 lines
Quoted 4 lines
[    2.174192] r8169 0000:01:00.0: enabling device (0140 -> 0143)
[    2.180041] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.188386] r8169 0000:01:00.0: (unregistered net_device): could not request regions
[    2.196140] r8169: probe of 0000:01:00.0 failed with error -16

I think that's because the pci_dev's resources are initially assigned PCI-aperture-relative addresses, and then these are later patched up to take account of where the aperture is mapped into the CPU's address space.

We definitely shouldn't be calling the driver probe routine before the device BARs are assigned.

Quoted 34 lines

Boot log using board files:

Quoted 4 lines
[    1.146145] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    1.151745] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    1.159007] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    1.166270] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

...

Quoted 4 lines
[    1.217829] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    1.225264] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    1.233236] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    1.241206] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]

... (I added some extra printks:)

Quoted 3 lines
[    1.488007] r8169 0000:01:00.0: BAR 0: requesting [io  0x1000-0x10ff]
[    1.501483] r8169 0000:01:00.0: BAR 2: requesting [mem 0xa0024000-0xa0024fff 64bit pref]
[    1.516611] r8169 0000:01:00.0: BAR 4: requesting [mem 0xa0020000-0xa0023fff 64bit pref]

whereas for a device tree boot:

(same):

Quoted 4 lines
[    2.112217] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    2.117635] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    2.124690] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    2.131731] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

... (request region happens early)

Quoted 4 lines
[    2.179838] r8169 0000:01:00.0: BAR 0: requesting [io  0x0000-0x00ff]
[    2.193312] r8169 0000:01:00.0: BAR 2: requesting [mem 0x00000000-0x00000fff 64bit pref]
[    2.201397] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.209742] r8169 0000:01:00.0: (unregistered net_device): could not request regions

... (same, just happens too late)

Quoted 4 lines
[    2.236818] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    2.244027] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    2.251794] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    2.259542] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]
Quoted 5 lines

I suspect this is all still related to the PCI devices themselves being probed much earlier in the overall PCI initialization sequence when the PCI controller is probed later in the boot sequence, whereas PCI device probe is deferred until the overall PCI initialization sequence is complete if the PCI controller is probed very early in the boot sequence.

Quoted 4 lines

I don't know what to apply your patches to (they don't apply cleanly to v3.6-rc2), so I can't see exactly what you're doing. But it looks like you might be calling pci_bus_add_devices() before pci_bus_assign_resource(), which isn't going to work.

The patch was on top of this series, which in turn is based on -next. However the patch doesn't actually change anything in the ordering of the initialization sequence, it just replaces the ARM implementation of pcibios_enable_device() to reuse pci_enable_resources().

ARM's main PCI entry point, arch/arm/kernel/bios32.c:pci_common_init(), does call the correct sequence: pci_bus_assign_resources() followed by pci_bus_add_devices(), so the sequence looks correct. However, judging by the logs Stephen posted, the BAR assignment is too late, after the driver has been probed.

Quoted 5 lines

I don't know what it means to probe PCI devices before probing the PCI controller (the host bridge) -- that shouldn't happen either. In order to probe PCI devices, we have to first know about the host bridge so we know how to do config accesses and what the bridge apertures are.

Right. I don't think this can happen. If the bridge hasn't been probed, then the devices shouldn't be there anyway.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120814/8c368b33/attachment.sig>

#63 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

In reply to Bjorn Helgaas
Quoted 1 line · Bjorn Helgaas

On Mon, Aug 13, 2012 at 11:47 AM, Stephen Warren <[email protected]> wrote:

...

Quoted 24 lines
Quoted 18 lines

whereas for a device tree boot:

(same):

Quoted 4 lines
[    2.112217] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    2.117635] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    2.124690] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    2.131731] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

... (request region happens early)

Quoted 4 lines
[    2.179838] r8169 0000:01:00.0: BAR 0: requesting [io  0x0000-0x00ff]
[    2.193312] r8169 0000:01:00.0: BAR 2: requesting [mem 0x00000000-0x00000fff 64bit pref]
[    2.201397] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.209742] r8169 0000:01:00.0: (unregistered net_device): could not request regions

... (same, just happens too late)

Quoted 4 lines
[    2.236818] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    2.244027] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    2.251794] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    2.259542] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]
Quoted 5 lines

I suspect this is all still related to the PCI devices themselves being probed much earlier in the overall PCI initialization sequence when the PCI controller is probed later in the boot sequence, whereas PCI device probe is deferred until the overall PCI initialization sequence is complete if the PCI controller is probed very early in the boot sequence.

Quoted 4 lines

I don't know what to apply your patches to (they don't apply cleanly to v3.6-rc2), so I can't see exactly what you're doing. But it looks like you might be calling pci_bus_add_devices() before pci_bus_assign_resource(), which isn't going to work.

Yes, that's exactly what is happening.

PCIe initialization starts in arch/arm/mach-tegra/pci.e tegra_pcie_init() which calls arch/arm/kernel/bios32.c pci_common_init(). That function first calls pcibios_init_hw() (in the same file, more about this later) and then loops over PCI buses, calling amongst other things pci_bus_assign_resources() then pci_bus_add_devices().

The problem is that ARM's pcibios_init_hw() calls pci_scan_root_bus() (or a host-driver-specific function which that also calls pci_scan_root_bus() in Tegra's case) which in turn calls pci_bus_add_devices() right at the end, before control has returned to pci_common_init() and hence before pci_bus_assign_resources() has been called.

If I modify pci_scan_root_bus() and remove the call to pci_bus_add_devices(), everything works as expected.

So, I guess the question is: Should ARM's pcibios_init_hw() not be calling pci_scan_root_bus(), or at least presumably the ARM PCI code needs to do things in a slightly different order?

#64 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 47 lines · Stephen Warren
Quoted 1 line · Bjorn Helgaas

On Mon, Aug 13, 2012 at 11:47 AM, Stephen Warren <[email protected]> wrote:

...

Quoted 24 lines
Quoted 18 lines

whereas for a device tree boot:

(same):

Quoted 4 lines
[    2.112217] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    2.117635] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    2.124690] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    2.131731] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

... (request region happens early)

Quoted 4 lines
[    2.179838] r8169 0000:01:00.0: BAR 0: requesting [io  0x0000-0x00ff]
[    2.193312] r8169 0000:01:00.0: BAR 2: requesting [mem 0x00000000-0x00000fff 64bit pref]
[    2.201397] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.209742] r8169 0000:01:00.0: (unregistered net_device): could not request regions

... (same, just happens too late)

Quoted 4 lines
[    2.236818] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    2.244027] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    2.251794] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    2.259542] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]
Quoted 5 lines

I suspect this is all still related to the PCI devices themselves being probed much earlier in the overall PCI initialization sequence when the PCI controller is probed later in the boot sequence, whereas PCI device probe is deferred until the overall PCI initialization sequence is complete if the PCI controller is probed very early in the boot sequence.

Quoted 4 lines

I don't know what to apply your patches to (they don't apply cleanly to v3.6-rc2), so I can't see exactly what you're doing. But it looks like you might be calling pci_bus_add_devices() before pci_bus_assign_resource(), which isn't going to work.

Yes, that's exactly what is happening.

PCIe initialization starts in arch/arm/mach-tegra/pci.e tegra_pcie_init() which calls arch/arm/kernel/bios32.c pci_common_init(). That function first calls pcibios_init_hw() (in the same file, more about this later) and then loops over PCI buses, calling amongst other things pci_bus_assign_resources() then pci_bus_add_devices().

The problem is that ARM's pcibios_init_hw() calls pci_scan_root_bus() (or a host-driver-specific function which that also calls pci_scan_root_bus() in Tegra's case) which in turn calls pci_bus_add_devices() right at the end, before control has returned to pci_common_init() and hence before pci_bus_assign_resources() has been called.

Quoted 6 lines

If I modify pci_scan_root_bus() and remove the call to pci_bus_add_devices(), everything works as expected.

So, I guess the question is: Should ARM's pcibios_init_hw() not be calling pci_scan_root_bus(), or at least presumably the ARM PCI code needs to do things in a slightly different order?

Maybe pci_scan_root_bus() should be calling pci_bus_assign_resources()? Or a new function could be added which also assigns the resources.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120814/fff2b990/attachment.sig>

maintainer
#65 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 48 lines · Thierry Reding
Quoted 47 lines · Stephen Warren
Quoted 1 line · Bjorn Helgaas

On Mon, Aug 13, 2012 at 11:47 AM, Stephen Warren <[email protected]> wrote:

...

Quoted 24 lines
Quoted 18 lines

whereas for a device tree boot:

(same):

Quoted 4 lines
[    2.112217] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    2.117635] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    2.124690] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    2.131731] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

... (request region happens early)

Quoted 4 lines
[    2.179838] r8169 0000:01:00.0: BAR 0: requesting [io  0x0000-0x00ff]
[    2.193312] r8169 0000:01:00.0: BAR 2: requesting [mem 0x00000000-0x00000fff 64bit pref]
[    2.201397] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.209742] r8169 0000:01:00.0: (unregistered net_device): could not request regions

... (same, just happens too late)

Quoted 4 lines
[    2.236818] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    2.244027] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    2.251794] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    2.259542] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]
Quoted 5 lines

I suspect this is all still related to the PCI devices themselves being probed much earlier in the overall PCI initialization sequence when the PCI controller is probed later in the boot sequence, whereas PCI device probe is deferred until the overall PCI initialization sequence is complete if the PCI controller is probed very early in the boot sequence.

Quoted 4 lines

I don't know what to apply your patches to (they don't apply cleanly to v3.6-rc2), so I can't see exactly what you're doing. But it looks like you might be calling pci_bus_add_devices() before pci_bus_assign_resource(), which isn't going to work.

Yes, that's exactly what is happening.

PCIe initialization starts in arch/arm/mach-tegra/pci.e tegra_pcie_init() which calls arch/arm/kernel/bios32.c pci_common_init(). That function first calls pcibios_init_hw() (in the same file, more about this later) and then loops over PCI buses, calling amongst other things pci_bus_assign_resources() then pci_bus_add_devices().

The problem is that ARM's pcibios_init_hw() calls pci_scan_root_bus() (or a host-driver-specific function which that also calls pci_scan_root_bus() in Tegra's case) which in turn calls pci_bus_add_devices() right at the end, before control has returned to pci_common_init() and hence before pci_bus_assign_resources() has been called.

Quoted 6 lines
Quoted 6 lines

If I modify pci_scan_root_bus() and remove the call to pci_bus_add_devices(), everything works as expected.

So, I guess the question is: Should ARM's pcibios_init_hw() not be calling pci_scan_root_bus(), or at least presumably the ARM PCI code needs to do things in a slightly different order?

I think you need to do something like this instead of using pci_scan_root_bus():

pci_create_root_bus()
pci_scan_child_bus()
pci_bus_assign_resources()
pci_bus_add_devices()

This is the effective order used by most of the pci_create_root_bus() callers.

Quoted 2 lines

Maybe pci_scan_root_bus() should be calling pci_bus_assign_resources()? Or a new function could be added which also assigns the resources.

Yes, it probably should. I'm nervous about just throwing it in there without quite a bit more analysis, but that's definitely the direction I think we should be heading.

Bjorn

#66 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 57 lines · Bjorn Helgaas
Quoted 48 lines · Thierry Reding
Quoted 47 lines · Stephen Warren
Quoted 1 line · Bjorn Helgaas

On Mon, Aug 13, 2012 at 11:47 AM, Stephen Warren <[email protected]> wrote:

...

Quoted 24 lines
Quoted 18 lines

whereas for a device tree boot:

(same):

Quoted 4 lines
[    2.112217] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    2.117635] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    2.124690] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    2.131731] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

... (request region happens early)

Quoted 4 lines
[    2.179838] r8169 0000:01:00.0: BAR 0: requesting [io  0x0000-0x00ff]
[    2.193312] r8169 0000:01:00.0: BAR 2: requesting [mem 0x00000000-0x00000fff 64bit pref]
[    2.201397] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.209742] r8169 0000:01:00.0: (unregistered net_device): could not request regions

... (same, just happens too late)

Quoted 4 lines
[    2.236818] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    2.244027] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    2.251794] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    2.259542] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]
Quoted 5 lines

I suspect this is all still related to the PCI devices themselves being probed much earlier in the overall PCI initialization sequence when the PCI controller is probed later in the boot sequence, whereas PCI device probe is deferred until the overall PCI initialization sequence is complete if the PCI controller is probed very early in the boot sequence.

Quoted 4 lines

I don't know what to apply your patches to (they don't apply cleanly to v3.6-rc2), so I can't see exactly what you're doing. But it looks like you might be calling pci_bus_add_devices() before pci_bus_assign_resource(), which isn't going to work.

Yes, that's exactly what is happening.

PCIe initialization starts in arch/arm/mach-tegra/pci.e tegra_pcie_init() which calls arch/arm/kernel/bios32.c pci_common_init(). That function first calls pcibios_init_hw() (in the same file, more about this later) and then loops over PCI buses, calling amongst other things pci_bus_assign_resources() then pci_bus_add_devices().

The problem is that ARM's pcibios_init_hw() calls pci_scan_root_bus() (or a host-driver-specific function which that also calls pci_scan_root_bus() in Tegra's case) which in turn calls pci_bus_add_devices() right at the end, before control has returned to pci_common_init() and hence before pci_bus_assign_resources() has been called.

Quoted 6 lines
Quoted 6 lines

If I modify pci_scan_root_bus() and remove the call to pci_bus_add_devices(), everything works as expected.

So, I guess the question is: Should ARM's pcibios_init_hw() not be calling pci_scan_root_bus(), or at least presumably the ARM PCI code needs to do things in a slightly different order?

Quoted 8 lines

I think you need to do something like this instead of using pci_scan_root_bus():

pci_create_root_bus()
pci_scan_child_bus()
pci_bus_assign_resources()
pci_bus_add_devices()

This is the effective order used by most of the pci_create_root_bus() callers.

That would pretty much duplicate everything in pci_scan_root_bus(). That might cause divergence down the road.

Can't we make the call to pci_bus_add_devices() optional in pci_scan_root_bus() somehow; one of:

* Add a parameter to pci_scan_root_bus() controlling this.

(rather a large patch)

* Split pci_scan_root_bus() into pci_scan_root_bus() and pci_scan_root_bus_no_add(), such that pci_scan_root_bus() is just a wrapper that calls pci_scan_root_bus_no_add() then pci_bus_add_devices().

(very simple patch, and the new function can easily be used as/when it's needed, e.g. enabled just for Tegra in 3.6 to reduce risk of regressions)

* Add a flag to struct pci_bus that requests pci_scan_root_bus() skip the call to pci_bus_add_devices().

(a flag in the bus struct just for one function seems a little circuitous, but perhaps OK)

* ifdef out the call to pci_bus_add_devices(), if building for ARM.

(very simple, and probably correct)

Actually, I'm not totally convinced some other archs shouldn't skip this too; while I couldn't find any other arch that explicitly calls pci_bus_assign_resources() and pci_bus_add_devices() after pci_scan_root_bus(), I did see some that call pci_assign_unassigned_resources() which seems like it might be due to a similar situation?

* Add another pcibios_*() callback that pci_scan_root_bus() calls to determine whether to call pci_bus_add_devices(), with default implementation.

#67 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 65 lines · Stephen Warren
Quoted 64 lines · Bjorn Helgaas
Quoted 48 lines · Thierry Reding
Quoted 47 lines · Stephen Warren
Quoted 1 line · Bjorn Helgaas

On Mon, Aug 13, 2012 at 11:47 AM, Stephen Warren <[email protected]> wrote:

...

Quoted 24 lines
Quoted 18 lines

whereas for a device tree boot:

(same):

Quoted 4 lines
[    2.112217] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    2.117635] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    2.124690] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    2.131731] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

... (request region happens early)

Quoted 4 lines
[    2.179838] r8169 0000:01:00.0: BAR 0: requesting [io  0x0000-0x00ff]
[    2.193312] r8169 0000:01:00.0: BAR 2: requesting [mem 0x00000000-0x00000fff 64bit pref]
[    2.201397] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.209742] r8169 0000:01:00.0: (unregistered net_device): could not request regions

... (same, just happens too late)

Quoted 4 lines
[    2.236818] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    2.244027] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    2.251794] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    2.259542] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]
Quoted 5 lines

I suspect this is all still related to the PCI devices themselves being probed much earlier in the overall PCI initialization sequence when the PCI controller is probed later in the boot sequence, whereas PCI device probe is deferred until the overall PCI initialization sequence is complete if the PCI controller is probed very early in the boot sequence.

Quoted 4 lines

I don't know what to apply your patches to (they don't apply cleanly to v3.6-rc2), so I can't see exactly what you're doing. But it looks like you might be calling pci_bus_add_devices() before pci_bus_assign_resource(), which isn't going to work.

Yes, that's exactly what is happening.

PCIe initialization starts in arch/arm/mach-tegra/pci.e tegra_pcie_init() which calls arch/arm/kernel/bios32.c pci_common_init(). That function first calls pcibios_init_hw() (in the same file, more about this later) and then loops over PCI buses, calling amongst other things pci_bus_assign_resources() then pci_bus_add_devices().

The problem is that ARM's pcibios_init_hw() calls pci_scan_root_bus() (or a host-driver-specific function which that also calls pci_scan_root_bus() in Tegra's case) which in turn calls pci_bus_add_devices() right at the end, before control has returned to pci_common_init() and hence before pci_bus_assign_resources() has been called.

Quoted 6 lines
Quoted 6 lines

If I modify pci_scan_root_bus() and remove the call to pci_bus_add_devices(), everything works as expected.

So, I guess the question is: Should ARM's pcibios_init_hw() not be calling pci_scan_root_bus(), or at least presumably the ARM PCI code needs to do things in a slightly different order?

I think you need to do something like this instead of using pci_scan_root_bus():

pci_create_root_bus()
pci_scan_child_bus()
pci_bus_assign_resources()
pci_bus_add_devices()

Quoted 7 lines
Quoted 1 line

This is the effective order used by most of the pci_create_root_bus() callers.

That would pretty much duplicate everything in pci_scan_root_bus(). That might cause divergence down the road.

Can't we make the call to pci_bus_add_devices() optional in pci_scan_root_bus() somehow; one of:

Sigh, that turns out not to work correctly; it solves at least this part of the problem when booting using device tree, but when booting using a board file, it causes the IRQ number passed to the PCIe device to be bogus:-(

I give up for now.

#68 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 1 line · Stephen Warren

On 08/14/2012 04:58 PM, Stephen Warren wrote:

...

Quoted 9 lines
Quoted 2 lines

Can't we make the call to pci_bus_add_devices() optional in pci_scan_root_bus() somehow; one of:

Sigh, that turns out not to work correctly; it solves at least this part of the problem when booting using device tree, but when booting using a board file, it causes the IRQ number passed to the PCIe device to be bogus:-(

I give up for now.

I think the appropriate workaround for Tegra in 3.6 is to simply make any drivers for PCIe-based devices be modules instead of built-in, as Thierry hinted at much earlier in the thread. I've validated that the Ethernet works just fine on TrimSlice with that change, booting v3.6-rc1 using either board files or device tree.

For 3.7, we should continue the discussion about a real fix; I'll look into the change Bjorn requested and see if it works, although given that hacking pci_scan_root_bus as described immediately previously in this thread caused a regression when booting using a board file, and the fact that board files are no longer supported on Tegra, I'm not too confident in the outcome...

#69 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 11 lines · Stephen Warren
Quoted 1 line · Stephen Warren

On 08/14/2012 04:58 PM, Stephen Warren wrote:

...

Quoted 8 lines
Quoted 2 lines

Can't we make the call to pci_bus_add_devices() optional in pci_scan_root_bus() somehow; one of:

Sigh, that turns out not to work correctly; it solves at least this part of the problem when booting using device tree, but when booting using a board file, it causes the IRQ number passed to the PCIe device to be bogus:-(

Quoted 7 lines
Quoted 1 line

I give up for now.

I think the appropriate workaround for Tegra in 3.6 is to simply make any drivers for PCIe-based devices be modules instead of built-in, as Thierry hinted at much earlier in the thread. I've validated that the Ethernet works just fine on TrimSlice with that change, booting v3.6-rc1 using either board files or device tree.

That's certainly the easiest and least error-prone solution.

Quoted 6 lines

For 3.7, we should continue the discussion about a real fix; I'll look into the change Bjorn requested and see if it works, although given that hacking pci_scan_root_bus as described immediately previously in this thread caused a regression when booting using a board file, and the fact that board files are no longer supported on Tegra, I'm not too confident in the outcome...

I don't understand this last part. If the problem is there when booting from board files and the board files are removed, doesn't that remove the problem as well? =)

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120815/7bce318a/attachment-0001.sig>

#70 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 31 lines · Thierry Reding
Quoted 11 lines · Stephen Warren
Quoted 1 line · Stephen Warren

On 08/14/2012 04:58 PM, Stephen Warren wrote:

...

Quoted 8 lines
Quoted 2 lines

Can't we make the call to pci_bus_add_devices() optional in pci_scan_root_bus() somehow; one of:

Sigh, that turns out not to work correctly; it solves at least this part of the problem when booting using device tree, but when booting using a board file, it causes the IRQ number passed to the PCIe device to be bogus:-(

Quoted 8 lines
Quoted 1 line

I give up for now.

I think the appropriate workaround for Tegra in 3.6 is to simply make any drivers for PCIe-based devices be modules instead of built-in, as Thierry hinted at much earlier in the thread. I've validated that the Ethernet works just fine on TrimSlice with that change, booting v3.6-rc1 using either board files or device tree.

That's certainly the easiest and least error-prone solution.

Quoted 7 lines

For 3.7, we should continue the discussion about a real fix; I'll look into the change Bjorn requested and see if it works, although given that hacking pci_scan_root_bus as described immediately previously in this thread caused a regression when booting using a board file, and the fact that board files are no longer supported on Tegra, I'm not too confident in the outcome...

Quoted 3 lines

I don't understand this last part. If the problem is there when booting from board files and the board files are removed, doesn't that remove the problem as well? =)

It does for ARM SoCs/CPUs exclusively using device tree, but not all ARM systems are converting to device tree, so the fact that Tegra has makes it harder for me not to break anything else.

#71 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 32 lines · Stephen Warren
Quoted 31 lines · Thierry Reding
Quoted 11 lines · Stephen Warren
Quoted 1 line · Stephen Warren

On 08/14/2012 04:58 PM, Stephen Warren wrote:

...

Quoted 8 lines
Quoted 2 lines

Can't we make the call to pci_bus_add_devices() optional in pci_scan_root_bus() somehow; one of:

Sigh, that turns out not to work correctly; it solves at least this part of the problem when booting using device tree, but when booting using a board file, it causes the IRQ number passed to the PCIe device to be bogus:-(

Quoted 8 lines
Quoted 1 line

I give up for now.

I think the appropriate workaround for Tegra in 3.6 is to simply make any drivers for PCIe-based devices be modules instead of built-in, as Thierry hinted at much earlier in the thread. I've validated that the Ethernet works just fine on TrimSlice with that change, booting v3.6-rc1 using either board files or device tree.

That's certainly the easiest and least error-prone solution.

Quoted 7 lines

For 3.7, we should continue the discussion about a real fix; I'll look into the change Bjorn requested and see if it works, although given that hacking pci_scan_root_bus as described immediately previously in this thread caused a regression when booting using a board file, and the fact that board files are no longer supported on Tegra, I'm not too confident in the outcome...

Quoted 7 lines
Quoted 3 lines

I don't understand this last part. If the problem is there when booting from board files and the board files are removed, doesn't that remove the problem as well? =)

It does for ARM SoCs/CPUs exclusively using device tree, but not all ARM systems are converting to device tree, so the fact that Tegra has makes it harder for me not to break anything else.

I think the best road to a real fix would be to implement a custom scan function for Tegra along the lines of what Bjorn suggested. Ideally, this implementation should eventually converge to what's done on other architectures. At that point maybe ARM can completely be converted to this new generic implementation and the Tegra-specific hook removed.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120815/4ecd1b42/attachment-0001.sig>

#72 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

In reply to Stephen Warren
Quoted 71 lines · Stephen Warren
Quoted 70 lines · Stephen Warren
Quoted 57 lines · Bjorn Helgaas
Quoted 48 lines · Thierry Reding
Quoted 47 lines · Stephen Warren
Quoted 1 line · Bjorn Helgaas

On Mon, Aug 13, 2012 at 11:47 AM, Stephen Warren <[email protected]> wrote:

...

Quoted 24 lines
Quoted 18 lines

whereas for a device tree boot:

(same):

Quoted 4 lines
[    2.112217] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    2.117635] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    2.124690] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    2.131731] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

... (request region happens early)

Quoted 4 lines
[    2.179838] r8169 0000:01:00.0: BAR 0: requesting [io  0x0000-0x00ff]
[    2.193312] r8169 0000:01:00.0: BAR 2: requesting [mem 0x00000000-0x00000fff 64bit pref]
[    2.201397] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.209742] r8169 0000:01:00.0: (unregistered net_device): could not request regions

... (same, just happens too late)

Quoted 4 lines
[    2.236818] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    2.244027] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    2.251794] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    2.259542] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]
Quoted 5 lines

I suspect this is all still related to the PCI devices themselves being probed much earlier in the overall PCI initialization sequence when the PCI controller is probed later in the boot sequence, whereas PCI device probe is deferred until the overall PCI initialization sequence is complete if the PCI controller is probed very early in the boot sequence.

Quoted 4 lines

I don't know what to apply your patches to (they don't apply cleanly to v3.6-rc2), so I can't see exactly what you're doing. But it looks like you might be calling pci_bus_add_devices() before pci_bus_assign_resource(), which isn't going to work.

Yes, that's exactly what is happening.

PCIe initialization starts in arch/arm/mach-tegra/pci.e tegra_pcie_init() which calls arch/arm/kernel/bios32.c pci_common_init(). That function first calls pcibios_init_hw() (in the same file, more about this later) and then loops over PCI buses, calling amongst other things pci_bus_assign_resources() then pci_bus_add_devices().

The problem is that ARM's pcibios_init_hw() calls pci_scan_root_bus() (or a host-driver-specific function which that also calls pci_scan_root_bus() in Tegra's case) which in turn calls pci_bus_add_devices() right at the end, before control has returned to pci_common_init() and hence before pci_bus_assign_resources() has been called.

Quoted 6 lines
Quoted 6 lines

If I modify pci_scan_root_bus() and remove the call to pci_bus_add_devices(), everything works as expected.

So, I guess the question is: Should ARM's pcibios_init_hw() not be calling pci_scan_root_bus(), or at least presumably the ARM PCI code needs to do things in a slightly different order?

Quoted 8 lines

I think you need to do something like this instead of using pci_scan_root_bus():

pci_create_root_bus()
pci_scan_child_bus()
pci_bus_assign_resources()
pci_bus_add_devices()

This is the effective order used by most of the pci_create_root_bus() callers.

That would pretty much duplicate everything in pci_scan_root_bus(). That might cause divergence down the road.

Quoted 7 lines
Quoted 2 lines

Can't we make the call to pci_bus_add_devices() optional in pci_scan_root_bus() somehow; one of:

Sigh, that turns out not to work correctly; it solves at least this part of the problem when booting using device tree, but when booting using a board file, it causes the IRQ number passed to the PCIe device to be bogus:-(

The reason this fails is because the following happens after pci_scan_bus_root():

	pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);

(in arch/arm/kernel/bios32.c:pci_common_init())

So, if I replace the call to pci_scan_root_bus() with the code you wrote above, then the IRQ numbers aren't assigned into the pci_dev structures until after they're device_add()ed, and hence probed().

Ideally, I could just add a call to pci_fixup_irqs() right before the call to pci_bus_add_devices() in the code you wrote above. However, that won't work, because pci_fixup_irqs() finds all the PCI devices to fix up by searching the list of devices that pci_bus_add_devices() adds to:-(

I guess it's a pretty basic premise of the current PCI code that all the PCI scanning happens well before any device drivers are registered, which in turn means that device_add() doesn't trigger the device's probe() until much later, after all the fixups and resource assignments are done?

#73 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 5 lines · Stephen Warren

I guess it's a pretty basic premise of the current PCI code that all the PCI scanning happens well before any device drivers are registered, which in turn means that device_add() doesn't trigger the device's probe() until much later, after all the fixups and resource assignments are done?

Are you saying that the PCI layer is again screwed up after all my hard work several years ago to ensure that PCI devices are properly setup _before_ they're made available to the PCI drivers then? That was around the time I was looking at Cardbus stuff, ensuring that that worked with the same guarantees.

Not amused.

What is wrong with the "probe devices, apply fixups, setup resources, apply more fixups, publish" process that it's had to be yet again broken?

#74 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 13 lines · Russell King - ARM Linux
Quoted 5 lines · Stephen Warren

I guess it's a pretty basic premise of the current PCI code that all the PCI scanning happens well before any device drivers are registered, which in turn means that device_add() doesn't trigger the device's probe() until much later, after all the fixups and resource assignments are done?

Are you saying that the PCI layer is again screwed up after all my hard work several years ago to ensure that PCI devices are properly setup _before_ they're made available to the PCI drivers then? That was around the time I was looking at Cardbus stuff, ensuring that that worked with the same guarantees.

Quoted 5 lines

Not amused.

What is wrong with the "probe devices, apply fixups, setup resources, apply more fixups, publish" process that it's had to be yet again broken?

I must admit, I'm having a hard time finding when the code worked like that; ARM's bios32.c:pcibios_init_hw() seems to have always called pci_scan_root_bus(), or ops function hw->scan(), which at least in the 1 PCIe controller driver I looked at, in turn always called either pci_scan_root_bus() or another similar function that I believe always called pci_bus_add_devices(), which is before pci_common_init() could assign the resources. Maybe I'm just looking at the wrong PCIe controller driver, or not looking back far enough in git history (or pre-git)? If you could point out when it was working as you describe (which sounds reasonable), I'd be interested in tracing the history from there to see when/why it changed.

maintainer
#75 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

In reply to Russell King - ARM Linux
Quoted 13 lines · Russell King - ARM Linux
Quoted 5 lines · Stephen Warren

I guess it's a pretty basic premise of the current PCI code that all the PCI scanning happens well before any device drivers are registered, which in turn means that device_add() doesn't trigger the device's probe() until much later, after all the fixups and resource assignments are done?

Are you saying that the PCI layer is again screwed up after all my hard work several years ago to ensure that PCI devices are properly setup _before_ they're made available to the PCI drivers then? That was around the time I was looking at Cardbus stuff, ensuring that that worked with the same guarantees.

Quoted 5 lines

Not amused.

What is wrong with the "probe devices, apply fixups, setup resources, apply more fixups, publish" process that it's had to be yet again broken?

It seems that there are some bugs in the PCI layer, no doubt introduced after all your hard work. We'll do our best to fix them.

The particular issue of pci_fixup_irqs() has been on my list for a while, and we talked about it at the recent PCI mini-summit. It's clearly broken that we do this with for_each_pci_dev() once at boot-time because that does nothing for hot-added devices. It's also broken that it is called after device_add() because the core shouldn't touch the device after it's available to drivers.

This should get fixed reasonably soon, probably not in v3.6, but hopefully in v3.7. It's not completely trivial because many arches have the same problem, and we need to fix all of them.

Bjorn

#76 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 31 lines · Bjorn Helgaas
Quoted 13 lines · Russell King - ARM Linux
Quoted 5 lines · Stephen Warren

I guess it's a pretty basic premise of the current PCI code that all the PCI scanning happens well before any device drivers are registered, which in turn means that device_add() doesn't trigger the device's probe() until much later, after all the fixups and resource assignments are done?

Are you saying that the PCI layer is again screwed up after all my hard work several years ago to ensure that PCI devices are properly setup _before_ they're made available to the PCI drivers then? That was around the time I was looking at Cardbus stuff, ensuring that that worked with the same guarantees.

Quoted 5 lines

Not amused.

What is wrong with the "probe devices, apply fixups, setup resources, apply more fixups, publish" process that it's had to be yet again broken?

It seems that there are some bugs in the PCI layer, no doubt introduced after all your hard work. We'll do our best to fix them.

The particular issue of pci_fixup_irqs() has been on my list for a while, and we talked about it at the recent PCI mini-summit. It's clearly broken that we do this with for_each_pci_dev() once at boot-time because that does nothing for hot-added devices. It's also broken that it is called after device_add() because the core shouldn't touch the device after it's available to drivers.

Quoted 3 lines

This should get fixed reasonably soon, probably not in v3.6, but hopefully in v3.7. It's not completely trivial because many arches have the same problem, and we need to fix all of them.

Has there been any progress on this? I've read the PCI mini summit notes that you posted a while ago but it doesn't mention the pci_fixup_irqs() issue. Was there some decision as to how this should be solved? If I understand correctly this should solve the issue that Stephen has been seeing with bogus interrupt assignments, so we'll need this to fix PCIe on Tegra. Is there anything I can do to help move this forward?

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120918/8c0a26ef/attachment.sig>

maintainer
#77 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

Quoted 36 lines · Thierry Reding
Quoted 31 lines · Bjorn Helgaas
Quoted 13 lines · Russell King - ARM Linux
Quoted 5 lines · Stephen Warren

I guess it's a pretty basic premise of the current PCI code that all the PCI scanning happens well before any device drivers are registered, which in turn means that device_add() doesn't trigger the device's probe() until much later, after all the fixups and resource assignments are done?

Are you saying that the PCI layer is again screwed up after all my hard work several years ago to ensure that PCI devices are properly setup _before_ they're made available to the PCI drivers then? That was around the time I was looking at Cardbus stuff, ensuring that that worked with the same guarantees.

Quoted 5 lines

Not amused.

What is wrong with the "probe devices, apply fixups, setup resources, apply more fixups, publish" process that it's had to be yet again broken?

It seems that there are some bugs in the PCI layer, no doubt introduced after all your hard work. We'll do our best to fix them.

The particular issue of pci_fixup_irqs() has been on my list for a while, and we talked about it at the recent PCI mini-summit. It's clearly broken that we do this with for_each_pci_dev() once at boot-time because that does nothing for hot-added devices. It's also broken that it is called after device_add() because the core shouldn't touch the device after it's available to drivers.

Quoted 3 lines

This should get fixed reasonably soon, probably not in v3.6, but hopefully in v3.7. It's not completely trivial because many arches have the same problem, and we need to fix all of them.

Quoted 6 lines

Has there been any progress on this? I've read the PCI mini summit notes that you posted a while ago but it doesn't mention the pci_fixup_irqs() issue. Was there some decision as to how this should be solved? If I understand correctly this should solve the issue that Stephen has been seeing with bogus interrupt assignments, so we'll need this to fix PCIe on Tegra. Is there anything I can do to help move this forward?

I didn't mention pci_fixup_irqs() by name in the notes, but that's part of what I meant by "device setup being done by initcalls" as a hot-plug issue. I know Myron Stowe expressed interest in working on that, but I don't think he's had a chance to do anything yet (at least, I haven't seen anything yet).

I don't have time to fix it myself, so moving it forward is just a matter of somebody doing the work and posting the patches. I think that code just needs to be moved to some pcibios hook (possibly a new one) that's called in the device_add path.

Bjorn

maintainer
#78 lore raw

v3 cover ARM: tegra: Add PCIe device tree support

In reply to Stephen Warren
Quoted 65 lines · Stephen Warren
Quoted 64 lines · Bjorn Helgaas
Quoted 48 lines · Thierry Reding
Quoted 47 lines · Stephen Warren
Quoted 1 line · Bjorn Helgaas

On Mon, Aug 13, 2012 at 11:47 AM, Stephen Warren <[email protected]> wrote:

...

Quoted 24 lines
Quoted 18 lines

whereas for a device tree boot:

(same):

Quoted 4 lines
[    2.112217] pci 0000:01:00.0: reg 10: [io  0x0000-0x00ff]
[    2.117635] pci 0000:01:00.0: reg 18: [mem 0x00000000-0x00000fff 64bit pref]
[    2.124690] pci 0000:01:00.0: reg 20: [mem 0x00000000-0x00003fff 64bit pref]
[    2.131731] pci 0000:01:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]

... (request region happens early)

Quoted 4 lines
[    2.179838] r8169 0000:01:00.0: BAR 0: requesting [io  0x0000-0x00ff]
[    2.193312] r8169 0000:01:00.0: BAR 2: requesting [mem 0x00000000-0x00000fff 64bit pref]
[    2.201397] r8169 0000:01:00.0: BAR 2: can't reserve [mem 0x00000000-0x00000fff 64bit pref]
[    2.209742] r8169 0000:01:00.0: (unregistered net_device): could not request regions

... (same, just happens too late)

Quoted 4 lines
[    2.236818] pci 0000:01:00.0: BAR 6: assigned [mem 0xa0000000-0xa001ffff pref]
[    2.244027] pci 0000:01:00.0: BAR 4: assigned [mem 0xa0020000-0xa0023fff 64bit pref]
[    2.251794] pci 0000:01:00.0: BAR 2: assigned [mem 0xa0024000-0xa0024fff 64bit pref]
[    2.259542] pci 0000:01:00.0: BAR 0: assigned [io  0x1000-0x10ff]
Quoted 5 lines

I suspect this is all still related to the PCI devices themselves being probed much earlier in the overall PCI initialization sequence when the PCI controller is probed later in the boot sequence, whereas PCI device probe is deferred until the overall PCI initialization sequence is complete if the PCI controller is probed very early in the boot sequence.

Quoted 4 lines

I don't know what to apply your patches to (they don't apply cleanly to v3.6-rc2), so I can't see exactly what you're doing. But it looks like you might be calling pci_bus_add_devices() before pci_bus_assign_resource(), which isn't going to work.

Yes, that's exactly what is happening.

PCIe initialization starts in arch/arm/mach-tegra/pci.e tegra_pcie_init() which calls arch/arm/kernel/bios32.c pci_common_init(). That function first calls pcibios_init_hw() (in the same file, more about this later) and then loops over PCI buses, calling amongst other things pci_bus_assign_resources() then pci_bus_add_devices().

The problem is that ARM's pcibios_init_hw() calls pci_scan_root_bus() (or a host-driver-specific function which that also calls pci_scan_root_bus() in Tegra's case) which in turn calls pci_bus_add_devices() right at the end, before control has returned to pci_common_init() and hence before pci_bus_assign_resources() has been called.

Quoted 6 lines
Quoted 6 lines

If I modify pci_scan_root_bus() and remove the call to pci_bus_add_devices(), everything works as expected.

So, I guess the question is: Should ARM's pcibios_init_hw() not be calling pci_scan_root_bus(), or at least presumably the ARM PCI code needs to do things in a slightly different order?

I think you need to do something like this instead of using pci_scan_root_bus():

pci_create_root_bus()
pci_scan_child_bus()
pci_bus_assign_resources()
pci_bus_add_devices()

Quoted 4 lines
Quoted 1 line

This is the effective order used by most of the pci_create_root_bus() callers.

That would pretty much duplicate everything in pci_scan_root_bus(). That might cause divergence down the road.

That's true, but it is what most other architectures do, and if you do it the same way, we'll be able to converge things more easily later.

Quoted 17 lines

Can't we make the call to pci_bus_add_devices() optional in pci_scan_root_bus() somehow; one of:

* Add a parameter to pci_scan_root_bus() controlling this.

(rather a large patch)

* Split pci_scan_root_bus() into pci_scan_root_bus() and pci_scan_root_bus_no_add(), such that pci_scan_root_bus() is just a wrapper that calls pci_scan_root_bus_no_add() then pci_bus_add_devices().

(very simple patch, and the new function can easily be used as/when it's needed, e.g. enabled just for Tegra in 3.6 to reduce risk of regressions)

* Add a flag to struct pci_bus that requests pci_scan_root_bus() skip the call to pci_bus_add_devices().

Quoted 6 lines

(a flag in the bus struct just for one function seems a little circuitous, but perhaps OK)

* ifdef out the call to pci_bus_add_devices(), if building for ARM.

(very simple, and probably correct)

I'd rather not add more variants of pci_scan_root_bus(). We already have several very similar things in drivers/pci/probe.c:

pci_scan_bus()
pci_scan_bus_parented()
pci_scan_root_bus()

And in addition, we have many callers of pci_create_root_bus() that look very much like one of these. I'm trying to consolidate all this, but there's a fair amount of work, and I think the simplest thing is to just use pci_create_root_bus() for now.

Quoted 6 lines

Actually, I'm not totally convinced some other archs shouldn't skip this too; while I couldn't find any other arch that explicitly calls pci_bus_assign_resources() and pci_bus_add_devices() after pci_scan_root_bus(), I did see some that call pci_assign_unassigned_resources() which seems like it might be due to a similar situation?

Yes, that does sound like a similar problem. In the past, resource assignment has been pretty much separate from enumeration, with the arch having the responsibility to enumerate, assign, then add devices.
But that is error-prone and needlessly arch-specific, and I'd like to
pull it into generic code. It's just not done yet :)

Quoted 3 lines

* Add another pcibios_*() callback that pci_scan_root_bus() calls to determine whether to call pci_bus_add_devices(), with default implementation.