diff options
author | Krishna Reddy <vdumpa@nvidia.com> | 2011-12-02 12:40:21 -0800 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2012-01-19 16:16:24 -0800 |
commit | 7d198798dd246d0b20e06d6f933e96cfde3b60fd (patch) | |
tree | 2bdd26cde53656ba1b2749465b0e9bb18cee76ac /arch/arm/mm | |
parent | 24f020cec2e6c3328620ad0c43e171c59f648370 (diff) |
arm: mm: Optimze cache flush in CPA.
Optimze cache flush time and enable cache flush for high mem pages in CPA.
Bug 865816
Change-Id: I15736010bd26c18ea0d3350c15769675f07ac055
Reviewed-on: http://git-master/r/71725
Signed-off-by: Krishna Reddy <vdumpa@nvidia.com>
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Reviewed-on: http://git-master/r/75880
Reviewed-by: Automatic_Commit_Validation_User
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/pageattr.c | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/arch/arm/mm/pageattr.c b/arch/arm/mm/pageattr.c index 098b957454f6..2026c5100473 100644 --- a/arch/arm/mm/pageattr.c +++ b/arch/arm/mm/pageattr.c @@ -29,6 +29,10 @@ #define cpa_debug(x, ...) #endif +#define FLUSH_CLEAN_BY_SET_WAY_PAGE_THRESHOLD 8 +extern void v7_flush_kern_cache_all(void *); +extern void __flush_dcache_page(struct address_space *, struct page *); + /* * The current flushing context - we pass it instead of 5 arguments: */ @@ -125,13 +129,26 @@ static void cpa_flush_range(unsigned long start, int numpages, int cache) } } +static void inner_flush_cache_all(void) +{ + on_each_cpu(v7_flush_kern_cache_all, NULL, 1); +} + static void cpa_flush_array(unsigned long *start, int numpages, int cache, int in_flags, struct page **pages) { unsigned int i, level; + bool flush_inner = true; + unsigned long base; BUG_ON(irqs_disabled()); + if (numpages >= FLUSH_CLEAN_BY_SET_WAY_PAGE_THRESHOLD && + cache && in_flags & CPA_PAGES_ARRAY) { + inner_flush_cache_all(); + flush_inner = false; + } + for (i = 0; i < numpages; i++) { unsigned long addr; pte_t *pte; @@ -143,8 +160,14 @@ static void cpa_flush_array(unsigned long *start, int numpages, int cache, flush_tlb_kernel_range(addr, addr + PAGE_SIZE); - if (cache) { - + if (cache && in_flags & CPA_PAGES_ARRAY) { + /* cache flush all pages including high mem pages. */ + if (flush_inner) + __flush_dcache_page( + page_mapping(pages[i]), pages[i]); + base = page_to_phys(pages[i]); + outer_flush_range(base, base + PAGE_SIZE); + } else if (cache) { pte = lookup_address(addr, &level); /* @@ -795,14 +818,14 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages, ret = __change_page_attr_set_clr(&cpa, checkalias); + cache = cache_attr(mask_set); /* - * Check whether we really changed something: + * Check whether we really changed something or + * cache need to be flushed. */ - if (!(cpa.flags & CPA_FLUSHTLB)) + if (!(cpa.flags & CPA_FLUSHTLB) && !cache) goto out; - cache = cache_attr(mask_set); - if (cpa.flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) { cpa_flush_array(addr, numpages, cache, cpa.flags, pages); |