[PATCH v2 3/3] PCI: ARM: add support for generic PCI host controller
Will Deacon
will.deacon at arm.com
Thu Feb 13 06:04:02 EST 2014
Hi Arnd,
Thanks again for the comments.
On Wed, Feb 12, 2014 at 08:59:46PM +0000, Arnd Bergmann wrote:
> On Wednesday 12 February 2014 20:16:11 Will Deacon wrote:
> > +- ranges : As described in IEEE Std 1275-1994, but must provide
> > + at least a definition of one or both of IO and Memory
> > + Space.
>
> I'd say *must* provide at least non-prefetchable memory. *may* provide
> prefetchable memory and/or I/O space.
Can do. Should I enforce this in the driver too? (i.e. complain if
non-prefetchable memory is absent).
> > +Interrupt mapping is exactly as described in `Open Firmware Recommended
> > +Practice: Interrupt Mapping' and requires the following properties:
> > +
> > +- #interrupt-cells : Must be 1
> > +
> > +- interrupt-map : <see aforementioned specification>
> > +
> > +- interrupt-map-mask : <see aforementioned specification>
>
> We probably want to add an optional 'bus-range' property (the default being
> <0 255> if absent), so we don't have to map all the config space.
Yes, and that will be important given your comments later on.
> > diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> > index 47d46c6d8468..491d74c36f6a 100644
> > --- a/drivers/pci/host/Kconfig
> > +++ b/drivers/pci/host/Kconfig
> > @@ -33,4 +33,11 @@ config PCI_RCAR_GEN2
> > There are 3 internal PCI controllers available with a single
> > built-in EHCI/OHCI host controller present on each one.
> >
> > +config PCI_ARM_GENERIC
> > + bool "ARM generic PCI host controller"
> > + depends on ARM && OF
> > + help
> > + Say Y here if you want to support a simple generic PCI host
> > + controller, such as the one emulated by kvmtool.
> > +
> > endmenu
>
> Looks good for now. In the long run, I'd hope to get rid of the 'ARM'
> part here and make it work on any architecture, but that requires
> significant work that we should not depend on here.
Agreed. arm64 is the obvious next target (once Liviu's series is sorted out
-- I'm currently using a simplified port of bios32.c for testing).
> > +struct gen_pci_cfg_window {
> > + u64 cpu_phys;
> > + void __iomem *base;
> > + u8 bus;
> > + spinlock_t lock;
> > + const struct gen_pci_cfg_accessors *accessors;
> > +};
> > +
> > +struct gen_pci_resource {
> > + struct list_head list;
> > + struct resource cpu_res;
> > + resource_size_t offset;
> > +};
>
> Your gen_pci_resource is actually identical to struct pci_host_bridge_window,
> which I guess is coincidence, but it would be nice to actually use
> the standard structure to make it easier to integrate with common
> infrastructure later.
Ha, at least I managed to come up with the same struct! I'll move to the
generic version.
> > +
> > +struct gen_pci {
> > + struct device *dev;
> > + struct resource *io_res;
> > + struct list_head mem_res;
> > + struct gen_pci_cfg_window cfg;
> > +};
>
> How about making this structure derived from pci_host_bridge?
> That would already contain a lot of the members, and gets two things
> right:
>
> * it's useful to have an embedded 'struct device' here, and use dev->parent
> to point to the device from DT
> * for I/O, we actually want a pci_host_bridge_window, not just a resource,
> since we should keep track of the offset
Sure. Also, if we kill nr_controllers, then we can have a simple I/O space
allocator to populate the offset.
> > +static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus,
> > + unsigned int devfn,
> > + int where)
> > +{
> > + struct pci_sys_data *sys = bus->sysdata;
> > + struct gen_pci *pci = sys->private_data;
> > + u32 busn = bus->number;
> > +
> > + spin_lock(&pci->cfg.lock);
> > + if (pci->cfg.bus != busn) {
> > + resource_size_t offset;
> > +
> > + devm_iounmap(pci->dev, pci->cfg.base);
> > + offset = pci->cfg.cpu_phys + (busn << 20);
> > + pci->cfg.base = devm_ioremap(pci->dev, offset, SZ_1M);
> > + pci->cfg.bus = busn;
> > + }
> > +
> > + return pci->cfg.base + ((devfn << 12) | where);
> > +}
>
> Nice idea, but unfortunately broken: we need config space access from
> atomic context, since there are drivers doing that.
That aside, I just took a spin_lock so this needs fixing regardless. The
only solution I can think of then is to map all of the buses at setup time
(making bus_ranges pretty important) and hope that I don't chew through all
of vmalloc.
> > +static int gen_pci_probe(struct platform_device *pdev)
> > +{
> > + struct hw_pci hw;
> > + struct of_pci_range range;
> > + struct of_pci_range_parser parser;
> > + struct gen_pci *pci;
> > + const __be32 *reg;
> > + const struct of_device_id *of_id;
> > + struct device *dev = &pdev->dev;
> > + struct device_node *np = dev->of_node;
>
> Could you try to move almost all of this function into gen_pci_setup()?
> I suspect this will make it easier later to share this driver with other
> architectures.
I'll take a look. If we get rid of nr_controllers, as suggested later on,
the line between probe and setup is somewhat blurred.
> > +
> > + hw = (struct hw_pci) {
> > + .nr_controllers = 1,
> > + .private_data = (void **)&pci,
> > + .setup = gen_pci_setup,
> > + .map_irq = of_irq_parse_and_map_pci,
> > + .ops = &gen_pci_ops,
> > + };
> > +
> > + pci_common_init_dev(dev, &hw);
> > + return 0;
> > +}
>
> A missing part here seems to be a way to propagate errors from
> the pci_common_init_dev or gen_pci_setup back to the caller.
>
> This seems to be a result of the arm pcibios implementation not
> being meant for loadable modules, but I suspect it can be fixed.
> The nr_controllers>1 logic gets a bit in the way there, but it's
> also a model that seems to be getting out of fashion:
> kirkwood/dove/orion5x/mv78xx0 use it at the moment, but are
> migrating over to the new pci-mvebu code that doesn't as they
> get rid of the non-DT probing. pci-rcar-gen2.c uses it, but it
> seems they already ran into problems with that and are changing
> it. That pretty much leaves iop13xx as the only user, but at
> that point we can probably move the loop into iop13xx specific
> code.
Makes sense once there are no users of the field.
Will
More information about the linux-arm-kernel
mailing list