On Thu, Apr 18, 2013 at 04:27:48PM +0100, Andrew Murray wrote: > I'm trying to understand PCI I/O addressing in the kernel... (again) > > I understand that ideally you want to give PCI bus addresses to PCI > devices in the range of 0K to 64K. This seems to be achieved in > pcibios_init_resources in arm's kernel/bios32.c implementation. The ideal world (for small scale systems) is to have only one PCI host bridge, and multiple root port bridges. This way the 0->64k range can be shared between all the ports and this problem doesn't come up. Look at how the new tegra and marvell work in this regard. There are two motivations to use the low space.. Firstly some HW is just broken with 32 bit IO because x86 doesn't use it. Secondly, the legacy ISA 'no-BAR' or subtractive decode IO addresses are fixed (eg 0x3bx is VGA related) and the HW needs to be able to route them to the VGA card, independently of the PCI compliant BAR based IO routing. > What happens if you want to add another root bus? In this > implementation the start address of the io_res is now 64K and as > sys->io_offset is set to 0 the bus addresses under this second root > bus will be 64K-128K - which I assume may break some things. In this case you want to set io_offset for each host bridge to translate 64k*nr -> 0 (ie, don't set it to 0) and IO map the right 64k of MMIO space to 64k*nr to make this work. The translation should look like: Linux driver does IO to 64k+1 ARM io port wrapper translates 64k+1 to (IO base + 64k+1) virtual address TLB translates (IO base + 64k+1) to physical X+1 HW converts physical X+1 to PCI IO transaction with IO address 1 The io_offset, which impacts pci_add_resource_offset, is used to tell the Linux PCI core that BAR address 1, is actually seen in Linux as IO 64k+1. But, if you do this, I really recommend using separate PCI domains. It is very wonky to see a single PCI bus hierarchy with overlapping BAR addresses. Using proper bridges and sharing the space like x86 does is vastly preferred, IMHO. > And to allow subsequent busses to use I/O starting from 0, you'd have to set > sys->io_offset to 64K*nr and adapt functions such as pci_iomap to use the > offset? I think all the support is already there? The translation happens in the PCI core when working with BARs, the Linux struct resource layer already has io_offset included. The only impact the offset has is in how the PCI core deals with BARs. Regards, Jason -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html