On Wed, Dec 24, 2014 at 4:11 PM, Murali Karicheri <m-karicheri2@xxxxxx> wrote: > Add of_pci_dma_configure() to allow updating the dma configuration > of the pci device using the configuration from DT of the parent of > the root bridge device. > > Signed-off-by: Murali Karicheri <m-karicheri2@xxxxxx> > --- > drivers/of/of_pci.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ > include/linux/of_pci.h | 12 ++++++++ > 2 files changed, 85 insertions(+) > > diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c > index 88471d3..6d43f59 100644 > --- a/drivers/of/of_pci.c > +++ b/drivers/of/of_pci.c > @@ -229,6 +229,79 @@ parse_failed: > return err; > } > EXPORT_SYMBOL_GPL(of_pci_get_host_bridge_resources); > + > +/** > + * of_get_pci_root_bridge_parent - Helper function to get the OF node of > + * the root bridge's parent I believe this has to be a one line description for DocBook. > + * @dev: ptr to pci_dev struct of the pci device > + * > + * This function will traverse the bus up to the root bus starting with > + * the child and return the of node ptr to bridge device's parent device. > + */ > +struct device_node *of_get_pci_root_bridge_parent(struct pci_dev *dev) > +{ > + struct pci_bus *bus = dev->bus; > + struct device *bridge; > + > + while (!pci_is_root_bus(bus)) > + bus = bus->parent; > + bridge = bus->bridge; > + > + return bridge->parent->of_node; > +} > +EXPORT_SYMBOL_GPL(of_get_pci_root_bridge_parent); > + > +/** > + * of_pci_dma_configure - Setup DMA configuration > + * @dev: ptr to pci_dev struct of the pci device > + * > + * Try to get PCI devices's DMA configuration from DT and update it > + * accordingly. This is similar to of_dma_configure() in of/platform.c > + */ > +void of_pci_dma_configure(struct pci_dev *pci_dev) > +{ > + struct device *dev = &pci_dev->dev; > + u64 dma_addr, paddr, size; > + struct device_node *parent_np; > + unsigned long offset; > + bool coherent; > + int ret; > + > + parent_np = of_get_pci_root_bridge_parent(pci_dev); > + > + if (parent_np) { Save a level of indentation and do: if (!parent_np) return; > + /* > + * Set default dma-mask to 32 bit. Drivers are expected to setup > + * the correct supported dma_mask. > + */ > + dev->coherent_dma_mask = DMA_BIT_MASK(32); > + > + /* > + * Set it to coherent_dma_mask by default if the architecture > + * code has not set it. > + */ > + if (!dev->dma_mask) > + dev->dma_mask = &dev->coherent_dma_mask; > + > + ret = of_dma_get_range(parent_np, &dma_addr, &paddr, &size); > + if (ret < 0) { > + dma_addr = offset = 0; > + size = dev->coherent_dma_mask + 1; > + } else { > + offset = PFN_DOWN(paddr - dma_addr); > + dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset); > + } > + dev->dma_pfn_offset = offset; > + > + coherent = of_dma_is_coherent(parent_np); > + dev_dbg(dev, "device is%sdma coherent\n", > + coherent ? " " : " not "); > + > + arch_setup_dma_ops(dev, dma_addr, size, NULL, coherent); This is the same code as of_dma_configure. The only difference I see is which node ptr is passed to of_dma_get_range. You need to make that a function param of of_dma_configure. of_dma_configure also has iommu handling now. You will probably need something similar for PCI in that you setup an iommu based on the root bus DT properties. Rob -- 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