static long kgsl_cache_range_op(unsigned long addr, int size, unsigned int flags) { #ifdef CONFIG_OUTER_CACHE unsigned long end; #endif BUG_ON(addr & (KGSL_PAGESIZE - 1)); BUG_ON(size & (KGSL_PAGESIZE - 1)); if (flags & KGSL_CACHE_FLUSH) dmac_flush_range((const void *)addr, (const void *)(addr + size)); else if (flags & KGSL_CACHE_CLEAN) dmac_clean_range((const void *)addr, (const void *)(addr + size)); else dmac_inv_range((const void *)addr, (const void *)(addr + size)); #ifdef CONFIG_OUTER_CACHE for (end = addr; end < (addr + size); end += KGSL_PAGESIZE) { pte_t *pte_ptr, pte; unsigned long physaddr; if (flags & KGSL_CACHE_VMALLOC_ADDR) physaddr = vmalloc_to_pfn((void *)end); else if (flags & KGSL_CACHE_USER_ADDR) { pte_ptr = kgsl_get_pte_from_vaddr(end); if (!pte_ptr) return -EINVAL; pte = *pte_ptr; physaddr = pte_pfn(pte); pte_unmap(pte_ptr); } else return -EINVAL; physaddr <<= PAGE_SHIFT; if (flags & KGSL_CACHE_FLUSH) outer_flush_range(physaddr, physaddr + KGSL_PAGESIZE); else if (flags & KGSL_CACHE_CLEAN) outer_clean_range(physaddr, physaddr + KGSL_PAGESIZE); else outer_inv_range(physaddr, physaddr + KGSL_PAGESIZE); } #endif return 0; }
static long flush_l1_cache_range(unsigned long addr, int size) { struct page *page; pte_t *pte_ptr; unsigned long end; for (end = addr; end < (addr + size); end += KGSL_PAGESIZE) { pte_ptr = kgsl_get_pte_from_vaddr(end); if (!pte_ptr) return -EINVAL; page = pte_page(pte_val(*pte_ptr)); if (!page) { KGSL_DRV_ERR("could not find page for pte\n"); pte_unmap(pte_ptr); return -EINVAL; } pte_unmap(pte_ptr); flush_dcache_page(page); } return 0; }