Skip to content

Commit 0d8d83d

Browse files
paulburtonralfbaechle
authored andcommitted
MIPS: Use CPHYSADDR to implement mips32 __pa
Use CPHYSADDR to implement the __pa macro converting from a virtual to a physical address for MIPS32, much as is already done for MIPS64 (though without the complication of having both compatibility & XKPHYS segments). This allows for __pa to work regardless of whether the address being translated is in kseg0 or kseg1, unlike the previous subtraction based approach which only worked for addresses in kseg0. Working for kseg1 addresses is important if __pa is used on addresses allocated by dma_alloc_coherent, where on systems with non-coherent I/O we provide addresses in kseg1. If this address is then used with dma_map_single_attrs then it is provided to virt_to_page, which in turn calls virt_to_phys which is a wrapper around __pa. The result is that we end up with a physical address 0x20000000 bytes (ie. the size of kseg0) too high. In addition to providing consistency with MIPS64 & fixing the kseg1 case above this has the added bonus of generating smaller code for systems implementing MIPS32r2 & beyond, where a single ext instruction can extract the physical address rather than needing to load an immediate into a temp register & subtract it. This results in ~1.3KB savings for a boston_defconfig kernel adjusted to set CONFIG_32BIT=y. This patch does not change the EVA case, which may or may not have similar issues around handling both cached & uncached addresses but is beyond the scope of this patch. Signed-off-by: Paul Burton <paul.burton@imgtec.com> Cc: Dan Williams <dan.j.williams@intel.com> Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13836/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
1 parent 5c315e3 commit 0d8d83d

File tree

1 file changed

+28
-10
lines changed

1 file changed

+28
-10
lines changed

arch/mips/include/asm/page.h

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -162,16 +162,34 @@ typedef struct { unsigned long pgprot; } pgprot_t;
162162
/*
163163
* __pa()/__va() should be used only during mem init.
164164
*/
165-
#ifdef CONFIG_64BIT
166-
#define __pa(x) \
167-
({ \
168-
unsigned long __x = (unsigned long)(x); \
169-
__x < CKSEG0 ? XPHYSADDR(__x) : CPHYSADDR(__x); \
170-
})
171-
#else
172-
#define __pa(x) \
173-
((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
174-
#endif
165+
static inline unsigned long ___pa(unsigned long x)
166+
{
167+
if (config_enabled(CONFIG_64BIT)) {
168+
/*
169+
* For MIPS64 the virtual address may either be in one of
170+
* the compatibility segements ckseg0 or ckseg1, or it may
171+
* be in xkphys.
172+
*/
173+
return x < CKSEG0 ? XPHYSADDR(x) : CPHYSADDR(x);
174+
}
175+
176+
if (!config_enabled(CONFIG_EVA)) {
177+
/*
178+
* We're using the standard MIPS32 legacy memory map, ie.
179+
* the address x is going to be in kseg0 or kseg1. We can
180+
* handle either case by masking out the desired bits using
181+
* CPHYSADDR.
182+
*/
183+
return CPHYSADDR(x);
184+
}
185+
186+
/*
187+
* EVA is in use so the memory map could be anything, making it not
188+
* safe to just mask out bits.
189+
*/
190+
return x - PAGE_OFFSET + PHYS_OFFSET;
191+
}
192+
#define __pa(x) ___pa((unsigned long)(x))
175193
#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
176194
#include <asm/io.h>
177195

0 commit comments

Comments
 (0)