summaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/flush.c
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2005-06-20 10:51:03 +0200
committerRussell King <rmk@dyn-67.arm.linux.org.uk>2005-06-20 10:51:03 +0200
commit8830f04a092b47f3d246271b24685cd9eab82027 (patch)
tree8258af450ec736fd0ff3cf0864eb5407b3f8b5ff /arch/arm/mm/flush.c
parentMerge with ../linux-2.6-smp (diff)
downloadlinux-8830f04a092b47f3d246271b24685cd9eab82027.tar.xz
linux-8830f04a092b47f3d246271b24685cd9eab82027.zip
[PATCH] ARM: Fix delayed dcache flush for ARMv6 non-aliasing caches
flush_dcache_page() did nothing for these caches, but since they suffer from I/D cache coherency issues, we need to ensure that data is written back to RAM. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm/flush.c')
-rw-r--r--arch/arm/mm/flush.c44
1 files changed, 18 insertions, 26 deletions
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 4085ed983e46..191788fb18d1 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -37,13 +37,8 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
#define flush_pfn_alias(pfn,vaddr) do { } while (0)
#endif
-static void __flush_dcache_page(struct address_space *mapping, struct page *page)
+void __flush_dcache_page(struct address_space *mapping, struct page *page)
{
- struct mm_struct *mm = current->active_mm;
- struct vm_area_struct *mpnt;
- struct prio_tree_iter iter;
- pgoff_t pgoff;
-
/*
* Writeback any data associated with the kernel mapping of this
* page. This ensures that data in the physical page is mutually
@@ -52,24 +47,21 @@ static void __flush_dcache_page(struct address_space *mapping, struct page *page
__cpuc_flush_dcache_page(page_address(page));
/*
- * If there's no mapping pointer here, then this page isn't
- * visible to userspace yet, so there are no cache lines
- * associated with any other aliases.
- */
- if (!mapping)
- return;
-
- /*
- * This is a page cache page. If we have a VIPT cache, we
- * only need to do one flush - which would be at the relevant
+ * If this is a page cache page, and we have an aliasing VIPT cache,
+ * we only need to do one flush - which would be at the relevant
* userspace colour, which is congruent with page->index.
*/
- if (cache_is_vipt()) {
- if (cache_is_vipt_aliasing())
- flush_pfn_alias(page_to_pfn(page),
- page->index << PAGE_CACHE_SHIFT);
- return;
- }
+ if (mapping && cache_is_vipt_aliasing())
+ flush_pfn_alias(page_to_pfn(page),
+ page->index << PAGE_CACHE_SHIFT);
+}
+
+static void __flush_dcache_aliases(struct address_space *mapping, struct page *page)
+{
+ struct mm_struct *mm = current->active_mm;
+ struct vm_area_struct *mpnt;
+ struct prio_tree_iter iter;
+ pgoff_t pgoff;
/*
* There are possible user space mappings of this page:
@@ -116,12 +108,12 @@ void flush_dcache_page(struct page *page)
{
struct address_space *mapping = page_mapping(page);
- if (cache_is_vipt_nonaliasing())
- return;
-
if (mapping && !mapping_mapped(mapping))
set_bit(PG_dcache_dirty, &page->flags);
- else
+ else {
__flush_dcache_page(mapping, page);
+ if (mapping && cache_is_vivt())
+ __flush_dcache_aliases(mapping, page);
+ }
}
EXPORT_SYMBOL(flush_dcache_page);