Skip to content
Browse files

mm: ashmem: Add cache clean and invalidate ioctls for ashmem

Change-Id: Idc120f9f869c1a68e5f012327aa7f599ac065fce
CRs-fixed: 291124
Signed-off-by: Shubhraprakash Das <sadas@codeaurora.org>
  • Loading branch information...
1 parent 3a71671 commit 8b9f2f43489dd52cc9a4da7252d927f2218b419c Shubhraprakash Das committed with dalingrin Jul 18, 2011
Showing with 35 additions and 40 deletions.
  1. +2 −0 include/linux/ashmem.h
  2. +33 −40 mm/ashmem.c
View
2 include/linux/ashmem.h
@@ -45,6 +45,8 @@ struct ashmem_pin {
#define ASHMEM_GET_PIN_STATUS _IO(__ASHMEMIOC, 9)
#define ASHMEM_PURGE_ALL_CACHES _IO(__ASHMEMIOC, 10)
#define ASHMEM_CACHE_FLUSH_RANGE _IO(__ASHMEMIOC, 11)
+#define ASHMEM_CACHE_CLEAN_RANGE _IO(__ASHMEMIOC, 12)
+#define ASHMEM_CACHE_INV_RANGE _IO(__ASHMEMIOC, 13)
int get_ashmem_file(int fd, struct file **filp, struct file **vm_file,
unsigned long *len);
View
73 mm/ashmem.c
@@ -631,77 +631,64 @@ static int ashmem_pin_unpin(struct ashmem_area *asma, unsigned long cmd,
}
#ifdef CONFIG_OUTER_CACHE
-static unsigned int kgsl_virtaddr_to_physaddr(unsigned int virtaddr)
+static unsigned int virtaddr_to_physaddr(unsigned int virtaddr)
{
unsigned int physaddr = 0;
pgd_t *pgd_ptr = NULL;
pmd_t *pmd_ptr = NULL;
pte_t *pte_ptr = NULL, pte;
+ spin_lock(&current->mm->page_table_lock);
pgd_ptr = pgd_offset(current->mm, virtaddr);
if (pgd_none(*pgd) || pgd_bad(*pgd)) {
- pr_info
- ("Invalid pgd entry found while trying to convert virtual "
- "address to physical\n");
- return 0;
+ pr_err("Failed to convert virtaddr %x to pgd_ptr\n",
+ virtaddr);
+ goto done;
}
pmd_ptr = pmd_offset(pgd_ptr, virtaddr);
if (pmd_none(*pmd_ptr) || pmd_bad(*pmd_ptr)) {
- pr_info
- ("Invalid pmd entry found while trying to convert virtual "
- "address to physical\n");
- return 0;
+ pr_err("Failed to convert pgd_ptr %p to pmd_ptr\n",
+ (void *)pgd_ptr);
+ goto done;
}
pte_ptr = pte_offset_map(pmd_ptr, virtaddr);
if (!pte_ptr) {
- pr_info
- ("Unable to map pte entry while trying to convert virtual "
- "address to physical\n");
- return 0;
+ pr_err("Failed to convert pmd_ptr %p to pte_ptr\n",
+ (void *)pmd_ptr);
+ goto done;
}
pte = *pte_ptr;
physaddr = pte_pfn(pte);
pte_unmap(pte_ptr);
+done:
+ spin_unlock(&current->mm->page_table_lock);
physaddr <<= PAGE_SHIFT;
return physaddr;
}
#endif
-static int ashmem_flush_cache_range(struct ashmem_area *asma)
+static int ashmem_cache_op(struct ashmem_area *asma,
+ void (*cache_func)(unsigned long vstart, unsigned long length,
+ unsigned long pstart))
{
#ifdef CONFIG_OUTER_CACHE
- unsigned long end;
+ unsigned long vaddr;
#endif
- unsigned long addr;
- unsigned int size, result = 0;
-
mutex_lock(&ashmem_mutex);
-
- size = asma->size;
- addr = asma->vm_start;
- if (!addr || (addr & (PAGE_SIZE - 1)) || !size ||
- (size & (PAGE_SIZE - 1))) {
- result = -EINVAL;
- goto done;
- }
-
- flush_cache_user_range(addr, addr + size);
-#ifdef CONFIG_OUTER_CACHE
- for (end = addr; end < (addr + size); end += PAGE_SIZE) {
+#ifndef CONFIG_OUTER_CACHE
+ cache_func(asma->vm_start, asma->size, 0);
+#else
+ for (vaddr = asma->vm_start; vaddr < asma->vm_start + asma->size;
+ vaddr += PAGE_SIZE) {
unsigned long physaddr;
- physaddr = kgsl_virtaddr_to_physaddr(end);
- if (!physaddr) {
- result = -EINVAL;
- goto done;
- }
-
- outer_flush_range(physaddr, physaddr + PAGE_SIZE);
+ physaddr = virtaddr_to_physaddr(vaddr);
+ if (!physaddr)
+ return -EINVAL;
+ cache_func(vaddr, PAGE_SIZE, physaddr);
}
- mb();
#endif
-done:
mutex_unlock(&ashmem_mutex);
return 0;
}
@@ -747,7 +734,13 @@ static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
break;
case ASHMEM_CACHE_FLUSH_RANGE:
- ret = ashmem_flush_cache_range(asma);
+ ret = ashmem_cache_op(asma, &clean_and_invalidate_caches);
+ break;
+ case ASHMEM_CACHE_CLEAN_RANGE:
+ ret = ashmem_cache_op(asma, &clean_caches);
+ break;
+ case ASHMEM_CACHE_INV_RANGE:
+ ret = ashmem_cache_op(asma, &invalidate_caches);
break;
}

0 comments on commit 8b9f2f4

Please sign in to comment.
Something went wrong with that request. Please try again.