The issue (addr == 0) you mentioned had been discussed before
(http://www.linux-mips.org/archives/linux-mips/2008-03/msg00011.html).
For some reasons, the solution couldn't be accepted.
Since then, we haven't touched that function until the changes of
"kmap_high_get" were involved. The changes we made in
"__flush_dcache_page" (below) should fix the problem which has been
resolved in ARM.
Dezhong
void __flush_dcache_page(struct page *page)
{
struct address_space *mapping = page_mapping(page);
void *addr;
/* If there is a temporary kernel mapping, i.e. if kmap_atomic was
* used to map a page, we only need to flush the page. We can skip
* the other work here because it won't be used in any other way. */
if (PageHighMem(page)) {
addr = kmap_atomic_to_vaddr(page);
if (addr != NULL) {
flush_data_cache_page((unsigned long) addr);
return;
}
}
/* If page_mapping returned a non-NULL value, then the page is not
* in the swap cache and it isn't anonymously mapped. If it's not
* already mapped into user space, we can just set the dirty bit to
* get the cache flushed later, if needed */
if (mapping && !mapping_mapped(mapping)) {
SetPageDcacheDirty(page);
return;
}
/*
* We could delay the flush for the !page_mapping case too. But that
* case is for exec env/arg pages and those are %99 certainly going to
* get faulted into the tlb (and thus flushed) anyways.
*/
if (!PageHighMem(page)) {
addr = page_address(page);
flush_data_cache_page((unsigned long) addr);
} else {
if (!cpu_has_dc_aliases) {
addr = kmap_high_get(page);
if (addr) {
/* The page has been kmapped */
flush_data_cache_page((unsigned long) addr);
kunmap_high(page);
} else {
/* Alright, we need a temporary kernel mapping. Since we are on
* a processor that has hardware to eliminate data cache
* aliases, we don't have to get an address whose virtual index
* into the cache that matches the index originally used to map
* the page. This makes the task doable. */
addr = kmap_atomic(page, KM_MIPS_SYNC_PAGE);
flush_data_cache_page((unsigned long) addr);
kunmap_atomic(addr, KM_MIPS_SYNC_PAGE);
}
} else {
/* Sorry, we may have data cache aliases, which means that we
* have to be able to get a virtual address whose virtual index
* into cache matches the index used to map this page. This is
* hard and so, just like the hard problems in my Physics
* classes, is left as an exercise for the reader. */
panic("Unable to flush page 0x%p on processor with data cache "
"aliases\n", page);
}
}
}
|