Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 13f96d8f authored by Nicolas Pitre's avatar Nicolas Pitre Committed by Russell King
Browse files

ARM: 5687/1: fix an oops with highmem



In xdr_partial_copy_from_skb() there is that sequence:

		kaddr = kmap_atomic(*ppage, KM_SKB_SUNRPC_DATA);
		[...]
		flush_dcache_page(*ppage);
		kunmap_atomic(kaddr, KM_SKB_SUNRPC_DATA);

Mixing flush_dcache_page() and kmap_atomic() is a bit odd,
especially since kunmap_atomic() must deal with cache issues
already.  OTOH the non-highmem case must use flush_dcache_page()
as kunmap_atomic() becomes a no op with no cache maintenance.

Problem is that with highmem the implementation of kmap_atomic()
doesn't set page->virtual, and page_address(page) returns 0 in
that case. Here flush_dcache_page() calls __flush_dcache_page()
which calls __cpuc_flush_dcache_page(page_address(page)) resulting
in a kernel oops.

None of the kmap_atomic() implementations uses set_page_address().
Hence we can assume page_address() is always expected to return 0 in
that case. Let's conditionally call __cpuc_flush_dcache_page() only
when the page address is non zero, and perform that test only when
highmem is configured.

Signed-off-by: default avatarNicolas Pitre <nico@marvell.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 37d0892c
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -144,6 +144,13 @@ void __flush_dcache_page(struct address_space *mapping, struct page *page)
	 * page.  This ensures that data in the physical page is mutually
	 * coherent with the kernels mapping.
	 */
#ifdef CONFIG_HIGHMEM
	/*
	 * kmap_atomic() doesn't set the page virtual address, and
	 * kunmap_atomic() takes care of cache flushing already.
	 */
	if (page_address(page))
#endif
		__cpuc_flush_dcache_page(page_address(page));

	/*