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

Commit b2ff7171 authored by James Hogan's avatar James Hogan Committed by Ralf Baechle
Browse files

MIPS: c-r4k: Fix flush_icache_range() for EVA



flush_icache_range() flushes icache lines in a protected fashion for
kernel addresses, however this isn't correct with EVA where protected
cache ops only operate on user addresses, making flush_icache_range()
ineffective.

Split the implementations of __flush_icache_user_range() from
flush_icache_range(), changing the normal flush_icache_range() to use
unprotected normal cache ops.

Signed-off-by: default avatarJames Hogan <james.hogan@imgtec.com>
Cc: Leonid Yegoshin <leonid.yegoshin@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/14156/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 24d1a6e6
Loading
Loading
Loading
Loading
+35 −8
Original line number Original line Diff line number Diff line
@@ -722,11 +722,13 @@ struct flush_icache_range_args {
	unsigned long start;
	unsigned long start;
	unsigned long end;
	unsigned long end;
	unsigned int type;
	unsigned int type;
	bool user;
};
};


static inline void __local_r4k_flush_icache_range(unsigned long start,
static inline void __local_r4k_flush_icache_range(unsigned long start,
						  unsigned long end,
						  unsigned long end,
						  unsigned int type)
						  unsigned int type,
						  bool user)
{
{
	if (!cpu_has_ic_fills_f_dc) {
	if (!cpu_has_ic_fills_f_dc) {
		if (type == R4K_INDEX ||
		if (type == R4K_INDEX ||
@@ -734,7 +736,10 @@ static inline void __local_r4k_flush_icache_range(unsigned long start,
			r4k_blast_dcache();
			r4k_blast_dcache();
		} else {
		} else {
			R4600_HIT_CACHEOP_WAR_IMPL;
			R4600_HIT_CACHEOP_WAR_IMPL;
			if (user)
				protected_blast_dcache_range(start, end);
				protected_blast_dcache_range(start, end);
			else
				blast_dcache_range(start, end);
		}
		}
	}
	}


@@ -748,7 +753,10 @@ static inline void __local_r4k_flush_icache_range(unsigned long start,
			break;
			break;


		default:
		default:
			if (user)
				protected_blast_icache_range(start, end);
				protected_blast_icache_range(start, end);
			else
				blast_icache_range(start, end);
			break;
			break;
		}
		}
	}
	}
@@ -757,7 +765,13 @@ static inline void __local_r4k_flush_icache_range(unsigned long start,
static inline void local_r4k_flush_icache_range(unsigned long start,
static inline void local_r4k_flush_icache_range(unsigned long start,
						unsigned long end)
						unsigned long end)
{
{
	__local_r4k_flush_icache_range(start, end, R4K_HIT | R4K_INDEX);
	__local_r4k_flush_icache_range(start, end, R4K_HIT | R4K_INDEX, false);
}

static inline void local_r4k_flush_icache_user_range(unsigned long start,
						     unsigned long end)
{
	__local_r4k_flush_icache_range(start, end, R4K_HIT | R4K_INDEX, true);
}
}


static inline void local_r4k_flush_icache_range_ipi(void *args)
static inline void local_r4k_flush_icache_range_ipi(void *args)
@@ -766,11 +780,13 @@ static inline void local_r4k_flush_icache_range_ipi(void *args)
	unsigned long start = fir_args->start;
	unsigned long start = fir_args->start;
	unsigned long end = fir_args->end;
	unsigned long end = fir_args->end;
	unsigned int type = fir_args->type;
	unsigned int type = fir_args->type;
	bool user = fir_args->user;


	__local_r4k_flush_icache_range(start, end, type);
	__local_r4k_flush_icache_range(start, end, type, user);
}
}


static void r4k_flush_icache_range(unsigned long start, unsigned long end)
static void __r4k_flush_icache_range(unsigned long start, unsigned long end,
				     bool user)
{
{
	struct flush_icache_range_args args;
	struct flush_icache_range_args args;
	unsigned long size, cache_size;
	unsigned long size, cache_size;
@@ -778,6 +794,7 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end)
	args.start = start;
	args.start = start;
	args.end = end;
	args.end = end;
	args.type = R4K_HIT | R4K_INDEX;
	args.type = R4K_HIT | R4K_INDEX;
	args.user = user;


	/*
	/*
	 * Indexed cache ops require an SMP call.
	 * Indexed cache ops require an SMP call.
@@ -803,6 +820,16 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end)
	instruction_hazard();
	instruction_hazard();
}
}


static void r4k_flush_icache_range(unsigned long start, unsigned long end)
{
	return __r4k_flush_icache_range(start, end, false);
}

static void r4k_flush_icache_user_range(unsigned long start, unsigned long end)
{
	return __r4k_flush_icache_range(start, end, true);
}

#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_DMA_MAYBE_COHERENT)
#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_DMA_MAYBE_COHERENT)


static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
@@ -1904,8 +1931,8 @@ void r4k_cache_init(void)
	flush_data_cache_page	= r4k_flush_data_cache_page;
	flush_data_cache_page	= r4k_flush_data_cache_page;
	flush_icache_range	= r4k_flush_icache_range;
	flush_icache_range	= r4k_flush_icache_range;
	local_flush_icache_range	= local_r4k_flush_icache_range;
	local_flush_icache_range	= local_r4k_flush_icache_range;
	__flush_icache_user_range	= r4k_flush_icache_range;
	__flush_icache_user_range	= r4k_flush_icache_user_range;
	__local_flush_icache_user_range	= local_r4k_flush_icache_range;
	__local_flush_icache_user_range	= local_r4k_flush_icache_user_range;


#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_DMA_MAYBE_COHERENT)
#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_DMA_MAYBE_COHERENT)
	if (coherentio) {
	if (coherentio) {