Merge "ARM: dma-mapping: Allow highmem pages to not have a mapping"
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 0c0562a..f6fb3b8 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -479,7 +479,7 @@
return NULL;
}
-static void __dma_free_remap(void *cpu_addr, size_t size)
+static void __dma_free_remap(void *cpu_addr, size_t size, bool no_warn)
{
struct arm_vmregion *c;
unsigned long addr;
@@ -489,9 +489,11 @@
c = arm_vmregion_find_remove(&consistent_head, (unsigned long)cpu_addr);
if (!c) {
- pr_err("%s: trying to free invalid coherent area: %p\n",
- __func__, cpu_addr);
- dump_stack();
+ if (!no_warn) {
+ pr_err("%s: trying to free invalid coherent area: %p\n",
+ __func__, cpu_addr);
+ dump_stack();
+ }
return;
}
@@ -633,6 +635,7 @@
return 1;
}
+#define NO_KERNEL_MAPPING_DUMMY 0x2222
static void *__alloc_from_contiguous(struct device *dev, size_t size,
pgprot_t prot, struct page **ret_page,
bool no_kernel_mapping,
@@ -653,10 +656,20 @@
__dma_remap(page, size, prot, no_kernel_mapping);
ptr = page_address(page);
} else {
- ptr = __dma_alloc_remap(page, size, GFP_KERNEL, prot, caller);
- if (!ptr) {
- dma_release_from_contiguous(dev, page, count);
- return NULL;
+ if (no_kernel_mapping) {
+ /*
+ * Something non-NULL needs to be returned here. Give
+ * back a dummy address that is unmapped to catch
+ * clients trying to use the address incorrectly
+ */
+ ptr = (void *)NO_KERNEL_MAPPING_DUMMY;
+ } else {
+ ptr = __dma_alloc_remap(page, size, GFP_KERNEL, prot,
+ caller);
+ if (!ptr) {
+ dma_release_from_contiguous(dev, page, count);
+ return NULL;
+ }
}
}
*ret_page = page;
@@ -669,7 +682,7 @@
if (!PageHighMem(page))
__dma_remap(page, size, pgprot_kernel, false);
else
- __dma_free_remap(cpu_addr, size);
+ __dma_free_remap(cpu_addr, size, true);
dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT);
}
@@ -826,7 +839,7 @@
if (arch_is_coherent() || nommu()) {
__dma_free_buffer(page, size);
} else if (!IS_ENABLED(CONFIG_CMA)) {
- __dma_free_remap(cpu_addr, size);
+ __dma_free_remap(cpu_addr, size, false);
__dma_free_buffer(page, size);
} else {
if (__free_from_pool(cpu_addr, size))
@@ -1362,7 +1375,7 @@
c = arm_vmregion_find(&consistent_head, (unsigned long)cpu_addr);
if (c) {
struct page **pages = c->priv;
- __dma_free_remap(cpu_addr, size);
+ __dma_free_remap(cpu_addr, size, false);
__iommu_remove_mapping(dev, handle, size);
__iommu_free_buffer(dev, pages, size);
}