Re: [PATCH 1/1] arm/dts: Tegra30: Add device tree support for SMMU
On Wednesday 18 April 2012, Hiroshi Doyu wrote: If we can consider IOMMU as one of the implementation of DMA(Direct Memory Access), the prefix dma-(window) may make sense here. Then, we don't have to introduce a new concept IO virtual address(iova) in addition to the existing bus address(?) Anyway, either name would be ok for me;) I would just use dma-window, without the ibm, prefix but following the same conventions. Note that the of_parse_dma_window function is currently only defined in powerpc specific code, and should get moved to drivers/of from arch/powerpc/kernel/prom_parse.c. Arnd ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/1] arm/dts: Tegra30: Add device tree support for SMMU
From: Arnd Bergmann a...@arndb.de Subject: Re: [PATCH 1/1] arm/dts: Tegra30: Add device tree support for SMMU Date: Wed, 18 Apr 2012 09:31:53 +0200 Message-ID: 201204180731.54064.a...@arndb.de On Wednesday 18 April 2012, Hiroshi Doyu wrote: If we can consider IOMMU as one of the implementation of DMA(Direct Memory Access), the prefix dma-(window) may make sense here. Then, we don't have to introduce a new concept IO virtual address(iova) in addition to the existing bus address(?) Anyway, either name would be ok for me;) I would just use dma-window, without the ibm, prefix but following the same conventions. Note that the of_parse_dma_window function is currently only defined in powerpc specific code, and should get moved to drivers/of from arch/powerpc/kernel/prom_parse.c. Something like below? At least, I verified that this works with tegra-smmu. From 67c1dd493637c9e972d04e061a8e67049687021a Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU hd...@nvidia.com Date: Wed, 18 Apr 2012 12:09:03 +0300 Subject: [PATCH 1/1] dt: Add general DMA window parser This code was stolen from: arch/microblaze/kernel/prom_parse.c arch/powerpc/kernel/prom_parse.c Once ibm, prefix is removed from dts file. This generic one could replace the originals. Signed-off-by: Hiroshi DOYU hd...@nvidia.com --- drivers/of/Kconfig |4 drivers/of/Makefile|1 + drivers/of/of_dma.c| 35 +++ include/linux/of_address.h | 10 ++ 4 files changed, 50 insertions(+), 0 deletions(-) diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index dfba3e6..3b0298b 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -83,4 +83,8 @@ config OF_MTD depends on MTD def_bool y +config OF_DMA + depends on HAS_DMA + def_bool y + endmenu # OF diff --git a/drivers/of/Makefile b/drivers/of/Makefile index e027f44..711ff5b 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_OF_MDIO) += of_mdio.o obj-$(CONFIG_OF_PCI) += of_pci.o obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o obj-$(CONFIG_OF_MTD) += of_mtd.o +obj-$(CONFIG_OF_DMA) += of_dma.o diff --git a/drivers/of/of_dma.c b/drivers/of/of_dma.c new file mode 100644 index 000..1db1ccd --- /dev/null +++ b/drivers/of/of_dma.c @@ -0,0 +1,35 @@ +/* + * Stealed from: + * arch/microblaze/kernel/prom_parse.c + * arch/powerpc/kernel/prom_parse.c + */ + +#include linux/of_address.h + +void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, + unsigned long *busno, unsigned long *phys, unsigned long *size) +{ + const u32 *dma_window; + u32 cells; + const unsigned char *prop; + + dma_window = dma_window_prop; + + /* busno is always one cell */ + if (busno) + *busno = *(dma_window++); + + prop = of_get_property(dn, #dma-address-cells, NULL); + if (!prop) + prop = of_get_property(dn, #address-cells, NULL); + + cells = prop ? *(u32 *)prop : of_n_addr_cells(dn); + *phys = of_read_number(dma_window, cells); + + dma_window += cells; + + prop = of_get_property(dn, #dma-size-cells, NULL); + cells = prop ? *(u32 *)prop : of_n_size_cells(dn); + *size = of_read_number(dma_window, cells); +} + diff --git a/include/linux/of_address.h b/include/linux/of_address.h index 01b925a..2a0f7c6 100644 --- a/include/linux/of_address.h +++ b/include/linux/of_address.h @@ -21,6 +21,10 @@ extern void __iomem *of_iomap(struct device_node *device, int index); extern const u32 *of_get_address(struct device_node *dev, int index, u64 *size, unsigned int *flags); +extern void of_parse_dma_window(struct device_node *dn, + const void *dma_window_prop, unsigned long *busno, + unsigned long *phys, unsigned long *size); + #ifndef pci_address_to_pio static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; } #define pci_address_to_pio pci_address_to_pio @@ -48,6 +52,12 @@ static inline const u32 *of_get_address(struct device_node *dev, int index, { return NULL; } + +static inline void of_parse_dma_window(struct device_node *dn, + const void *dma_window_prop, unsigned long *busno, + unsigned long *phys, unsigned long *size) +{ +} #endif /* CONFIG_OF_ADDRESS */ -- 1.7.5.4 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/1] arm/dts: Tegra30: Add device tree support for SMMU
* Hiroshi Doyu wrote: diff --git a/drivers/of/of_dma.c b/drivers/of/of_dma.c new file mode 100644 index 000..1db1ccd --- /dev/null +++ b/drivers/of/of_dma.c @@ -0,0 +1,35 @@ +/* + * Stealed from: Stolen from + * arch/microblaze/kernel/prom_parse.c + * arch/powerpc/kernel/prom_parse.c + */ + +#include linux/of_address.h + +void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, + unsigned long *busno, unsigned long *phys, unsigned long *size) +{ + const u32 *dma_window; Should be __be32. + u32 cells; + const unsigned char *prop; + + dma_window = dma_window_prop; + + /* busno is always one cell */ + if (busno) + *busno = *(dma_window++); This needs endianness conversion: *busno = be32_to_cpup(dma_window++); + + prop = of_get_property(dn, #dma-address-cells, NULL); + if (!prop) + prop = of_get_property(dn, #address-cells, NULL); + + cells = prop ? *(u32 *)prop : of_n_addr_cells(dn); Same here. + *phys = of_read_number(dma_window, cells); + + dma_window += cells; + + prop = of_get_property(dn, #dma-size-cells, NULL); + cells = prop ? *(u32 *)prop : of_n_size_cells(dn); And here. Thierry pgpHTGRLdfLIW.pgp Description: PGP signature ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/1] dt: Add general DMA window parser
From: Thierry Reding thierry.red...@avionic-design.de Subject: Re: [PATCH 1/1] dt: Add general DMA window parser Date: Wed, 18 Apr 2012 12:26:29 +0200 Message-ID: 20120418102629.ga14...@avionic-0098.mockup.avionic-design.de * PGP Signed by an unknown key * Hiroshi Doyu wrote: + cells = prop ? *(__be32 *)prop : of_n_addr_cells(dn); I think this needs to be: cells = prop ? be32_to_cpup(prop) : of_n_addr_cells(dn); Only casting isn't enough, you need the bytes to be swapped. Right. Try again. Sorry for spamming. From 1ee8a9b3a839456b170af74b11a4304bfda965c4 Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU hd...@nvidia.com Date: Wed, 18 Apr 2012 12:09:03 +0300 Subject: [PATCH 1/1] dt: Add general DMA window parser This code was stolen from: arch/microblaze/kernel/prom_parse.c arch/powerpc/kernel/prom_parse.c Once ibm, prefix is removed from dts file. This generic one could replace the originals. Signed-off-by: Hiroshi DOYU hd...@nvidia.com --- drivers/of/Kconfig |4 drivers/of/Makefile|1 + drivers/of/of_dma.c| 35 +++ include/linux/of_address.h | 10 ++ 4 files changed, 50 insertions(+), 0 deletions(-) diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index dfba3e6..3b0298b 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -83,4 +83,8 @@ config OF_MTD depends on MTD def_bool y +config OF_DMA + depends on HAS_DMA + def_bool y + endmenu # OF diff --git a/drivers/of/Makefile b/drivers/of/Makefile index e027f44..711ff5b 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_OF_MDIO) += of_mdio.o obj-$(CONFIG_OF_PCI) += of_pci.o obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o obj-$(CONFIG_OF_MTD) += of_mtd.o +obj-$(CONFIG_OF_DMA) += of_dma.o diff --git a/drivers/of/of_dma.c b/drivers/of/of_dma.c new file mode 100644 index 000..45c9e88 --- /dev/null +++ b/drivers/of/of_dma.c @@ -0,0 +1,35 @@ +/* + * Stolen from: + * arch/microblaze/kernel/prom_parse.c + * arch/powerpc/kernel/prom_parse.c + */ + +#include linux/of_address.h + +void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, + unsigned long *busno, unsigned long *phys, unsigned long *size) +{ + const __be32 *dma_window; + u32 cells; + const unsigned char *prop; + + dma_window = dma_window_prop; + + /* busno is always one cell */ + if (busno) + *busno = be32_to_cpup(dma_window++); + + prop = of_get_property(dn, #dma-address-cells, NULL); + if (!prop) + prop = of_get_property(dn, #address-cells, NULL); + + cells = prop ? be32_to_cpup(prop) : of_n_addr_cells(dn); + *phys = of_read_number(dma_window, cells); + + dma_window += cells; + + prop = of_get_property(dn, #dma-size-cells, NULL); + cells = prop ? be32_to_cpup(prop) : of_n_size_cells(dn); + *size = of_read_number(dma_window, cells); +} + diff --git a/include/linux/of_address.h b/include/linux/of_address.h index 01b925a..2a0f7c6 100644 --- a/include/linux/of_address.h +++ b/include/linux/of_address.h @@ -21,6 +21,10 @@ extern void __iomem *of_iomap(struct device_node *device, int index); extern const u32 *of_get_address(struct device_node *dev, int index, u64 *size, unsigned int *flags); +extern void of_parse_dma_window(struct device_node *dn, + const void *dma_window_prop, unsigned long *busno, + unsigned long *phys, unsigned long *size); + #ifndef pci_address_to_pio static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; } #define pci_address_to_pio pci_address_to_pio @@ -48,6 +52,12 @@ static inline const u32 *of_get_address(struct device_node *dev, int index, { return NULL; } + +static inline void of_parse_dma_window(struct device_node *dn, + const void *dma_window_prop, unsigned long *busno, + unsigned long *phys, unsigned long *size) +{ +} #endif /* CONFIG_OF_ADDRESS */ -- 1.7.5.4 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/1] dt: Add general DMA window parser
* Hiroshi Doyu wrote: diff --git a/drivers/of/of_dma.c b/drivers/of/of_dma.c new file mode 100644 index 000..45c9e88 --- /dev/null +++ b/drivers/of/of_dma.c @@ -0,0 +1,35 @@ +/* + * Stolen from: + * arch/microblaze/kernel/prom_parse.c + * arch/powerpc/kernel/prom_parse.c + */ + +#include linux/of_address.h + +void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, + unsigned long *busno, unsigned long *phys, unsigned long *size) +{ + const __be32 *dma_window; + u32 cells; + const unsigned char *prop; There's no need for this to be const unsigned char *, const void * will do just as well. + + dma_window = dma_window_prop; + + /* busno is always one cell */ + if (busno) + *busno = be32_to_cpup(dma_window++); + + prop = of_get_property(dn, #dma-address-cells, NULL); + if (!prop) + prop = of_get_property(dn, #address-cells, NULL); + + cells = prop ? be32_to_cpup(prop) : of_n_addr_cells(dn); + *phys = of_read_number(dma_window, cells); This should probably fail gracefully if phys == NULL, similar to what you do for busno. + + dma_window += cells; + + prop = of_get_property(dn, #dma-size-cells, NULL); + cells = prop ? be32_to_cpup(prop) : of_n_size_cells(dn); + *size = of_read_number(dma_window, cells); Same here. +} + And you might want to add a EXPORT_SYMBOL(of_parse_dma_window) here so the function can be used from modules. Sorry for having you go through another round. I should have looked more closely before. Thierry pgpteip6Gokw2.pgp Description: PGP signature ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [RFC PATCH 1/3] iommu: Introduce iommu_group
On Mon, Apr 02, 2012 at 03:14:40PM -0600, Alex Williamson wrote: IOMMUs often do not have visibility of individual devices in the system. Due to IOMMU design, bus topology, or device quirks, we can often only identify groups of devices. Examples include Intel VT-d AMD-Vi which often have function level visibility compared to POWER partitionable endpoints which have bridge level granularity. That's a significant oversimplification of the situation on POWER, although it doesn't really matter in this context. On older (i.e. pre PCI-E) hardware, PEs have either host bridge (i.e. domain) granularity, or in IIUC in some cases p2p bridge granularity, using special p2p bridges, since that's the only real way to do iommu differentiation without the PCI-E requestor IDs. This isn't as coarse as it seems in practice, because the hardware is usually built with a bridge per physical PCI slot. On newer PCI-E hardware, the PE granularity is basically a firmware decision, and can go down to function level. I believe pHyp puts the granularity at the bridge level. Our non-virtualized Linux firmware currently does put it at the function level, but Ben is thinking about changing that to bridge level: again, because of the hardware design that isn't as coarse as it seems, and at this level we can hardware guarantee isolation to a degree that's not possible at the function level. PCIe-to-PCI bridges also often cloud the IOMMU visibility as it cannot distiguish devices behind the bridge. Devices can also sometimes hurt themselves by initiating DMA using the wrong source ID on a multifunction PCI device. IOMMU groups are meant to help solve these problems and hopefully become the working unit of the IOMMI API. So far, so simple. No objections here. I am trying to work out what the real difference in approach is in this seriers from either your or my earlier isolation group series. AFAICT it's just that this approach is explicitly only about IOMMU identity, ignoring (here) any other factors which might affect isolation. Or am I missing something? -- David Gibson| I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [RFC PATCH 2/3] iommu: Create basic group infrastructure and update AMD-Vi Intel VT-d
On Mon, Apr 02, 2012 at 03:14:46PM -0600, Alex Williamson wrote: IOMMU groups define the minimum granularity of the IOMMU. We therefore create groups using a dma_dev which is the effective requestor ID for the entire group. Additional devices can be added to groups based on system topology, IOMMU limitations, or device quirks. This implementation also includes a simple idr database for creating a flat address space of group IDs across multiple IOMMUs. Updates included for Intel VT-d, using example iommu callbacks for adding and removing devices, as well as AMD-Vi, which tracks devices on it's own. We should be able to better integrate the iommu_group within existing AMD-Vi structs or provide a private data location within the iommu_group where we can eventually reduce redundancy. Signed-off-by: Alex Williamson alex.william...@redhat.com Looks reasonable as far as it goes. This still lacks an obvious means for doing group assignment of devices on busses subordinate to devices that are on iommu managed busses. Which as we discussed earlier is a bit of a can of worms, but necessary. --- drivers/iommu/amd_iommu.c | 50 ++- drivers/iommu/intel-iommu.c | 76 + drivers/iommu/iommu.c | 198 ++- include/linux/iommu.h | 23 + 4 files changed, 267 insertions(+), 80 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index f75e060..876db28 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -256,9 +256,10 @@ static bool check_device(struct device *dev) static int iommu_init_device(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); + struct pci_dev *dma_pdev, *pdev = to_pci_dev(dev); struct iommu_dev_data *dev_data; u16 alias; + int ret; if (dev-archdata.iommu) return 0; @@ -279,6 +280,26 @@ static int iommu_init_device(struct device *dev) return -ENOTSUPP; } dev_data-alias_data = alias_data; + + dma_pdev = pci_get_bus_and_slot(alias 8, alias 0xff); + } else + dma_pdev = pdev; + + /* dma_pdev = iommu_pci_quirk(dma_pdev) */ Presumably an actual implementation of the quirk is coming? It might be an idea for it to take both the individual and representative devices, in case that information is useful. + if (!dma_pdev-dev.iommu_group) { + struct iommu_group *group; + + group = iommu_group_alloc(dma_pdev-dev); + if (IS_ERR(group)) + return PTR_ERR(group); + } + + ret = iommu_group_add_device(dma_pdev-dev.iommu_group, dev); + if (ret) { + if (iommu_group_empty(dma_pdev-dev.iommu_group)) + iommu_group_free(dma_pdev-dev.iommu_group); + return ret; It might be nice to have generic helpers that do this kind of lifetime handling of the groups, but that's a detail. } if (pci_iommuv2_capable(pdev)) { @@ -309,6 +330,12 @@ static void iommu_ignore_device(struct device *dev) static void iommu_uninit_device(struct device *dev) { + struct iommu_group *group = dev-iommu_group; + + iommu_group_remove_device(dev); + if (iommu_group_empty(group)) + iommu_group_free(group); + /* * Nothing to do here - we keep dev_data around for unplugged devices * and reuse it when the device is re-plugged - not doing so would @@ -3191,26 +3218,6 @@ static int amd_iommu_domain_has_cap(struct iommu_domain *domain, return 0; } -static int amd_iommu_device_group(struct device *dev, unsigned int *groupid) -{ - struct iommu_dev_data *dev_data = dev-archdata.iommu; - struct pci_dev *pdev = to_pci_dev(dev); - u16 devid; - - if (!dev_data) - return -ENODEV; - - if (pdev-is_virtfn || !iommu_group_mf) - devid = dev_data-devid; - else - devid = calc_devid(pdev-bus-number, -PCI_DEVFN(PCI_SLOT(pdev-devfn), 0)); - - *groupid = amd_iommu_alias_table[devid]; - - return 0; -} - static struct iommu_ops amd_iommu_ops = { .domain_init = amd_iommu_domain_init, .domain_destroy = amd_iommu_domain_destroy, @@ -3220,7 +3227,6 @@ static struct iommu_ops amd_iommu_ops = { .unmap = amd_iommu_unmap, .iova_to_phys = amd_iommu_iova_to_phys, .domain_has_cap = amd_iommu_domain_has_cap, - .device_group = amd_iommu_device_group, .pgsize_bitmap = AMD_IOMMU_PGSIZES, }; diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index c9c6053..41ab7d0 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4075,54 +4075,59 @@ static int intel_iommu_domain_has_cap(struct iommu_domain *domain, return 0; }
[PATCHv9 02/10] ARM: dma-mapping: use pr_* instread of printk
Replace all calls to printk with pr_* functions family. Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com Acked-by: Kyungmin Park kyungmin.p...@samsung.com Acked-by: Arnd Bergmann a...@arndb.de Tested-By: Subash Patel subash.ramasw...@linaro.org --- arch/arm/mm/dma-mapping.c | 16 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index db23ae4..366f3a2 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -184,14 +184,14 @@ static int __init consistent_init(void) pud = pud_alloc(init_mm, pgd, base); if (!pud) { - printk(KERN_ERR %s: no pud tables\n, __func__); + pr_err(%s: no pud tables\n, __func__); ret = -ENOMEM; break; } pmd = pmd_alloc(init_mm, pud, base); if (!pmd) { - printk(KERN_ERR %s: no pmd tables\n, __func__); + pr_err(%s: no pmd tables\n, __func__); ret = -ENOMEM; break; } @@ -199,7 +199,7 @@ static int __init consistent_init(void) pte = pte_alloc_kernel(pmd, base); if (!pte) { - printk(KERN_ERR %s: no pte tables\n, __func__); + pr_err(%s: no pte tables\n, __func__); ret = -ENOMEM; break; } @@ -222,7 +222,7 @@ __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot, int bit; if (!consistent_pte) { - printk(KERN_ERR %s: not initialised\n, __func__); + pr_err(%s: not initialised\n, __func__); dump_stack(); return NULL; } @@ -281,14 +281,14 @@ static void __dma_free_remap(void *cpu_addr, size_t size) c = arm_vmregion_find_remove(consistent_head, (unsigned long)cpu_addr); if (!c) { - printk(KERN_ERR %s: trying to free invalid coherent area: %p\n, + pr_err(%s: trying to free invalid coherent area: %p\n, __func__, cpu_addr); dump_stack(); return; } if ((c-vm_end - c-vm_start) != size) { - printk(KERN_ERR %s: freeing wrong coherent size (%ld != %d)\n, + pr_err(%s: freeing wrong coherent size (%ld != %d)\n, __func__, c-vm_end - c-vm_start, size); dump_stack(); size = c-vm_end - c-vm_start; @@ -310,8 +310,8 @@ static void __dma_free_remap(void *cpu_addr, size_t size) } if (pte_none(pte) || !pte_present(pte)) - printk(KERN_CRIT %s: bad page in kernel page table\n, - __func__); + pr_crit(%s: bad page in kernel page table\n, + __func__); } while (size -= PAGE_SIZE); flush_tlb_kernel_range(c-vm_start, c-vm_end); -- 1.7.1.569.g6f426 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCHv9 08/10] ARM: dma-mapping: remove redundant code and cleanup
This patch just performs a global cleanup in DMA mapping implementation for ARM architecture. Some of the tiny helper functions have been moved to the caller code, some have been merged together. Signed-off-by: Marek Szyprowski m.szyprow...@samsung.com Acked-by: Kyungmin Park kyungmin.p...@samsung.com Acked-by: Arnd Bergmann a...@arndb.de Tested-By: Subash Patel subash.ramasw...@linaro.org --- arch/arm/mm/dma-mapping.c | 88 1 files changed, 24 insertions(+), 64 deletions(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index a4db5ec..615fabd 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -40,64 +40,12 @@ * the CPU does do speculative prefetches, which means we clean caches * before transfers and delay cache invalidation until transfer completion. * - * Private support functions: these are not part of the API and are - * liable to change. Drivers must not use these. */ -static inline void __dma_single_cpu_to_dev(const void *kaddr, size_t size, - enum dma_data_direction dir) -{ - extern void ___dma_single_cpu_to_dev(const void *, size_t, - enum dma_data_direction); - - if (!arch_is_coherent()) - ___dma_single_cpu_to_dev(kaddr, size, dir); -} - -static inline void __dma_single_dev_to_cpu(const void *kaddr, size_t size, - enum dma_data_direction dir) -{ - extern void ___dma_single_dev_to_cpu(const void *, size_t, - enum dma_data_direction); - - if (!arch_is_coherent()) - ___dma_single_dev_to_cpu(kaddr, size, dir); -} - -static inline void __dma_page_cpu_to_dev(struct page *page, unsigned long off, - size_t size, enum dma_data_direction dir) -{ - extern void ___dma_page_cpu_to_dev(struct page *, unsigned long, +static void __dma_page_cpu_to_dev(struct page *, unsigned long, size_t, enum dma_data_direction); - - if (!arch_is_coherent()) - ___dma_page_cpu_to_dev(page, off, size, dir); -} - -static inline void __dma_page_dev_to_cpu(struct page *page, unsigned long off, - size_t size, enum dma_data_direction dir) -{ - extern void ___dma_page_dev_to_cpu(struct page *, unsigned long, +static void __dma_page_dev_to_cpu(struct page *, unsigned long, size_t, enum dma_data_direction); - if (!arch_is_coherent()) - ___dma_page_dev_to_cpu(page, off, size, dir); -} - - -static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page, -unsigned long offset, size_t size, enum dma_data_direction dir) -{ - __dma_page_cpu_to_dev(page, offset, size, dir); - return pfn_to_dma(dev, page_to_pfn(page)) + offset; -} - -static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle, - size_t size, enum dma_data_direction dir) -{ - __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)), - handle ~PAGE_MASK, size, dir); -} - /** * arm_dma_map_page - map a portion of a page for streaming DMA * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices @@ -112,11 +60,13 @@ static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle, * The device owns this memory once this call has completed. The CPU * can regain ownership by calling dma_unmap_page(). */ -static inline dma_addr_t arm_dma_map_page(struct device *dev, struct page *page, +static dma_addr_t arm_dma_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs) { - return __dma_map_page(dev, page, offset, size, dir); + if (!arch_is_coherent()) + __dma_page_cpu_to_dev(page, offset, size, dir); + return pfn_to_dma(dev, page_to_pfn(page)) + offset; } /** @@ -133,27 +83,31 @@ static inline dma_addr_t arm_dma_map_page(struct device *dev, struct page *page, * After this call, reads by the CPU to the buffer are guaranteed to see * whatever the device wrote there. */ -static inline void arm_dma_unmap_page(struct device *dev, dma_addr_t handle, +static void arm_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs) { - __dma_unmap_page(dev, handle, size, dir); + if (!arch_is_coherent()) + __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)), + handle ~PAGE_MASK, size, dir); } -static inline void arm_dma_sync_single_for_cpu(struct device *dev, +static void arm_dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle, size_t size, enum dma_data_direction dir) { unsigned int offset = handle (PAGE_SIZE - 1); struct page *page = pfn_to_page(dma_to_pfn(dev, handle-offset)); - __dma_page_dev_to_cpu(page, offset, size,
[PATCHv9 00/10] ARM: DMA-mapping framework redesign
Hello, This is a quick update on dma-mapping redesign patches for ARM. I did some minor fixes suggested by Arnd and extended commit messages for a few patches. Like the previous version, the patches have been rebased onto latest Linux v3.4-rc3 which comes with dma_map_ops related preparation changes. The patches are also available on my git repository at: git://git.linaro.org/people/mszyprowski/linux-dma-mapping.git 3.4-rc3-arm-dma-v9 The code has been tested on Samsung Exynos4 'UniversalC210' and NURI boards with IOMMU driver posted by KyongHo Cho. The integration patch has been posted in the following thread: http://www.spinics.net/lists/arm-kernel/msg169030.html History of the development: v1: (initial version of the DMA-mapping redesign patches): http://www.spinics.net/lists/linux-mm/msg21241.html v2: http://lists.linaro.org/pipermail/linaro-mm-sig/2011-September/000571.html http://lists.linaro.org/pipermail/linaro-mm-sig/2011-September/000577.html v3: http://www.spinics.net/lists/linux-mm/msg25490.html v4 and v5: http://www.spinics.net/lists/arm-kernel/msg151147.html http://www.spinics.net/lists/arm-kernel/msg154889.html v6: http://www.spinics.net/lists/linux-mm/msg29903.html v7: http://www.spinics.net/lists/arm-kernel/msg162149.html v8: http://www.spinics.net/lists/arm-kernel/msg168478.html Best regards Marek Szyprowski Samsung Poland RD Center Patch summary: Marek Szyprowski (10): common: add dma_mmap_from_coherent() function ARM: dma-mapping: use pr_* instread of printk ARM: dma-mapping: introduce DMA_ERROR_CODE constant ARM: dma-mapping: remove offset parameter to prepare for generic dma_ops ARM: dma-mapping: use asm-generic/dma-mapping-common.h ARM: dma-mapping: implement dma sg methods on top of any generic dma ops ARM: dma-mapping: move all dma bounce code to separate dma ops structure ARM: dma-mapping: remove redundant code and cleanup ARM: dma-mapping: use alloc, mmap, free from dma_ops ARM: dma-mapping: add support for IOMMU mapper arch/arm/Kconfig |9 + arch/arm/common/dmabounce.c| 84 +++- arch/arm/include/asm/device.h |4 + arch/arm/include/asm/dma-iommu.h | 34 ++ arch/arm/include/asm/dma-mapping.h | 407 --- arch/arm/mm/dma-mapping.c | 1015 ++-- arch/arm/mm/vmregion.h |2 +- drivers/base/dma-coherent.c| 42 ++ include/asm-generic/dma-coherent.h |4 +- 9 files changed, 1134 insertions(+), 467 deletions(-) create mode 100644 arch/arm/include/asm/dma-iommu.h -- 1.7.1.569.g6f426 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/1] dt: Add general DMA window parser
On 04/18/2012 04:19 AM, Hiroshi Doyu wrote: Subject: [PATCH 1/1] dt: Add general DMA window parser This code was stolen from: arch/microblaze/kernel/prom_parse.c arch/powerpc/kernel/prom_parse.c Once ibm, prefix is removed from dts file. This generic one could replace the originals. +extern void of_parse_dma_window(struct device_node *dn, +const void *dma_window_prop, unsigned long *busno, +unsigned long *phys, unsigned long *size); At least some other of_*() parsing functions take the property name rather than the property pointer, and also take an index into the property in order to support multiple entries in it. See for example of_parse_phandle and of_get_named_gpio_flags. Should this new API be similar? E.g.: extern void of_parse_dma_window(struct device_node *np, const char *propname, int index, unsigned long *busno, unsigned long *phys, unsigned long *size); ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/1] arm/dts: Tegra30: Add device tree support for SMMU
On 04/17/2012 11:10 PM, Hiroshi Doyu wrote: On Mon, 16 Apr 2012 18:07:06 +0200 Stephen Warren swar...@wwwdotorg.org wrote: On 04/16/2012 04:10 AM, Hiroshi Doyu wrote: Stephen Warren wrote at Fri, 13 Apr 2012 21:33:47 +0200: On 04/13/2012 04:22 AM, Hiroshi Doyu wrote: Add device tree support for Tegra30 IOMMU(SMMU). ... But why does the SMMU driver expect to control the AHB arbitration registers? They seem unrelated to the SMMU. It's necessary to inform AHB that SMMU is ready to use. There's a dedicated bit for SMMU in this AHB arbitration register. Shouldn't there be a dedicated driver for the AHB arbitration registers that the SMMU driver calls into to achieve this? IIRC, the AHB arbitration registers support much more than the SMMU enable, and if we ever need to touch those other features, going to the SMMU driver to do so probably wouldn't make sense. Agree. Sounds like the way to go. We haven't upstreamed AHB driver yet. So is it ok to remove AHB entry from SMMU dt and add AHB function call when upstreaming AHB driver? I'll work on that. I think that seems reasonable for now, yes. I assume you mean implementing e.g. arch/arm/mach-tegra/tegra30-ahb.c, similar to how, say, the fuse APIs work. ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu