gpu: ion: Use standard cache routines
Instead of using custom routines for cache operations use the
standard operations for cache flush, cache clean, and cache
invalidate. In addition only call outer cache routines if
outer cache is available.
Change-Id: Idb51bf7348fd526ebdea1e6ff2e366b8a3b4de33
Signed-off-by: Olav Haugan <ohaugan@codeaurora.org>
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index 710583b..3561a8a 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -30,6 +30,7 @@
#include <mach/iommu_domains.h>
#include <asm/mach/map.h>
+#include <asm/cacheflush.h>
struct ion_carveout_heap {
struct ion_heap heap;
@@ -41,6 +42,7 @@
int (*release_region)(void *);
atomic_t map_count;
void *bus_id;
+ unsigned int has_outer_cache;
};
ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap,
@@ -229,25 +231,31 @@
void *vaddr, unsigned int offset, unsigned int length,
unsigned int cmd)
{
- unsigned long vstart, pstart;
-
- pstart = buffer->priv_phys + offset;
- vstart = (unsigned long)vaddr;
+ void (*outer_cache_op)(phys_addr_t, phys_addr_t);
+ struct ion_carveout_heap *carveout_heap =
+ container_of(heap, struct ion_carveout_heap, heap);
switch (cmd) {
case ION_IOC_CLEAN_CACHES:
- clean_caches(vstart, length, pstart);
+ dmac_clean_range(vaddr, vaddr + length);
+ outer_cache_op = outer_clean_range;
break;
case ION_IOC_INV_CACHES:
- invalidate_caches(vstart, length, pstart);
+ dmac_inv_range(vaddr, vaddr + length);
+ outer_cache_op = outer_inv_range;
break;
case ION_IOC_CLEAN_INV_CACHES:
- clean_and_invalidate_caches(vstart, length, pstart);
+ dmac_flush_range(vaddr, vaddr + length);
+ outer_cache_op = outer_flush_range;
break;
default:
return -EINVAL;
}
+ if (carveout_heap->has_outer_cache) {
+ unsigned long pstart = buffer->priv_phys + offset;
+ outer_cache_op(pstart, pstart + length);
+ }
return 0;
}
@@ -447,6 +455,7 @@
carveout_heap->heap.type = ION_HEAP_TYPE_CARVEOUT;
carveout_heap->allocated_bytes = 0;
carveout_heap->total_size = heap_data->size;
+ carveout_heap->has_outer_cache = heap_data->has_outer_cache;
if (heap_data->extra_data) {
struct ion_co_heap_pdata *extra_data =
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index fcbf1d4..1c50c04 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -34,6 +34,7 @@
#include "ion_priv.h"
#include <asm/mach/map.h>
+#include <asm/cacheflush.h>
/**
* struct ion_cp_heap - container for the heap and shared heap data
@@ -66,7 +67,8 @@
* @reserved_vrange: reserved virtual address range for use with fmem
* @iommu_map_all: Indicates whether we should map whole heap into IOMMU.
* @iommu_2x_map_domain: Indicates the domain to use for overmapping.
- */
+ * @has_outer_cache: set to 1 if outer cache is used, 0 otherwise.
+*/
struct ion_cp_heap {
struct ion_heap heap;
struct gen_pool *pool;
@@ -90,7 +92,7 @@
void *reserved_vrange;
int iommu_map_all;
int iommu_2x_map_domain;
-
+ unsigned int has_outer_cache;
};
enum {
@@ -541,25 +543,31 @@
void *vaddr, unsigned int offset, unsigned int length,
unsigned int cmd)
{
- unsigned long vstart, pstart;
-
- pstart = buffer->priv_phys + offset;
- vstart = (unsigned long)vaddr;
+ void (*outer_cache_op)(phys_addr_t, phys_addr_t);
+ struct ion_cp_heap *cp_heap =
+ container_of(heap, struct ion_cp_heap, heap);
switch (cmd) {
case ION_IOC_CLEAN_CACHES:
- clean_caches(vstart, length, pstart);
+ dmac_clean_range(vaddr, vaddr + length);
+ outer_cache_op = outer_clean_range;
break;
case ION_IOC_INV_CACHES:
- invalidate_caches(vstart, length, pstart);
+ dmac_inv_range(vaddr, vaddr + length);
+ outer_cache_op = outer_inv_range;
break;
case ION_IOC_CLEAN_INV_CACHES:
- clean_and_invalidate_caches(vstart, length, pstart);
+ dmac_flush_range(vaddr, vaddr + length);
+ outer_cache_op = outer_flush_range;
break;
default:
return -EINVAL;
}
+ if (cp_heap->has_outer_cache) {
+ unsigned long pstart = buffer->priv_phys + offset;
+ outer_cache_op(pstart, pstart + length);
+ }
return 0;
}
@@ -915,6 +923,7 @@
cp_heap->heap_protected = HEAP_NOT_PROTECTED;
cp_heap->secure_base = cp_heap->base;
cp_heap->secure_size = heap_data->size;
+ cp_heap->has_outer_cache = heap_data->has_outer_cache;
if (heap_data->extra_data) {
struct ion_cp_heap_pdata *extra_data =
heap_data->extra_data;
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index 70bdc7f..621144b 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -23,10 +23,12 @@
#include <asm/mach/map.h>
#include <asm/page.h>
+#include <asm/cacheflush.h>
#include <mach/iommu_domains.h>
struct ion_iommu_heap {
struct ion_heap heap;
+ unsigned int has_outer_cache;
};
struct ion_iommu_priv_data {
@@ -261,34 +263,39 @@
void *vaddr, unsigned int offset, unsigned int length,
unsigned int cmd)
{
- unsigned long vstart, pstart;
- void (*op)(unsigned long, unsigned long, unsigned long);
- unsigned int i;
- struct ion_iommu_priv_data *data = buffer->priv_virt;
-
- if (!data)
- return -ENOMEM;
+ void (*outer_cache_op)(phys_addr_t, phys_addr_t);
+ struct ion_iommu_heap *iommu_heap =
+ container_of(heap, struct ion_iommu_heap, heap);
switch (cmd) {
case ION_IOC_CLEAN_CACHES:
- op = clean_caches;
+ dmac_clean_range(vaddr, vaddr + length);
+ outer_cache_op = outer_clean_range;
break;
case ION_IOC_INV_CACHES:
- op = invalidate_caches;
+ dmac_inv_range(vaddr, vaddr + length);
+ outer_cache_op = outer_inv_range;
break;
case ION_IOC_CLEAN_INV_CACHES:
- op = clean_and_invalidate_caches;
+ dmac_flush_range(vaddr, vaddr + length);
+ outer_cache_op = outer_flush_range;
break;
default:
return -EINVAL;
}
- vstart = (unsigned long) vaddr;
- for (i = 0; i < data->nrpages; ++i, vstart += PAGE_SIZE) {
- pstart = page_to_phys(data->pages[i]);
- op(vstart, PAGE_SIZE, pstart);
- }
+ if (iommu_heap->has_outer_cache) {
+ unsigned long pstart;
+ unsigned int i;
+ struct ion_iommu_priv_data *data = buffer->priv_virt;
+ if (!data)
+ return -ENOMEM;
+ for (i = 0; i < data->nrpages; ++i) {
+ pstart = page_to_phys(data->pages[i]);
+ outer_cache_op(pstart, pstart + PAGE_SIZE);
+ }
+ }
return 0;
}
@@ -327,6 +334,7 @@
iommu_heap->heap.ops = &iommu_heap_ops;
iommu_heap->heap.type = ION_HEAP_TYPE_IOMMU;
+ iommu_heap->has_outer_cache = heap_data->has_outer_cache;
return &iommu_heap->heap;
}
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
index 26c6632..08b271b 100644
--- a/drivers/gpu/ion/ion_system_heap.c
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -26,9 +26,12 @@
#include <mach/iommu_domains.h>
#include "ion_priv.h"
#include <mach/memory.h>
+#include <asm/cacheflush.h>
static atomic_t system_heap_allocated;
static atomic_t system_contig_heap_allocated;
+static unsigned int system_heap_has_outer_cache;
+static unsigned int system_heap_contig_has_outer_cache;
static int ion_system_heap_allocate(struct ion_heap *heap,
struct ion_buffer *buffer,
@@ -144,63 +147,66 @@
void *vaddr, unsigned int offset, unsigned int length,
unsigned int cmd)
{
- unsigned long vstart, pstart;
- void *vend;
- void *vtemp;
- unsigned long ln = 0;
- void (*op)(unsigned long, unsigned long, unsigned long);
+ void (*outer_cache_op)(phys_addr_t, phys_addr_t);
switch (cmd) {
case ION_IOC_CLEAN_CACHES:
- op = clean_caches;
+ dmac_clean_range(vaddr, vaddr + length);
+ outer_cache_op = outer_clean_range;
break;
case ION_IOC_INV_CACHES:
- op = invalidate_caches;
+ dmac_inv_range(vaddr, vaddr + length);
+ outer_cache_op = outer_inv_range;
break;
case ION_IOC_CLEAN_INV_CACHES:
- op = clean_and_invalidate_caches;
+ dmac_flush_range(vaddr, vaddr + length);
+ outer_cache_op = outer_flush_range;
break;
default:
return -EINVAL;
}
- vend = buffer->priv_virt + buffer->size;
- vtemp = buffer->priv_virt + offset;
+ if (system_heap_has_outer_cache) {
+ unsigned long pstart;
+ void *vend;
+ void *vtemp;
+ unsigned long ln = 0;
+ vend = buffer->priv_virt + buffer->size;
+ vtemp = buffer->priv_virt + offset;
- if ((vtemp+length) > vend) {
- pr_err("Trying to flush outside of mapped range.\n");
- pr_err("End of mapped range: %p, trying to flush to "
- "address %p\n", vend, vtemp+length);
- WARN(1, "%s: called with heap name %s, buffer size 0x%x, "
- "vaddr 0x%p, offset 0x%x, length: 0x%x\n", __func__,
- heap->name, buffer->size, vaddr, offset, length);
- return -EINVAL;
- }
-
- for (vstart = (unsigned long) vaddr;
- ln < length && vtemp < vend;
- vtemp += PAGE_SIZE, ln += PAGE_SIZE,
- vstart += PAGE_SIZE) {
- struct page *page = vmalloc_to_page(vtemp);
- if (!page) {
- WARN(1, "Could not find page for virt. address %p\n",
- vtemp);
- return -EINVAL;
- }
- pstart = page_to_phys(page);
- /*
- * If page -> phys is returning NULL, something
- * has really gone wrong...
- */
- if (!pstart) {
- WARN(1, "Could not translate %p to physical address\n",
- vtemp);
+ if ((vtemp+length) > vend) {
+ pr_err("Trying to flush outside of mapped range.\n");
+ pr_err("End of mapped range: %p, trying to flush to "
+ "address %p\n", vend, vtemp+length);
+ WARN(1, "%s: called with heap name %s, buffer size 0x%x, "
+ "vaddr 0x%p, offset 0x%x, length: 0x%x\n",
+ __func__, heap->name, buffer->size, vaddr,
+ offset, length);
return -EINVAL;
}
- op(vstart, PAGE_SIZE, pstart);
- }
+ for (; ln < length && vtemp < vend;
+ vtemp += PAGE_SIZE, ln += PAGE_SIZE) {
+ struct page *page = vmalloc_to_page(vtemp);
+ if (!page) {
+ WARN(1, "Could not find page for virt. address %p\n",
+ vtemp);
+ return -EINVAL;
+ }
+ pstart = page_to_phys(page);
+ /*
+ * If page -> phys is returning NULL, something
+ * has really gone wrong...
+ */
+ if (!pstart) {
+ WARN(1, "Could not translate %p to physical address\n",
+ vtemp);
+ return -EINVAL;
+ }
+ outer_cache_op(pstart, pstart + PAGE_SIZE);
+ }
+ }
return 0;
}
@@ -314,7 +320,7 @@
.unmap_iommu = ion_system_heap_unmap_iommu,
};
-struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused)
+struct ion_heap *ion_system_heap_create(struct ion_platform_heap *pheap)
{
struct ion_heap *heap;
@@ -323,6 +329,7 @@
return ERR_PTR(-ENOMEM);
heap->ops = &vmalloc_ops;
heap->type = ION_HEAP_TYPE_SYSTEM;
+ system_heap_has_outer_cache = pheap->has_outer_cache;
return heap;
}
@@ -394,31 +401,38 @@
unsigned int offset, unsigned int length,
unsigned int cmd)
{
- unsigned long vstart, pstart;
-
- pstart = virt_to_phys(buffer->priv_virt) + offset;
- if (!pstart) {
- WARN(1, "Could not do virt to phys translation on %p\n",
- buffer->priv_virt);
- return -EINVAL;
- }
-
- vstart = (unsigned long) vaddr;
+ void (*outer_cache_op)(phys_addr_t, phys_addr_t);
switch (cmd) {
case ION_IOC_CLEAN_CACHES:
- clean_caches(vstart, length, pstart);
+ dmac_clean_range(vaddr, vaddr + length);
+ outer_cache_op = outer_clean_range;
break;
case ION_IOC_INV_CACHES:
- invalidate_caches(vstart, length, pstart);
+ dmac_inv_range(vaddr, vaddr + length);
+ outer_cache_op = outer_inv_range;
break;
case ION_IOC_CLEAN_INV_CACHES:
- clean_and_invalidate_caches(vstart, length, pstart);
+ dmac_flush_range(vaddr, vaddr + length);
+ outer_cache_op = outer_flush_range;
break;
default:
return -EINVAL;
}
+ if (system_heap_contig_has_outer_cache) {
+ unsigned long pstart;
+
+ pstart = virt_to_phys(buffer->priv_virt) + offset;
+ if (!pstart) {
+ WARN(1, "Could not do virt to phys translation on %p\n",
+ buffer->priv_virt);
+ return -EINVAL;
+ }
+
+ outer_cache_op(pstart, pstart + PAGE_SIZE);
+ }
+
return 0;
}
@@ -524,7 +538,7 @@
.unmap_iommu = ion_system_heap_unmap_iommu,
};
-struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *unused)
+struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *pheap)
{
struct ion_heap *heap;
@@ -533,6 +547,7 @@
return ERR_PTR(-ENOMEM);
heap->ops = &kmalloc_ops;
heap->type = ION_HEAP_TYPE_SYSTEM_CONTIG;
+ system_heap_contig_has_outer_cache = pheap->has_outer_cache;
return heap;
}
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index c8bfce3..c239910 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -280,6 +280,7 @@
struct ion_platform_heap *heap_data = &pdata->heaps[i];
msm_ion_allocate(heap_data);
+ heap_data->has_outer_cache = pdata->has_outer_cache;
heaps[i] = ion_heap_create(heap_data);
if (IS_ERR_OR_NULL(heaps[i])) {
heaps[i] = 0;
diff --git a/include/linux/ion.h b/include/linux/ion.h
index b5495a0..d9443ff 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -148,6 +148,7 @@
* @base: base address of heap in physical memory if applicable
* @size: size of the heap in bytes if applicable
* @memory_type:Memory type used for the heap
+ * @has_outer_cache: set to 1 if outer cache is used, 0 otherwise.
* @extra_data: Extra data specific to each heap type
*/
struct ion_platform_heap {
@@ -157,6 +158,7 @@
ion_phys_addr_t base;
size_t size;
enum ion_memory_types memory_type;
+ unsigned int has_outer_cache;
void *extra_data;
};
@@ -228,6 +230,7 @@
/**
* struct ion_platform_data - array of platform heaps passed from board file
+ * @has_outer_cache: set to 1 if outer cache is used, 0 otherwise.
* @nr: number of structures in the array
* @request_region: function to be called when the number of allocations goes
* from 0 -> 1
@@ -239,6 +242,7 @@
* Provided by the board file in the form of platform data to a platform device.
*/
struct ion_platform_data {
+ unsigned int has_outer_cache;
int nr;
int (*request_region)(void *);
int (*release_region)(void *);