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

Commit ab61f7d2 authored by Haavard Skinnemoen's avatar Haavard Skinnemoen
Browse files

[AVR32] Fix bug in invalidate_dcache_region()



If (start + size) is not cacheline aligned and (start & mask) > (end &
mask), the last but one cacheline won't be invalidated as it should.
Fix this by rounding `end' down to the nearest cacheline boundary if
it gets adjusted due to misalignment.

Also flush the write buffer unconditionally -- if the dcache wrote
back a line just before we invalidated it, the dirty data may be
sitting in the write buffer waiting to corrupt our buffer later.

Signed-off-by: default avatarHaavard Skinnemoen <hskinnemoen@atmel.com>
parent 75154f40
Loading
Loading
Loading
Loading
+5 −9
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@
void invalidate_dcache_region(void *start, size_t size)
{
	unsigned long v, begin, end, linesz, mask;
	int flush = 0;

	linesz = boot_cpu_data.dcache.linesz;
	mask = linesz - 1;
@@ -32,23 +31,20 @@ void invalidate_dcache_region(void *start, size_t size)
	 * instead of invalidating ... never discard valid data!
	 */
	begin = (unsigned long)start;
	end = begin + size - 1;
	end = begin + size;

	if (begin & mask) {
		flush_dcache_line(start);
		begin += linesz;
		flush = 1;
	}
	if ((end & mask) != mask) {
	if (end & mask) {
		flush_dcache_line((void *)end);
		end -= linesz;
		flush = 1;
		end &= ~mask;
	}

	/* remaining cachelines only need invalidation */
	for (v = begin; v <= end; v += linesz)
	for (v = begin; v < end; v += linesz)
		invalidate_dcache_line((void *)v);
	if (flush)
	flush_write_buffer();
}