Commit 9a74b3eb authored by Ralf Baechle's avatar Ralf Baechle

[MIPS] Fix buggy invocations of kmap_coherent()

kmap_coherent will only work correctly if the page it is called on is
not marked dirty.  If it's dirty the kernel address of the page should
be used instead of a temporary mapping.
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent c42d95d6
...@@ -92,12 +92,17 @@ EXPORT_SYMBOL(__flush_dcache_page); ...@@ -92,12 +92,17 @@ EXPORT_SYMBOL(__flush_dcache_page);
void __flush_anon_page(struct page *page, unsigned long vmaddr) void __flush_anon_page(struct page *page, unsigned long vmaddr)
{ {
if (pages_do_alias((unsigned long)page_address(page), vmaddr)) { unsigned long addr = (unsigned long) page_address(page);
void *kaddr;
kaddr = kmap_coherent(page, vmaddr); if (pages_do_alias(addr, vmaddr)) {
flush_data_cache_page((unsigned long)kaddr); if (page_mapped(page) && !Page_dcache_dirty(page)) {
kunmap_coherent(); void *kaddr;
kaddr = kmap_coherent(page, vmaddr);
flush_data_cache_page((unsigned long)kaddr);
kunmap_coherent();
} else
flush_data_cache_page(addr);
} }
} }
......
...@@ -211,7 +211,8 @@ void copy_user_highpage(struct page *to, struct page *from, ...@@ -211,7 +211,8 @@ void copy_user_highpage(struct page *to, struct page *from,
void *vfrom, *vto; void *vfrom, *vto;
vto = kmap_atomic(to, KM_USER1); vto = kmap_atomic(to, KM_USER1);
if (cpu_has_dc_aliases && page_mapped(from)) { if (cpu_has_dc_aliases &&
page_mapped(from) && !Page_dcache_dirty(from)) {
vfrom = kmap_coherent(from, vaddr); vfrom = kmap_coherent(from, vaddr);
copy_page(vto, vfrom); copy_page(vto, vfrom);
kunmap_coherent(); kunmap_coherent();
...@@ -234,7 +235,8 @@ void copy_to_user_page(struct vm_area_struct *vma, ...@@ -234,7 +235,8 @@ void copy_to_user_page(struct vm_area_struct *vma,
struct page *page, unsigned long vaddr, void *dst, const void *src, struct page *page, unsigned long vaddr, void *dst, const void *src,
unsigned long len) unsigned long len)
{ {
if (cpu_has_dc_aliases && page_mapped(page)) { if (cpu_has_dc_aliases &&
page_mapped(page) && !Page_dcache_dirty(page)) {
void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
memcpy(vto, src, len); memcpy(vto, src, len);
kunmap_coherent(); kunmap_coherent();
...@@ -253,7 +255,8 @@ void copy_from_user_page(struct vm_area_struct *vma, ...@@ -253,7 +255,8 @@ void copy_from_user_page(struct vm_area_struct *vma,
struct page *page, unsigned long vaddr, void *dst, const void *src, struct page *page, unsigned long vaddr, void *dst, const void *src,
unsigned long len) unsigned long len)
{ {
if (cpu_has_dc_aliases && page_mapped(page)) { if (cpu_has_dc_aliases &&
page_mapped(page) && !Page_dcache_dirty(page)) {
void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
memcpy(dst, vfrom, len); memcpy(dst, vfrom, len);
kunmap_coherent(); kunmap_coherent();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment