Thread (63 messages) 63 messages, 10 authors, 2014-06-02

[PATCH v3 4/7] of: configure the platform device dma parameters

From: bhelgaas@google.com (Bjorn Helgaas)
Date: 2014-05-05 22:28:26
Also in: linux-devicetree, lkml

On Mon, May 5, 2014 at 2:55 PM, Arnd Bergmann [off-list ref] wrote:
On Monday 05 May 2014 14:45:21 Bjorn Helgaas wrote:
quoted
[+cc Ben, Chris]

On Fri, May 2, 2014 at 12:59 PM, Arnd Bergmann [off-list ref] wrote:
quoted
On Friday 02 May 2014 10:54:59 Bjorn Helgaas wrote:
quoted
quoted
+static void of_dma_configure(struct device *dev)
+{
+     u64 dma_addr, paddr, size;
+     int ret;
+
+     dev->coherent_dma_mask = DMA_BIT_MASK(32);
+     if (!dev->dma_mask)
+             dev->dma_mask = &dev->coherent_dma_mask;
+
+     /*
+      * if dma-coherent property exist, call arch hook to setup
+      * dma coherent operations.
+      */
+     if (of_dma_is_coherent(dev->of_node)) {
+             set_arch_dma_coherent_ops(dev);
+             dev_dbg(dev, "device is dma coherent\n");
+     }
+
+     /*
+      * if dma-ranges property doesn't exist - just return else
+      * setup the dma offset
+      */
+     ret = of_dma_get_range(dev->of_node, &dma_addr, &paddr, &size);
+     if ((ret == -ENODEV) || (ret < 0)) {
+             dev_dbg(dev, "no dma range information to setup\n");
+             return;
+     }
+
+     /* DMA ranges found. Calculate and set dma_pfn_offset */
+     dev->dma_pfn_offset = PFN_DOWN(paddr - dma_addr);
+     dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", dev->dma_pfn_offset);
Is this effectively the same as an IOMMU that applies a constant offset
to the bus address?  Could or should this be done by adding a simple IOMMU
driver instead of adding dma_pfn_offset to struct device?
We currently have two dma_map_ops variants on ARM (plus another set for
coherent/noncoherent differences, but we can ignore that for the sake
of this discussion): one that handles linear mappings and one that
handles IOMMUs by calling into the linux/iommu.h APIs.

I guess what you mean by 'a simple IOMMU driver' would be another
dma_map_ops implementation that is separate from real IOMMUs, right?
I suppose so; it seems like the offset could be managed inside
arm_dma_ops.  My idea of an IOMMU is something that maps bus addresses
to physical memory addresses.  That's what we're doing here; it's just
that the mapping function is very simple.  So why add something new in
struct device for it?

I think powerpc and tile do something similar in dma_direct_map_page()
and tile_pci_dma_map_page() (they store the offset in struct
dev_archdata).
Ah, so the only question is whether to store it in dev_archdata or
in device. I think the argument for using struct device directly
was that it lets us access this field from architecture independent
code. It's not important to the overall design though: we could easily
put it in dev_archdata and call an architecture specific function to
set it, if there are good reasons for keeping it out of the generic
device structure.
Well, it wasn't my *only* question, since I didn't know about the
powerpc and tile usage originally :).  Putting it in dev_archdata does
seem better because it's a similar solution to a similar problem, and
it's less public.

I still wonder whether arm, powerpc, and tile (and I just noticed
microblaze also has a similar dma_direct_map_page()) could all be
handled by attaching devices to a generic trivial IOMMU driver
parameterized with the appropriate constant offset.

What arch-independent code would access this data?  I expect that
drivers will use dma_map_page(), etc., so they should already have
both the bus and the physical address and wouldn't need it.  Shouldn't
generic code just rely on the DMA API, which might use an IOMMU or
this dma_pfn_offset internally?

Bjorn
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help