diff options
author | David Daney <ddaney@caviumnetworks.com> | 2010-08-04 14:53:57 -0700 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2010-08-05 13:26:31 +0100 |
commit | 2b5987abaf2dd6c3934e0376b7d9f64411cdcf03 (patch) | |
tree | 1d3609613faed623728eed98a83565f781201420 /arch/mips/cavium-octeon/setup.c | |
parent | 70dc6f045fce6907b5d10377850a78ada6837ffb (diff) | |
download | blackbird-op-linux-2b5987abaf2dd6c3934e0376b7d9f64411cdcf03.tar.gz blackbird-op-linux-2b5987abaf2dd6c3934e0376b7d9f64411cdcf03.zip |
MIPS: Octeon: Allow more than 3.75GB of memory with PCIe
We reserve the 3.75GB - 4GB region of PCIe address space for device to
device transfers, making the corresponding physical memory under
direct mapping unavailable for DMA.
To allow for PCIe DMA to all physical memory we map this chunk of
physical memory with BAR1. Because of the resulting discontinuity in
the mapping function, we remove a page of memory at each end of the
range so multi-page DMA buffers can never be allocated that span the
range.
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
To: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/1535/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/cavium-octeon/setup.c')
-rw-r--r-- | arch/mips/cavium-octeon/setup.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 041326e34f4d..69197cb6c7ea 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -32,6 +32,7 @@ #include <asm/time.h> #include <asm/octeon/octeon.h> +#include <asm/octeon/pci-octeon.h> #ifdef CONFIG_CAVIUM_DECODE_RSL extern void cvmx_interrupt_rsl_decode(void); @@ -609,6 +610,22 @@ void __init prom_init(void) register_smp_ops(&octeon_smp_ops); } +/* Exclude a single page from the regions obtained in plat_mem_setup. */ +static __init void memory_exclude_page(u64 addr, u64 *mem, u64 *size) +{ + if (addr > *mem && addr < *mem + *size) { + u64 inc = addr - *mem; + add_memory_region(*mem, inc, BOOT_MEM_RAM); + *mem += inc; + *size -= inc; + } + + if (addr == *mem && *size > PAGE_SIZE) { + *mem += PAGE_SIZE; + *size -= PAGE_SIZE; + } +} + void __init plat_mem_setup(void) { uint64_t mem_alloc_size; @@ -659,12 +676,27 @@ void __init plat_mem_setup(void) CVMX_BOOTMEM_FLAG_NO_LOCKING); #endif if (memory >= 0) { + u64 size = mem_alloc_size; + + /* + * exclude a page at the beginning and end of + * the 256MB PCIe 'hole' so the kernel will not + * try to allocate multi-page buffers that + * span the discontinuity. + */ + memory_exclude_page(CVMX_PCIE_BAR1_PHYS_BASE, + &memory, &size); + memory_exclude_page(CVMX_PCIE_BAR1_PHYS_BASE + + CVMX_PCIE_BAR1_PHYS_SIZE, + &memory, &size); + /* * This function automatically merges address * regions next to each other if they are * received in incrementing order. */ - add_memory_region(memory, mem_alloc_size, BOOT_MEM_RAM); + if (size) + add_memory_region(memory, size, BOOT_MEM_RAM); total += mem_alloc_size; } else { break; |