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

Commit 26b7a78c authored by Paul Mundt's avatar Paul Mundt
Browse files

sh: Lazy dcache writeback optimizations.



This converts the lazy dcache handling to the model described in
Documentation/cachetlb.txt and drops the ptep_get_and_clear() hacks
used for the aliasing dcaches on SH-4 and SH7705 in 32kB mode. As a
bonus, this slightly cuts down on the cache flushing frequency.

With that and the PTEA handling out of the way, the update_mmu_cache()
implementations can be consolidated, and we no longer have to worry
about which configuration the cache is in for the SH7705 case.

And finally, explicitly disable the lazy writeback on SMP (SH-4A).

Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 7a847f81
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -181,10 +181,6 @@ int __init detect_cpu_and_cache_system(void)
	cpu_data->dcache.ways = 1;
#endif

#ifdef CONFIG_CPU_HAS_PTEA
	cpu_data->flags |= CPU_HAS_PTEA;
#endif

	/*
	 * On anything that's not a direct-mapped cache, look to the CVR
	 * for I/D-cache specifics.
+1 −1
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ config CPU_SH4
	bool
	select CPU_HAS_INTEVT
	select CPU_HAS_SR_RB
	select CPU_HAS_PTEA if !CPU_SUBTYPE_ST40
	select CPU_HAS_PTEA if (!CPU_SUBTYPE_ST40 && !CPU_SH4A) || CPU_SHX2

config CPU_SH4A
	bool
+11 −1
Original line number Diff line number Diff line
@@ -236,10 +236,20 @@ static inline void flush_cache_4096(unsigned long start,
/*
 * Write back & invalidate the D-cache of the page.
 * (To avoid "alias" issues)
 *
 * This uses a lazy write-back on UP, which is explicitly
 * disabled on SMP.
 */
void flush_dcache_page(struct page *page)
{
	if (test_bit(PG_mapped, &page->flags)) {
#ifndef CONFIG_SMP
	struct address_space *mapping = page_mapping(page);

	if (mapping && !mapping_mapped(mapping))
		set_bit(PG_dcache_dirty, &page->flags);
	else
#endif
	{
		unsigned long phys = PHYSADDR(page_address(page));
		unsigned long addr = CACHE_OC_ADDRESS_ARRAY;
		int i, n;
+6 −3
Original line number Diff line number Diff line
@@ -3,11 +3,11 @@
 *
 * Copyright (C) 1999, 2000  Niibe Yutaka
 * Copyright (C) 2004  Alex Song
 * Copyright (C) 2006  Paul Mundt
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 */
#include <linux/init.h>
#include <linux/mman.h>
@@ -51,7 +51,6 @@ static inline void cache_wback_all(void)

			if ((data & v) == v)
				ctrl_outl(data & ~v, addr);

		}

		addrstart += cpu_data->dcache.way_incr;
@@ -128,7 +127,11 @@ static void __flush_dcache_page(unsigned long phys)
 */
void flush_dcache_page(struct page *page)
{
	if (test_bit(PG_mapped, &page->flags))
	struct address_space *mapping = page_mapping(page);

	if (mapping && !mapping_mapped(mapping))
		set_bit(PG_dcache_dirty, &page->flags);
	else
		__flush_dcache_page(PHYSADDR(page_address(page)));
}

+0 −22
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ extern struct mutex p3map_mutex[];
 */
void clear_user_page(void *to, unsigned long address, struct page *page)
{
	__set_bit(PG_mapped, &page->flags);
	if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
		clear_page(to);
	else {
@@ -59,7 +58,6 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
void copy_user_page(void *to, void *from, unsigned long address,
		    struct page *page)
{
	__set_bit(PG_mapped, &page->flags);
	if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
		copy_page(to, from);
	else {
@@ -84,23 +82,3 @@ void copy_user_page(void *to, void *from, unsigned long address,
		mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
	}
}

/*
 * For SH-4, we have our own implementation for ptep_get_and_clear
 */
inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
	pte_t pte = *ptep;

	pte_clear(mm, addr, ptep);
	if (!pte_not_present(pte)) {
		unsigned long pfn = pte_pfn(pte);
		if (pfn_valid(pfn)) {
			struct page *page = pfn_to_page(pfn);
			struct address_space *mapping = page_mapping(page);
			if (!mapping || !mapping_writably_mapped(mapping))
				__clear_bit(PG_mapped, &page->flags);
		}
	}
	return pte;
}
Loading