diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-01-11 13:28:19 -0200 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-01-11 13:28:19 -0200 |
commit | 734d1ece37fbf3d2ddfc71bc6c69e0fe35f02542 (patch) | |
tree | c4805dd7e746b1feb9e09e9849f3245d0b2c0c6b /arch/arm/mm/dma-mapping.c | |
parent | 216c82c6aba63eeb49d7654b448e0d47bea255bb (diff) | |
parent | 9931faca02c604c22335f5a935a501bb2ace6e20 (diff) |
Merge tag 'v3.8-rc3' into v4l_for_linus
Linux 3.8-rc3
* tag 'v3.8-rc3': (11110 commits)
Linux 3.8-rc3
mm: reinstante dropped pmd_trans_splitting() check
cred: Remove tgcred pointer from struct cred
drm/ttm: fix fence locking in ttm_buffer_object_transfer
ARM: clps711x: Fix bad merge of clockevents setup
ARM: highbank: save and restore L2 cache and GIC on suspend
ARM: highbank: add a power request clear
ARM: highbank: fix secondary boot and hotplug
ARM: highbank: fix typos with hignbank in power request functions
ARM: dts: fix highbank cpu mpidr values
ARM: dts: add device_type prop to cpu nodes on Calxeda platforms
drm/prime: drop reference on imported dma-buf come from gem
xen/netfront: improve truesize tracking
ARM: mx5: Fix MX53 flexcan2 clock
ARM: OMAP2+: am33xx-hwmod: Fix wrongly terminated am33xx_usbss_mpu_irqs array
sctp: fix Kconfig bug in default cookie hmac selection
EDAC: Cleanup device deregistering path
EDAC: Fix EDAC Kconfig menu
EDAC: Fix kernel panic on module unloading
ALSA: hda - add mute LED for HP Pavilion 17 (Realtek codec)
...
Diffstat (limited to 'arch/arm/mm/dma-mapping.c')
-rw-r--r-- | arch/arm/mm/dma-mapping.c | 45 |
1 files changed, 34 insertions, 11 deletions
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 58bc3e4d3bd..6b2fb87c869 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -124,8 +124,6 @@ static void arm_dma_sync_single_for_device(struct device *dev, __dma_page_cpu_to_dev(page, offset, size, dir); } -static int arm_dma_set_mask(struct device *dev, u64 dma_mask); - struct dma_map_ops arm_dma_ops = { .alloc = arm_dma_alloc, .free = arm_dma_free, @@ -971,7 +969,7 @@ int dma_supported(struct device *dev, u64 mask) } EXPORT_SYMBOL(dma_supported); -static int arm_dma_set_mask(struct device *dev, u64 dma_mask) +int arm_dma_set_mask(struct device *dev, u64 dma_mask) { if (!dev->dma_mask || !dma_supported(dev, dma_mask)) return -EIO; @@ -1036,7 +1034,8 @@ static inline void __free_iova(struct dma_iommu_mapping *mapping, spin_unlock_irqrestore(&mapping->lock, flags); } -static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, gfp_t gfp) +static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, + gfp_t gfp, struct dma_attrs *attrs) { struct page **pages; int count = size >> PAGE_SHIFT; @@ -1050,6 +1049,23 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, gfp_t if (!pages) return NULL; + if (dma_get_attr(DMA_ATTR_FORCE_CONTIGUOUS, attrs)) + { + unsigned long order = get_order(size); + struct page *page; + + page = dma_alloc_from_contiguous(dev, count, order); + if (!page) + goto error; + + __dma_clear_buffer(page, size); + + for (i = 0; i < count; i++) + pages[i] = page + i; + + return pages; + } + while (count) { int j, order = __fls(count); @@ -1083,14 +1099,21 @@ error: return NULL; } -static int __iommu_free_buffer(struct device *dev, struct page **pages, size_t size) +static int __iommu_free_buffer(struct device *dev, struct page **pages, + size_t size, struct dma_attrs *attrs) { int count = size >> PAGE_SHIFT; int array_size = count * sizeof(struct page *); int i; - for (i = 0; i < count; i++) - if (pages[i]) - __free_pages(pages[i], 0); + + if (dma_get_attr(DMA_ATTR_FORCE_CONTIGUOUS, attrs)) { + dma_release_from_contiguous(dev, pages[0], count); + } else { + for (i = 0; i < count; i++) + if (pages[i]) + __free_pages(pages[i], 0); + } + if (array_size <= PAGE_SIZE) kfree(pages); else @@ -1252,7 +1275,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, if (gfp & GFP_ATOMIC) return __iommu_alloc_atomic(dev, size, handle); - pages = __iommu_alloc_buffer(dev, size, gfp); + pages = __iommu_alloc_buffer(dev, size, gfp, attrs); if (!pages) return NULL; @@ -1273,7 +1296,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, err_mapping: __iommu_remove_mapping(dev, *handle, size); err_buffer: - __iommu_free_buffer(dev, pages, size); + __iommu_free_buffer(dev, pages, size, attrs); return NULL; } @@ -1329,7 +1352,7 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr, } __iommu_remove_mapping(dev, handle, size); - __iommu_free_buffer(dev, pages, size); + __iommu_free_buffer(dev, pages, size, attrs); } static int arm_iommu_get_sgtable(struct device *dev, struct sg_table *sgt, |