Commit 2b83878d authored by Max Filippov's avatar Max Filippov

xtensa: make __pa work with uncached KSEG addresses

When __pa is applied to virtual address in uncached KSEG region the
result is incorrect. Fix it by checking if the original address is in
the uncached KSEG and adjusting the result. It looks better than masking
off bits because pfn_valid would correctly work with new __pa results
and it may be made working in noMMU case, once we get definition for
uncached memory view.

This is required for the dma_common_mmap and DMA debug code to work
correctly: they both indirectly use __pa with coherent DMA addresses.
In case of DMA debug the visible effect is false reports that an address
mapped for DMA is accessed by CPU.

Cc: stable@vger.kernel.org
Tested-by: default avatarBoris Brezillon <boris.brezillon@free-electrons.com>
Reviewed-by: default avatarBoris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: default avatarMax Filippov <jcmvbkbc@gmail.com>
parent c02ed2e7
...@@ -164,8 +164,21 @@ void copy_user_highpage(struct page *to, struct page *from, ...@@ -164,8 +164,21 @@ void copy_user_highpage(struct page *to, struct page *from,
#define ARCH_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT) #define ARCH_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT)
#ifdef CONFIG_MMU
static inline unsigned long ___pa(unsigned long va)
{
unsigned long off = va - PAGE_OFFSET;
if (off >= XCHAL_KSEG_SIZE)
off -= XCHAL_KSEG_SIZE;
return off + PHYS_OFFSET;
}
#define __pa(x) ___pa((unsigned long)(x))
#else
#define __pa(x) \ #define __pa(x) \
((unsigned long) (x) - PAGE_OFFSET + PHYS_OFFSET) ((unsigned long) (x) - PAGE_OFFSET + PHYS_OFFSET)
#endif
#define __va(x) \ #define __va(x) \
((void *)((unsigned long) (x) - PHYS_OFFSET + PAGE_OFFSET)) ((void *)((unsigned long) (x) - PHYS_OFFSET + PAGE_OFFSET))
#define pfn_valid(pfn) \ #define pfn_valid(pfn) \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment