diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-06 15:41:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-06 15:41:54 -0400 |
commit | 8b70a90cabafb6a6e1a0d3f838b38355fe48337e (patch) | |
tree | 1234fd99081958a6d8ca1a8d8bfad7662106749c | |
parent | 7644a448ccf200d95ad4426e84a486dec5cc1703 (diff) | |
parent | 5b91a98c61abe914e6a80d7dc15e435c47ea0004 (diff) |
Merge branch 'for-v3.11' of git://git.linaro.org/people/mszyprowski/linux-dma-mapping
Pull ARM DMA mapping updates from Marek Szyprowski:
"This contains important bugfixes and an update for IOMMU integration
support for ARM architecture"
* 'for-v3.11' of git://git.linaro.org/people/mszyprowski/linux-dma-mapping:
ARM: dma: Drop __GFP_COMP for iommu dma memory allocations
ARM: DMA-mapping: mark all !DMA_TO_DEVICE pages in unmapping as clean
ARM: dma-mapping: NULLify dev->archdata.mapping pointer on detach
ARM: dma-mapping: convert DMA direction into IOMMU protection attributes
ARM: dma-mapping: Get pages if the cpu_addr is out of atomic_pool
-rw-r--r-- | arch/arm/mm/dma-mapping.c | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 7ec02961dfa0..7f9b1798c6cf 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c | |||
@@ -1328,6 +1328,15 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, | |||
1328 | if (gfp & GFP_ATOMIC) | 1328 | if (gfp & GFP_ATOMIC) |
1329 | return __iommu_alloc_atomic(dev, size, handle); | 1329 | return __iommu_alloc_atomic(dev, size, handle); |
1330 | 1330 | ||
1331 | /* | ||
1332 | * Following is a work-around (a.k.a. hack) to prevent pages | ||
1333 | * with __GFP_COMP being passed to split_page() which cannot | ||
1334 | * handle them. The real problem is that this flag probably | ||
1335 | * should be 0 on ARM as it is not supported on this | ||
1336 | * platform; see CONFIG_HUGETLBFS. | ||
1337 | */ | ||
1338 | gfp &= ~(__GFP_COMP); | ||
1339 | |||
1331 | pages = __iommu_alloc_buffer(dev, size, gfp, attrs); | 1340 | pages = __iommu_alloc_buffer(dev, size, gfp, attrs); |
1332 | if (!pages) | 1341 | if (!pages) |
1333 | return NULL; | 1342 | return NULL; |
@@ -1386,16 +1395,17 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma, | |||
1386 | void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr, | 1395 | void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr, |
1387 | dma_addr_t handle, struct dma_attrs *attrs) | 1396 | dma_addr_t handle, struct dma_attrs *attrs) |
1388 | { | 1397 | { |
1389 | struct page **pages = __iommu_get_pages(cpu_addr, attrs); | 1398 | struct page **pages; |
1390 | size = PAGE_ALIGN(size); | 1399 | size = PAGE_ALIGN(size); |
1391 | 1400 | ||
1392 | if (!pages) { | 1401 | if (__in_atomic_pool(cpu_addr, size)) { |
1393 | WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr); | 1402 | __iommu_free_atomic(dev, cpu_addr, handle, size); |
1394 | return; | 1403 | return; |
1395 | } | 1404 | } |
1396 | 1405 | ||
1397 | if (__in_atomic_pool(cpu_addr, size)) { | 1406 | pages = __iommu_get_pages(cpu_addr, attrs); |
1398 | __iommu_free_atomic(dev, cpu_addr, handle, size); | 1407 | if (!pages) { |
1408 | WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr); | ||
1399 | return; | 1409 | return; |
1400 | } | 1410 | } |
1401 | 1411 | ||
@@ -1650,13 +1660,27 @@ static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *p | |||
1650 | { | 1660 | { |
1651 | struct dma_iommu_mapping *mapping = dev->archdata.mapping; | 1661 | struct dma_iommu_mapping *mapping = dev->archdata.mapping; |
1652 | dma_addr_t dma_addr; | 1662 | dma_addr_t dma_addr; |
1653 | int ret, len = PAGE_ALIGN(size + offset); | 1663 | int ret, prot, len = PAGE_ALIGN(size + offset); |
1654 | 1664 | ||
1655 | dma_addr = __alloc_iova(mapping, len); | 1665 | dma_addr = __alloc_iova(mapping, len); |
1656 | if (dma_addr == DMA_ERROR_CODE) | 1666 | if (dma_addr == DMA_ERROR_CODE) |
1657 | return dma_addr; | 1667 | return dma_addr; |
1658 | 1668 | ||
1659 | ret = iommu_map(mapping->domain, dma_addr, page_to_phys(page), len, 0); | 1669 | switch (dir) { |
1670 | case DMA_BIDIRECTIONAL: | ||
1671 | prot = IOMMU_READ | IOMMU_WRITE; | ||
1672 | break; | ||
1673 | case DMA_TO_DEVICE: | ||
1674 | prot = IOMMU_READ; | ||
1675 | break; | ||
1676 | case DMA_FROM_DEVICE: | ||
1677 | prot = IOMMU_WRITE; | ||
1678 | break; | ||
1679 | default: | ||
1680 | prot = 0; | ||
1681 | } | ||
1682 | |||
1683 | ret = iommu_map(mapping->domain, dma_addr, page_to_phys(page), len, prot); | ||
1660 | if (ret < 0) | 1684 | if (ret < 0) |
1661 | goto fail; | 1685 | goto fail; |
1662 | 1686 | ||
@@ -1921,7 +1945,7 @@ void arm_iommu_detach_device(struct device *dev) | |||
1921 | 1945 | ||
1922 | iommu_detach_device(mapping->domain, dev); | 1946 | iommu_detach_device(mapping->domain, dev); |
1923 | kref_put(&mapping->kref, release_iommu_mapping); | 1947 | kref_put(&mapping->kref, release_iommu_mapping); |
1924 | mapping = NULL; | 1948 | dev->archdata.mapping = NULL; |
1925 | set_dma_ops(dev, NULL); | 1949 | set_dma_ops(dev, NULL); |
1926 | 1950 | ||
1927 | pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev)); | 1951 | pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev)); |