From 0d0e14770d4487a7ede8df93d82305cbfac2d453 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 27 Jul 2018 18:23:18 -0700 Subject: MIPS: Make (UN)CAC_ADDR() PHYS_OFFSET-agnostic Converting an address between cached & uncached (typically addresses in (c)kseg0 & (c)kseg1 or 2 xkphys regions) should not depend upon PHYS_OFFSET in any way - we're converting from a virtual address in one unmapped region to a virtual address in another unmapped region. For some reason our CAC_ADDR() & UNCAC_ADDR() macros make use of PAGE_OFFSET, which typically includes PHYS_OFFSET. This means that platforms with a non-zero PHYS_OFFSET typically have to workaround miscalculation by these 2 macros by also defining UNCAC_BASE to a value that isn't really correct. It appears that an attempt has previously been made to address this with commit 3f4579252aa1 ("MIPS: make CAC_ADDR and UNCAC_ADDR account for PHYS_OFFSET") which was later undone by commit ed3ce16c3d2b ("Revert "MIPS: make CAC_ADDR and UNCAC_ADDR account for PHYS_OFFSET"") which also introduced the ar7 workaround. That attempt at a fix was roughly equivalent, but essentially caused the CAC_ADDR() & UNCAC_ADDR() macros to cancel out PHYS_OFFSET by adding & then subtracting it again. In his revert Leonid is correct that using PHYS_OFFSET makes no sense in the context of these macros, but appears to have missed its inclusion via PAGE_OFFSET which means PHYS_OFFSET actually had an effect after the revert rather than before it. Here we fix this by modifying CAC_ADDR() & UNCAC_ADDR() to stop using PAGE_OFFSET (& thus PHYS_OFFSET), instead using __pa() & __va() along with UNCAC_BASE. For UNCAC_ADDR(), __pa() will convert a cached address to a physical address which we can simply use as an offset from UNCAC_BASE to obtain an address in the uncached region. For CAC_ADDR() we can undo the effect of UNCAC_ADDR() by subtracting UNCAC_BASE and using __va() on the result. With this change made, remove definitions of UNCAC_BASE from the ar7 & pic32 platforms which appear to have defined them only to workaround this problem. Signed-off-by: Paul Burton References: 3f4579252aa1 ("MIPS: make CAC_ADDR and UNCAC_ADDR account for PHYS_OFFSET") References: ed3ce16c3d2b ("Revert "MIPS: make CAC_ADDR and UNCAC_ADDR account for PHYS_OFFSET"") Patchwork: https://patchwork.linux-mips.org/patch/20046/ Cc: Florian Fainelli Cc: James Hogan Cc: Ralf Baechle Cc: linux-mips@linux-mips.org Cc: Vladimir Kondratiev --- arch/mips/include/asm/mach-ar7/spaces.h | 3 --- arch/mips/include/asm/mach-pic32/spaces.h | 1 - arch/mips/include/asm/page.h | 4 ++-- arch/mips/jazz/jazzdma.c | 2 +- arch/mips/mm/dma-noncoherent.c | 2 +- 5 files changed, 4 insertions(+), 8 deletions(-) diff --git a/arch/mips/include/asm/mach-ar7/spaces.h b/arch/mips/include/asm/mach-ar7/spaces.h index 660ab64c0fc9..a004d94dfbdd 100644 --- a/arch/mips/include/asm/mach-ar7/spaces.h +++ b/arch/mips/include/asm/mach-ar7/spaces.h @@ -17,9 +17,6 @@ #define PAGE_OFFSET _AC(0x94000000, UL) #define PHYS_OFFSET _AC(0x14000000, UL) -#define UNCAC_BASE _AC(0xb4000000, UL) /* 0xa0000000 + PHYS_OFFSET */ -#define IO_BASE UNCAC_BASE - #include #endif /* __ASM_AR7_SPACES_H */ diff --git a/arch/mips/include/asm/mach-pic32/spaces.h b/arch/mips/include/asm/mach-pic32/spaces.h index 046a0a9aa8b3..a1b9783b76ea 100644 --- a/arch/mips/include/asm/mach-pic32/spaces.h +++ b/arch/mips/include/asm/mach-pic32/spaces.h @@ -16,7 +16,6 @@ #ifdef CONFIG_PIC32MZDA #define PHYS_OFFSET _AC(0x08000000, UL) -#define UNCAC_BASE _AC(0xa8000000, UL) #endif #include diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h index ad461216b5a1..a051b82f8009 100644 --- a/arch/mips/include/asm/page.h +++ b/arch/mips/include/asm/page.h @@ -252,8 +252,8 @@ extern int __virt_addr_valid(const volatile void *kaddr); ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) -#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE) -#define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET) +#define UNCAC_ADDR(addr) (UNCAC_BASE + __pa(addr)) +#define CAC_ADDR(addr) ((unsigned long)__va((addr) - UNCAC_BASE)) #include #include diff --git a/arch/mips/jazz/jazzdma.c b/arch/mips/jazz/jazzdma.c index 446fc8c92e1e..d31bc2f01208 100644 --- a/arch/mips/jazz/jazzdma.c +++ b/arch/mips/jazz/jazzdma.c @@ -576,7 +576,7 @@ static void *jazz_dma_alloc(struct device *dev, size_t size, if (!(attrs & DMA_ATTR_NON_CONSISTENT)) { dma_cache_wback_inv((unsigned long)ret, size); - ret = UNCAC_ADDR(ret); + ret = (void *)UNCAC_ADDR(ret); } return ret; } diff --git a/arch/mips/mm/dma-noncoherent.c b/arch/mips/mm/dma-noncoherent.c index 25edf6d6b686..2aca1236af36 100644 --- a/arch/mips/mm/dma-noncoherent.c +++ b/arch/mips/mm/dma-noncoherent.c @@ -78,7 +78,7 @@ void *arch_dma_alloc(struct device *dev, size_t size, if (!dev_is_coherent(dev) && !(attrs & DMA_ATTR_NON_CONSISTENT)) { dma_cache_wback_inv((unsigned long) ret, size); - ret = UNCAC_ADDR(ret); + ret = (void *)UNCAC_ADDR(ret); } return ret; -- cgit v1.2.3