Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 509553a5 authored by Laura Abbott's avatar Laura Abbott Committed by Patrick Daly
Browse files

arm64: Support early fixup for CMA



Although it isn't architecturally required, CMA regions may need
to have attributes changed at runtime. Remap the CMA regions as
pages to allow this to happen.

Change-Id: I7dd7fa150ce69fdf05f8bf6f76a5ae26dd67ff1b
Signed-off-by: default avatarLaura Abbott <lauraa@codeaurora.org>
Signed-off-by: default avatarPatrick Daly <pdaly@codeaurora.org>
parent 7a6c5fd7
Loading
Loading
Loading
Loading
+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
+40 −2
Original line number Diff line number Diff line
@@ -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>
@@ -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)
{
@@ -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);
			/*
@@ -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);