Loading arch/arm64/include/asm/dma-contiguous.h 0 → 100644 +27 −0 Original line number Diff line number Diff line /* * Copyright (c) 2013,2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef _ASM_DMA_CONTIGUOUS_H #define _ASM_DMA_CONTIGUOUS_H #ifdef __KERNEL__ #ifdef CONFIG_DMA_CMA #include <linux/types.h> void dma_contiguous_early_fixup(phys_addr_t base, unsigned long size); #endif #endif #endif arch/arm64/mm/mmu.c +40 −2 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ #include <linux/io.h> #include <linux/slab.h> #include <linux/stop_machine.h> #include <linux/dma-contiguous.h> #include <linux/cma.h> #include <asm/barrier.h> #include <asm/cputype.h> Loading Loading @@ -59,6 +61,40 @@ static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss; static pmd_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss __maybe_unused; static pud_t bm_pud[PTRS_PER_PUD] __page_aligned_bss __maybe_unused; struct dma_contig_early_reserve { phys_addr_t base; unsigned long size; }; static struct dma_contig_early_reserve dma_mmu_remap[MAX_CMA_AREAS]; static int dma_mmu_remap_num; void __init dma_contiguous_early_fixup(phys_addr_t base, unsigned long size) { if (dma_mmu_remap_num >= ARRAY_SIZE(dma_mmu_remap)) { pr_err("ARM64: Not enough slots for DMA fixup reserved regions!\n"); return; } dma_mmu_remap[dma_mmu_remap_num].base = base; dma_mmu_remap[dma_mmu_remap_num].size = size; dma_mmu_remap_num++; } static bool dma_overlap(phys_addr_t start, phys_addr_t end) { int i; for (i = 0; i < dma_mmu_remap_num; i++) { phys_addr_t dma_base = dma_mmu_remap[i].base; phys_addr_t dma_end = dma_mmu_remap[i].base + dma_mmu_remap[i].size; if ((dma_base < end) && (dma_end > start)) return true; } return false; } pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, unsigned long size, pgprot_t vma_prot) { Loading Loading @@ -149,7 +185,8 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end, next = pmd_addr_end(addr, end); /* try section mapping first */ if (((addr | next | phys) & ~SECTION_MASK) == 0 && allow_block_mappings) { allow_block_mappings && !dma_overlap(phys, phys + next - addr)) { pmd_t old_pmd =*pmd; pmd_set_huge(pmd, phys, prot); /* Loading Loading @@ -209,7 +246,8 @@ static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end, /* * For 4K granule only, attempt to put down a 1GB block */ if (use_1G_block(addr, next, phys) && allow_block_mappings) { if (use_1G_block(addr, next, phys) && allow_block_mappings && !dma_overlap(phys, phys + next - addr)) { pud_t old_pud = *pud; pud_set_huge(pud, phys, prot); Loading Loading
arch/arm64/include/asm/dma-contiguous.h 0 → 100644 +27 −0 Original line number Diff line number Diff line /* * Copyright (c) 2013,2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef _ASM_DMA_CONTIGUOUS_H #define _ASM_DMA_CONTIGUOUS_H #ifdef __KERNEL__ #ifdef CONFIG_DMA_CMA #include <linux/types.h> void dma_contiguous_early_fixup(phys_addr_t base, unsigned long size); #endif #endif #endif
arch/arm64/mm/mmu.c +40 −2 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ #include <linux/io.h> #include <linux/slab.h> #include <linux/stop_machine.h> #include <linux/dma-contiguous.h> #include <linux/cma.h> #include <asm/barrier.h> #include <asm/cputype.h> Loading Loading @@ -59,6 +61,40 @@ static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss; static pmd_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss __maybe_unused; static pud_t bm_pud[PTRS_PER_PUD] __page_aligned_bss __maybe_unused; struct dma_contig_early_reserve { phys_addr_t base; unsigned long size; }; static struct dma_contig_early_reserve dma_mmu_remap[MAX_CMA_AREAS]; static int dma_mmu_remap_num; void __init dma_contiguous_early_fixup(phys_addr_t base, unsigned long size) { if (dma_mmu_remap_num >= ARRAY_SIZE(dma_mmu_remap)) { pr_err("ARM64: Not enough slots for DMA fixup reserved regions!\n"); return; } dma_mmu_remap[dma_mmu_remap_num].base = base; dma_mmu_remap[dma_mmu_remap_num].size = size; dma_mmu_remap_num++; } static bool dma_overlap(phys_addr_t start, phys_addr_t end) { int i; for (i = 0; i < dma_mmu_remap_num; i++) { phys_addr_t dma_base = dma_mmu_remap[i].base; phys_addr_t dma_end = dma_mmu_remap[i].base + dma_mmu_remap[i].size; if ((dma_base < end) && (dma_end > start)) return true; } return false; } pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, unsigned long size, pgprot_t vma_prot) { Loading Loading @@ -149,7 +185,8 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end, next = pmd_addr_end(addr, end); /* try section mapping first */ if (((addr | next | phys) & ~SECTION_MASK) == 0 && allow_block_mappings) { allow_block_mappings && !dma_overlap(phys, phys + next - addr)) { pmd_t old_pmd =*pmd; pmd_set_huge(pmd, phys, prot); /* Loading Loading @@ -209,7 +246,8 @@ static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end, /* * For 4K granule only, attempt to put down a 1GB block */ if (use_1G_block(addr, next, phys) && allow_block_mappings) { if (use_1G_block(addr, next, phys) && allow_block_mappings && !dma_overlap(phys, phys + next - addr)) { pud_t old_pud = *pud; pud_set_huge(pud, phys, prot); Loading