aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/cavium-octeon
diff options
context:
space:
mode:
authorDavid Daney <ddaney@caviumnetworks.com>2010-08-04 17:53:57 -0400
committerRalf Baechle <ralf@linux-mips.org>2010-08-05 08:26:31 -0400
commit2b5987abaf2dd6c3934e0376b7d9f64411cdcf03 (patch)
tree1d3609613faed623728eed98a83565f781201420 /arch/mips/cavium-octeon
parent70dc6f045fce6907b5d10377850a78ada6837ffb (diff)
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')
-rw-r--r--arch/mips/cavium-octeon/dma-octeon.c17
-rw-r--r--arch/mips/cavium-octeon/setup.c34
2 files changed, 43 insertions, 8 deletions
diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c
index be531ec1f206..d22b5a2d64f4 100644
--- a/arch/mips/cavium-octeon/dma-octeon.c
+++ b/arch/mips/cavium-octeon/dma-octeon.c
@@ -99,13 +99,16 @@ dma_addr_t octeon_map_dma_mem(struct device *dev, void *ptr, size_t size)
99 panic("dma_map_single: " 99 panic("dma_map_single: "
100 "Attempt to map illegal memory address 0x%llx\n", 100 "Attempt to map illegal memory address 0x%llx\n",
101 physical); 101 physical);
102 else if ((physical + size >= 102 else if (physical >= CVMX_PCIE_BAR1_PHYS_BASE &&
103 (4ull<<30) - (OCTEON_PCI_BAR1_HOLE_SIZE<<20)) 103 physical + size < (CVMX_PCIE_BAR1_PHYS_BASE + CVMX_PCIE_BAR1_PHYS_SIZE)) {
104 && physical < (4ull<<30)) 104 result = physical - CVMX_PCIE_BAR1_PHYS_BASE + CVMX_PCIE_BAR1_RC_BASE;
105 pr_warning("dma_map_single: Warning: " 105
106 "Mapping memory address that might " 106 if (((result+size-1) & dma_mask) != result+size-1)
107 "conflict with devices 0x%llx-0x%llx\n", 107 panic("dma_map_single: Attempt to map address 0x%llx-0x%llx, which can't be accessed according to the dma mask 0x%llx\n",
108 physical, physical+size-1); 108 physical, physical+size-1, dma_mask);
109 goto done;
110 }
111
109 /* The 2nd 256MB is mapped at 256<<20 instead of 0x410000000 */ 112 /* The 2nd 256MB is mapped at 256<<20 instead of 0x410000000 */
110 if ((physical >= 0x410000000ull) && physical < 0x420000000ull) 113 if ((physical >= 0x410000000ull) && physical < 0x420000000ull)
111 result = physical - 0x400000000ull; 114 result = physical - 0x400000000ull;
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 @@
32#include <asm/time.h> 32#include <asm/time.h>
33 33
34#include <asm/octeon/octeon.h> 34#include <asm/octeon/octeon.h>
35#include <asm/octeon/pci-octeon.h>
35 36
36#ifdef CONFIG_CAVIUM_DECODE_RSL 37#ifdef CONFIG_CAVIUM_DECODE_RSL
37extern void cvmx_interrupt_rsl_decode(void); 38extern void cvmx_interrupt_rsl_decode(void);
@@ -609,6 +610,22 @@ void __init prom_init(void)
609 register_smp_ops(&octeon_smp_ops); 610 register_smp_ops(&octeon_smp_ops);
610} 611}
611 612
613/* Exclude a single page from the regions obtained in plat_mem_setup. */
614static __init void memory_exclude_page(u64 addr, u64 *mem, u64 *size)
615{
616 if (addr > *mem && addr < *mem + *size) {
617 u64 inc = addr - *mem;
618 add_memory_region(*mem, inc, BOOT_MEM_RAM);
619 *mem += inc;
620 *size -= inc;
621 }
622
623 if (addr == *mem && *size > PAGE_SIZE) {
624 *mem += PAGE_SIZE;
625 *size -= PAGE_SIZE;
626 }
627}
628
612void __init plat_mem_setup(void) 629void __init plat_mem_setup(void)
613{ 630{
614 uint64_t mem_alloc_size; 631 uint64_t mem_alloc_size;
@@ -659,12 +676,27 @@ void __init plat_mem_setup(void)
659 CVMX_BOOTMEM_FLAG_NO_LOCKING); 676 CVMX_BOOTMEM_FLAG_NO_LOCKING);
660#endif 677#endif
661 if (memory >= 0) { 678 if (memory >= 0) {
679 u64 size = mem_alloc_size;
680
681 /*
682 * exclude a page at the beginning and end of
683 * the 256MB PCIe 'hole' so the kernel will not
684 * try to allocate multi-page buffers that
685 * span the discontinuity.
686 */
687 memory_exclude_page(CVMX_PCIE_BAR1_PHYS_BASE,
688 &memory, &size);
689 memory_exclude_page(CVMX_PCIE_BAR1_PHYS_BASE +
690 CVMX_PCIE_BAR1_PHYS_SIZE,
691 &memory, &size);
692
662 /* 693 /*
663 * This function automatically merges address 694 * This function automatically merges address
664 * regions next to each other if they are 695 * regions next to each other if they are
665 * received in incrementing order. 696 * received in incrementing order.
666 */ 697 */
667 add_memory_region(memory, mem_alloc_size, BOOT_MEM_RAM); 698 if (size)
699 add_memory_region(memory, size, BOOT_MEM_RAM);
668 total += mem_alloc_size; 700 total += mem_alloc_size;
669 } else { 701 } else {
670 break; 702 break;