// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2018-2020 Christoph Hellwig.
 *
 * DMA operations that map physical memory directly without using an IOMMU.
 */
#include <linux/memblock.h> /* for max_pfn */
#include <linux/export.h>
#include <linux/mm.h>
#include <linux/dma-map-ops.h>
#include <linux/scatterlist.h>
#include <linux/pfn.h>
#include <linux/vmalloc.h>
#include <linux/set_memory.h>
#include <linux/slab.h>
#include <linux/pci-p2pdma.h>
#include <linux/cc_platform.h>

#include "direct.h"

/*
 * Most architectures use ZONE_DMA for the first 16 Megabytes, but some use
 * it for entirely different regions. In that case the arch code needs to
 * override the variable below for dma-direct to work properly.
 */
u64 zone_dma_limit __ro_after_init = DMA_BIT_MASK(24);

static inline dma_addr_t phys_to_dma_direct(struct device *dev,
		phys_addr_t phys, bool unencrypted)
{
	if (unencrypted)
		return phys_to_dma_unencrypted(dev, phys);
	return phys_to_dma_encrypted(dev, phys);
}

static inline struct page *dma_direct_to_page(struct device *dev,
		dma_addr_t dma_addr)
{
	return pfn_to_page(PHYS_PFN(dma_to_phys(dev, dma_addr)));
}

u64 dma_direct_get_required_mask(struct device *dev)
{
	bool require_decrypted = force_dma_unencrypted(dev);
	phys_addr_t phys = ((phys_addr_t)max_pfn << PAGE_SHIFT) - 1;
	u64 max_dma = phys_to_dma_direct(dev, phys, require_decrypted);

	return (1ULL << (fls64(max_dma) - 1)) * 2 - 1;
}

static gfp_t dma_direct_optimal_gfp_mask(struct device *dev, u64 *phys_limit)
{
	u64 dma_limit = min_not_zero(
		dev->coherent_dma_mask,
		dev->bus_dma_limit);

	/*
	 * Optimistically try the zone that the physical address mask falls
	 * into first.  If that returns memory that isn't actually addressable
	 * we will fallback to the next lower zone and try again.
	 *
	 * Note that GFP_DMA32 and GFP_DMA are no ops without the corresponding
	 * zones.
	 */
	*phys_limit = dma_to_phys(dev, dma_limit);
	if (*phys_limit <= zone_dma_limit)
		return GFP_DMA;
	if (*phys_limit <= DMA_BIT_MASK(32))
		return GFP_DMA32;
	return 0;
}

bool dma_coherent_ok(struct device *dev, phys_addr_t phys, size_t size)
{
	bool require_decrypted = force_dma_unencrypted(dev);
	dma_addr_t dma_addr = phys_to_dma_direct(dev, phys, require_decrypted);

	if (dma_addr == DMA_MAPPING_ERROR)
		return false;
	return dma_addr + size - 1 <=
		min_not_zero(dev->coherent_dma_mask, dev->bus_dma_limit);
}

static int dma_set_decrypted(struct device *dev, void *vaddr, size_t size)
{
	int ret;

	ret = set_memory_decrypted((unsigned long)vaddr, PFN_UP(size));
	if (ret)
		pr_warn_ratelimited("leaking DMA memory that can't be decrypted\n");
	return ret;
}

static int dma_set_encrypted(struct device *dev, void *vaddr, size_t size)
{
	int ret;

	ret = set_memory_encrypted((unsigned long)vaddr, PFN_UP(size));
	if (ret)
		pr_warn_ratelimited("leaking DMA memory that can't be re-encrypted\n");
	return ret;
}

static struct page *dma_direct_alloc_swiotlb(struct device *dev, size_t size,
		unsigned long attrs)
{
	struct page *page = swiotlb_alloc(dev, size, attrs);

	if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
		swiotlb_free(dev, page, size);
		return NULL;
	}

	return page;
}

static struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
		gfp_t gfp, bool allow_highmem)
{
	int node = dev_to_node(dev);
	struct page *page;
	u64 phys_limit;

	WARN_ON_ONCE(!PAGE_ALIGNED(size));

	gfp |= dma_direct_optimal_gfp_mask(dev, &phys_limit);
	page = dma_alloc_contiguous(dev, size, gfp);
	if (page) {
		if (dma_coherent_ok(dev, page_to_phys(page), size) &&
		    (allow_highmem || !PageHighMem(page)))
			return page;

		dma_free_contiguous(dev, page, size);
	}

	while ((page = alloc_pages_node(node, gfp, get_order(size)))
	       && !dma_coherent_ok(dev, page_to_phys(page), size)) {
		__free_pages(page, get_order(size));

		if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
		    phys_limit < DMA_BIT_MASK(64) &&
		    !(gfp & (GFP_DMA32 | GFP_DMA)))
			gfp |= GFP_DMA32;
		else if (IS_ENABLED(CONFIG_ZONE_DMA) && !(gfp & GFP_DMA))
			gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
		else
			return NULL;
	}

	return page;
}

/*
 * Check if a potentially blocking operations needs to dip into the atomic
 * pools for the given device/gfp.
 */
static bool dma_direct_use_pool(struct device *dev, gfp_t gfp)
{
	return !gfpflags_allow_blocking(gfp) && !is_swiotlb_for_alloc(dev);
}

static struct page *dma_direct_alloc_from_pool(struct device *dev, size_t size,
		dma_addr_t *dma_handle, void **cpu_addr, gfp_t gfp,
		unsigned long attrs)
{
	struct page *page;
	u64 phys_limit;

	if (WARN_ON_ONCE(!IS_ENABLED(CONFIG_DMA_COHERENT_POOL)))
		return NULL;

	gfp |= dma_direct_optimal_gfp_mask(dev, &phys_limit);
	page = dma_alloc_from_pool(dev, size, cpu_addr, gfp, attrs,
				   dma_coherent_ok);
	if (!page)
		return NULL;
	*dma_handle = phys_to_dma_direct(dev, page_to_phys(page),
					 attrs & __DMA_ATTR_ALLOC_CC_SHARED);
	return page;
}

static void *dma_direct_alloc_no_mapping(struct device *dev, size_t size,
		dma_addr_t *dma_handle, gfp_t gfp)
{
	struct page *page;

	page = __dma_direct_alloc_pages(dev, size, gfp & ~__GFP_ZERO, true);
	if (!page)
		return NULL;

	/* remove any dirty cache lines on the kernel alias */
	if (!PageHighMem(page))
		arch_dma_prep_coherent(page, size);
	/*
	 * return the page pointer as the opaque cookie.
	 * Never used for unencrypted allocation
	 */
	*dma_handle = phys_to_dma_encrypted(dev, page_to_phys(page));
	return page;
}

void *dma_direct_alloc(struct device *dev, size_t size,
		dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
{
	bool remap = false, set_uncached = false;
	bool mark_mem_decrypt = false;
	bool allow_highmem = true;
	struct page *page;
	void *cpu_addr;

	if (force_dma_unencrypted(dev))
		attrs |= __DMA_ATTR_ALLOC_CC_SHARED;

	if (attrs & __DMA_ATTR_ALLOC_CC_SHARED) {
		/*
		 * Unencrypted/shared DMA requires a linear-mapped buffer
		 * address to look up the PFN and set architecture-required PFN
		 * attributes. This is not possible with HighMem. Avoid HighMem
		 * allocation.
		 */
		allow_highmem = false;
		mark_mem_decrypt = true;
	}

	size = PAGE_ALIGN(size);
	if (attrs & DMA_ATTR_NO_WARN)
		gfp |= __GFP_NOWARN;

	if (((attrs & (DMA_ATTR_NO_KERNEL_MAPPING | __DMA_ATTR_ALLOC_CC_SHARED)) ==
	     DMA_ATTR_NO_KERNEL_MAPPING) && !is_swiotlb_for_alloc(dev))
		return dma_direct_alloc_no_mapping(dev, size, dma_handle, gfp);

	if (!dev_is_dma_coherent(dev)) {
		if (IS_ENABLED(CONFIG_ARCH_HAS_DMA_ALLOC) &&
		    !is_swiotlb_for_alloc(dev))
			return arch_dma_alloc(dev, size, dma_handle, gfp,
					      attrs);

		/*
		 * If there is a global pool, always allocate from it for
		 * non-coherent devices.
		 */
		if (IS_ENABLED(CONFIG_DMA_GLOBAL_POOL))
			return dma_alloc_from_global_coherent(dev, size,
					dma_handle);

		/*
		 * Otherwise we require the architecture to either be able to
		 * mark arbitrary parts of the kernel direct mapping uncached,
		 * or remapped it uncached.
		 */
		set_uncached = IS_ENABLED(CONFIG_ARCH_HAS_DMA_SET_UNCACHED);
		remap = IS_ENABLED(CONFIG_DMA_DIRECT_REMAP);
		if (!set_uncached && !remap) {
			pr_warn_once("coherent DMA allocations not supported on this platform.\n");
			return NULL;
		}
	}

	/*
	 * Remapping or decrypting memory may block, allocate the memory from
	 * the atomic pools instead if we aren't allowed block.
	 * FIXME: With CONFIG_DMA_DIRECT_REMAP, the pool is also mapped as
	 * DMA-coherent (non-cacheable). We may want to create a separate pool
	 * dedicated to CC_SHARED atomic allocations.
	 */
	if ((remap || (attrs & __DMA_ATTR_ALLOC_CC_SHARED)) &&
	    dma_direct_use_pool(dev, gfp)) {
		page = dma_direct_alloc_from_pool(dev, size,
					dma_handle, &cpu_addr,
					gfp, attrs);
		return page ? cpu_addr : NULL;
	}

	if (is_swiotlb_for_alloc(dev)) {
		page = dma_direct_alloc_swiotlb(dev, size, attrs);
		if (page) {
			/*
			 * swiotlb allocations comes from pool already marked
			 * decrypted
			 */
			mark_mem_decrypt = false;
			goto setup_page;
		}
		return NULL;
	}

	/* we always manually zero the memory once we are done */
	page = __dma_direct_alloc_pages(dev, size, gfp & ~__GFP_ZERO, allow_highmem);
	if (!page)
		return NULL;

setup_page:
	/*
	 * dma_alloc_contiguous can return highmem pages depending on a
	 * combination the cma= arguments and per-arch setup.  These need to be
	 * remapped to return a kernel virtual address.
	 */
	if (PageHighMem(page)) {
		remap = true;
		set_uncached = false;
	}

	if (mark_mem_decrypt) {
		void *lm_addr;

		lm_addr = page_address(page);
		if (set_memory_decrypted((unsigned long)lm_addr, PFN_UP(size)))
			goto out_leak_pages;
	}

	if (remap) {
		pgprot_t prot = dma_pgprot(dev, PAGE_KERNEL, attrs);

		/* remove any dirty cache lines on the kernel alias */
		arch_dma_prep_coherent(page, size);

		/* create a coherent mapping */
		cpu_addr = dma_common_contiguous_remap(page, size, prot,
					__builtin_return_address(0));
		if (!cpu_addr)
			goto out_encrypt_pages;
	} else {
		cpu_addr = page_address(page);
	}

	memset(cpu_addr, 0, size);

	if (set_uncached) {
		void *uncached_cpu_addr;

		arch_dma_prep_coherent(page, size);
		uncached_cpu_addr = arch_dma_set_uncached(cpu_addr, size);
		if (IS_ERR(uncached_cpu_addr))
			goto out_free_remap_pages;
		cpu_addr = uncached_cpu_addr;
	}

	*dma_handle = phys_to_dma_direct(dev, page_to_phys(page),
					 attrs & __DMA_ATTR_ALLOC_CC_SHARED);
	return cpu_addr;

out_free_remap_pages:
	if (remap)
		dma_common_free_remap(cpu_addr, size);

out_encrypt_pages:
	if (mark_mem_decrypt &&
	    dma_set_encrypted(dev, page_address(page), size))
		goto out_leak_pages;

	if (!swiotlb_free(dev, page, size))
		dma_free_contiguous(dev, page, size);
	return NULL;
out_leak_pages:
	return NULL;
}

void dma_direct_free(struct device *dev, size_t size,
		void *cpu_addr, dma_addr_t dma_addr, unsigned long attrs)
{
	phys_addr_t phys;
	bool mark_mem_encrypted = false;
	struct io_tlb_pool *swiotlb_pool;
	unsigned int page_order = get_order(size);

	/*
	 * If the allocation used decrypted/shared backing pages, restore
	 * the encryption state on free.
	 */
	if (force_dma_unencrypted(dev))
		attrs |= __DMA_ATTR_ALLOC_CC_SHARED;

	if (attrs & __DMA_ATTR_ALLOC_CC_SHARED)
		mark_mem_encrypted = true;

	if (((attrs & (DMA_ATTR_NO_KERNEL_MAPPING | __DMA_ATTR_ALLOC_CC_SHARED)) ==
	     DMA_ATTR_NO_KERNEL_MAPPING) && !is_swiotlb_for_alloc(dev)) {
		/* cpu_addr is a struct page cookie, not a kernel address */
		dma_free_contiguous(dev, cpu_addr, size);
		return;
	}

	if (IS_ENABLED(CONFIG_ARCH_HAS_DMA_ALLOC) &&
	    !dev_is_dma_coherent(dev) &&
	    !is_swiotlb_for_alloc(dev)) {
		arch_dma_free(dev, size, cpu_addr, dma_addr, attrs);
		return;
	}

	if (IS_ENABLED(CONFIG_DMA_GLOBAL_POOL) &&
	    !dev_is_dma_coherent(dev)) {
		if (!dma_release_from_global_coherent(page_order, cpu_addr))
			WARN_ON_ONCE(1);
		return;
	}

	/* If cpu_addr is not from an atomic pool, dma_free_from_pool() fails */
	if (IS_ENABLED(CONFIG_DMA_COHERENT_POOL) &&
	    dma_free_from_pool(dev, cpu_addr, PAGE_ALIGN(size)))
		return;

	phys = dma_to_phys(dev, dma_addr);
	swiotlb_pool = swiotlb_find_pool(dev, phys);
	if (swiotlb_pool)
		/* Swiotlb doesn't need a page attribute update on free */
		mark_mem_encrypted = false;

	if (is_vmalloc_addr(cpu_addr)) {
		vunmap(cpu_addr);
	} else {
		if (IS_ENABLED(CONFIG_ARCH_HAS_DMA_CLEAR_UNCACHED))
			arch_dma_clear_uncached(cpu_addr, size);
	}

	if (mark_mem_encrypted) {
		void *lm_addr;

		lm_addr = phys_to_virt(phys);
		if (set_memory_encrypted((unsigned long)lm_addr, PFN_UP(size))) {
			pr_warn_ratelimited("leaking DMA memory that can't be re-encrypted\n");
			return;
		}
	}

	if (swiotlb_pool)
		swiotlb_free_from_pool(dev, phys, swiotlb_pool);
	else
		dma_free_contiguous(dev, dma_direct_to_page(dev, dma_addr), size);
}

struct page *dma_direct_alloc_pages(struct device *dev, size_t size,
		dma_addr_t *dma_handle, enum dma_data_direction dir, gfp_t gfp)
{
	unsigned long attrs = 0;
	struct page *page;
	void *cpu_addr;

	if (force_dma_unencrypted(dev))
		attrs |= __DMA_ATTR_ALLOC_CC_SHARED;

	if ((attrs & __DMA_ATTR_ALLOC_CC_SHARED) && dma_direct_use_pool(dev, gfp))
		return dma_direct_alloc_from_pool(dev, size, dma_handle,
						  &cpu_addr, gfp, attrs);

	if (is_swiotlb_for_alloc(dev)) {
		page = dma_direct_alloc_swiotlb(dev, size, attrs);
		if (!page)
			return NULL;

		cpu_addr = page_address(page);
		goto setup_page;
	}

	page = __dma_direct_alloc_pages(dev, size, gfp, false);
	if (!page)
		return NULL;

	cpu_addr = page_address(page);
	if ((attrs & __DMA_ATTR_ALLOC_CC_SHARED) &&
	    dma_set_decrypted(dev, cpu_addr, size))
		goto out_leak_pages;
setup_page:
	memset(cpu_addr, 0, size);
	*dma_handle = phys_to_dma_direct(dev, page_to_phys(page),
					 attrs & __DMA_ATTR_ALLOC_CC_SHARED);
	return page;
out_leak_pages:
	return NULL;
}

void dma_direct_free_pages(struct device *dev, size_t size,
		struct page *page, dma_addr_t dma_addr,
		enum dma_data_direction dir)
{
	phys_addr_t phys;
	void *vaddr = page_address(page);
	struct io_tlb_pool *swiotlb_pool;
	/*
	 * if the device had requested for an unencrypted buffer,
	 * convert it to encrypted on free
	 */
	bool mark_mem_encrypted = force_dma_unencrypted(dev);

	/* If page is not from an atomic pool, dma_free_from_pool_page() fails */
	if (IS_ENABLED(CONFIG_DMA_COHERENT_POOL) &&
	    dma_free_from_pool_page(dev, page, size))
		return;

	phys = page_to_phys(page);
	swiotlb_pool = swiotlb_find_pool(dev, phys);
	if (swiotlb_pool)
		mark_mem_encrypted = false;

	if (mark_mem_encrypted && dma_set_encrypted(dev, vaddr, size))
		return;

	if (swiotlb_pool)
		swiotlb_free_from_pool(dev, phys, swiotlb_pool);
	else
		dma_free_contiguous(dev, page, size);
}

#if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \
    defined(CONFIG_SWIOTLB)
void dma_direct_sync_sg_for_device(struct device *dev,
		struct scatterlist *sgl, int nents, enum dma_data_direction dir)
{
	struct scatterlist *sg;
	int i;

	for_each_sg(sgl, sg, nents, i) {
		phys_addr_t paddr = dma_to_phys(dev, sg_dma_address(sg));

		swiotlb_sync_single_for_device(dev, paddr, sg->length, dir);

		if (!dev_is_dma_coherent(dev))
			arch_sync_dma_for_device(paddr, sg->length,
					dir);
	}
	if (!dev_is_dma_coherent(dev))
		arch_sync_dma_flush();
}
#endif

#if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) || \
    defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL) || \
    defined(CONFIG_SWIOTLB)
void dma_direct_sync_sg_for_cpu(struct device *dev,
		struct scatterlist *sgl, int nents, enum dma_data_direction dir)
{
	struct scatterlist *sg;
	int i;

	for_each_sg(sgl, sg, nents, i) {
		phys_addr_t paddr = dma_to_phys(dev, sg_dma_address(sg));

		if (!dev_is_dma_coherent(dev))
			arch_sync_dma_for_cpu(paddr, sg->length, dir);

		swiotlb_sync_single_for_cpu(dev, paddr, sg->length, dir);
	}

	if (!dev_is_dma_coherent(dev)) {
		arch_sync_dma_flush();
		arch_sync_dma_for_cpu_all();
	}
}

/*
 * Unmaps segments, except for ones marked as pci_p2pdma which do not
 * require any further action as they contain a bus address.
 */
void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sgl,
		int nents, enum dma_data_direction dir, unsigned long attrs)
{
	struct scatterlist *sg;
	int i;
	bool need_sync = false;

	for_each_sg(sgl,  sg, nents, i) {
		if (sg_dma_is_bus_address(sg)) {
			sg_dma_unmark_bus_address(sg);
		} else {
			need_sync = true;
			dma_direct_unmap_phys(dev, sg->dma_address,
					      sg_dma_len(sg), dir, attrs, false);
		}
	}
	if (need_sync && !dev_is_dma_coherent(dev))
		arch_sync_dma_flush();
}
#endif

int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
		enum dma_data_direction dir, unsigned long attrs)
{
	struct pci_p2pdma_map_state p2pdma_state = {};
	struct scatterlist *sg;
	int i, ret;
	bool need_sync = false;

	for_each_sg(sgl, sg, nents, i) {
		switch (pci_p2pdma_state(&p2pdma_state, dev, sg_page(sg))) {
		case PCI_P2PDMA_MAP_THRU_HOST_BRIDGE:
			/*
			 * Any P2P mapping that traverses the PCI host bridge
			 * must be mapped with CPU physical address and not PCI
			 * bus addresses.
			 */
			fallthrough;
		case PCI_P2PDMA_MAP_NONE:
			need_sync = true;
			sg->dma_address = dma_direct_map_phys(dev, sg_phys(sg),
					sg->length, dir, attrs, false);
			if (sg->dma_address == DMA_MAPPING_ERROR) {
				ret = -EIO;
				goto out_unmap;
			}
			break;
		case PCI_P2PDMA_MAP_BUS_ADDR:
			sg->dma_address = pci_p2pdma_bus_addr_map(
				p2pdma_state.mem, sg_phys(sg));
			sg_dma_mark_bus_address(sg);
			break;
		default:
			ret = -EREMOTEIO;
			goto out_unmap;
		}
		sg_dma_len(sg) = sg->length;
	}

	if (need_sync && !dev_is_dma_coherent(dev))
		arch_sync_dma_flush();
	return nents;

out_unmap:
	dma_direct_unmap_sg(dev, sgl, i, dir, attrs | DMA_ATTR_SKIP_CPU_SYNC);
	return ret;
}

int dma_direct_get_sgtable(struct device *dev, struct sg_table *sgt,
		void *cpu_addr, dma_addr_t dma_addr, size_t size,
		unsigned long attrs)
{
	struct page *page = dma_direct_to_page(dev, dma_addr);
	int ret;

	ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
	if (!ret)
		sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0);
	return ret;
}

bool dma_direct_can_mmap(struct device *dev)
{
	return dev_is_dma_coherent(dev) ||
		IS_ENABLED(CONFIG_DMA_NONCOHERENT_MMAP);
}

int dma_direct_mmap(struct device *dev, struct vm_area_struct *vma,
		void *cpu_addr, dma_addr_t dma_addr, size_t size,
		unsigned long attrs)
{
	unsigned long user_count = vma_pages(vma);
	unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
	unsigned long pfn = PHYS_PFN(dma_to_phys(dev, dma_addr));
	const pgoff_t pgoff_start = vma_start_pgoff(vma);
	const pgoff_t pgoff_end = vma_end_pgoff(vma);
	int ret = -ENXIO;

	if (force_dma_unencrypted(dev))
		attrs |= DMA_ATTR_CC_SHARED;

	vma->vm_page_prot = dma_pgprot(dev, vma->vm_page_prot, attrs);

	if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret))
		return ret;
	if (dma_mmap_from_global_coherent(vma, cpu_addr, size, &ret))
		return ret;

	if (pgoff_start >= count || pgoff_end > count)
		return -ENXIO;
	return remap_pfn_range(vma, vma->vm_start, pfn + pgoff_start,
			user_count << PAGE_SHIFT, vma->vm_page_prot);
}

dma_addr_t dma_direct_map_phys(struct device *dev, phys_addr_t phys,
		size_t size, enum dma_data_direction dir,
		unsigned long attrs, bool flush)
{
	dma_addr_t dma_addr;

	if (attrs & DMA_ATTR_MMIO) {
		/*
		 * For host memory encryption treat MMIO memory as shared
		 */
		if (cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT))
			attrs |= DMA_ATTR_CC_SHARED;
	}

	if (is_swiotlb_force_bounce(dev)) {
		if (attrs & (DMA_ATTR_MMIO | DMA_ATTR_REQUIRE_COHERENT))
			return DMA_MAPPING_ERROR;

		return swiotlb_map(dev, phys, size, dir, attrs);
	}

	if (attrs & DMA_ATTR_CC_SHARED)
		dma_addr = phys_to_dma_unencrypted(dev, phys);
	else
		dma_addr = phys_to_dma_encrypted(dev, phys);

	if (attrs & DMA_ATTR_MMIO) {
		if (unlikely(!dma_capable(dev, dma_addr, size, false, attrs)))
			goto err_overflow;
		goto dma_mapped;
	}

	if (unlikely(!dma_capable(dev, dma_addr, size, true, attrs)) ||
	    dma_kmalloc_needs_bounce(dev, size, dir)) {
		if (is_swiotlb_active(dev) &&
		    !(attrs & DMA_ATTR_REQUIRE_COHERENT))
			return swiotlb_map(dev, phys, size, dir, attrs);
		goto err_overflow;
	}

dma_mapped:
	if (!dev_is_dma_coherent(dev) &&
	    !(attrs & (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_MMIO))) {
		arch_sync_dma_for_device(phys, size, dir);
		if (flush)
			arch_sync_dma_flush();
	}
	return dma_addr;

err_overflow:
	dev_WARN_ONCE(
		dev, 1,
		"DMA addr %pad+%zu overflow (mask %llx, bus limit %llx).\n",
		&dma_addr, size, *dev->dma_mask, dev->bus_dma_limit);
	return DMA_MAPPING_ERROR;
}

int dma_direct_supported(struct device *dev, u64 mask)
{
	u64 min_mask = ((u64)max_pfn << PAGE_SHIFT) - 1;

	/*
	 * Because 32-bit DMA masks are so common we expect every architecture
	 * to be able to satisfy them - either by not supporting more physical
	 * memory, or by providing a ZONE_DMA32.  If neither is the case, the
	 * architecture needs to use an IOMMU instead of the direct mapping.
	 */
	if (mask >= DMA_BIT_MASK(32))
		return 1;

	/*
	 * This check needs to be against the actual bit mask value, so use
	 * phys_to_dma_unencrypted() here so that the SME encryption mask isn't
	 * part of the check.
	 */
	if (IS_ENABLED(CONFIG_ZONE_DMA))
		min_mask = min_t(u64, min_mask, zone_dma_limit);
	return mask >= phys_to_dma_unencrypted(dev, min_mask);
}

static const struct bus_dma_region *dma_find_range(struct device *dev,
						   unsigned long start_pfn)
{
	const struct bus_dma_region *m;

	for (m = dev->dma_range_map; PFN_DOWN(m->size); m++) {
		unsigned long cpu_start_pfn = PFN_DOWN(m->cpu_start);

		if (start_pfn >= cpu_start_pfn &&
		    start_pfn - cpu_start_pfn < PFN_DOWN(m->size))
			return m;
	}

	return NULL;
}

/*
 * To check whether all ram resource ranges are covered by dma range map
 * Returns 0 when further check is needed
 * Returns 1 if there is some RAM range can't be covered by dma_range_map
 */
static int check_ram_in_range_map(unsigned long start_pfn,
				  unsigned long nr_pages, void *data)
{
	unsigned long end_pfn = start_pfn + nr_pages;
	struct device *dev = data;

	while (start_pfn < end_pfn) {
		const struct bus_dma_region *bdr;

		bdr = dma_find_range(dev, start_pfn);
		if (!bdr)
			return 1;

		start_pfn = PFN_DOWN(bdr->cpu_start) + PFN_DOWN(bdr->size);
	}

	return 0;
}

bool dma_direct_all_ram_mapped(struct device *dev)
{
	if (!dev->dma_range_map)
		return true;
	return !walk_system_ram_range(0, PFN_DOWN(ULONG_MAX) + 1, dev,
				      check_ram_in_range_map);
}

size_t dma_direct_max_mapping_size(struct device *dev)
{
	/* If SWIOTLB is active, use its maximum mapping size */
	if (is_swiotlb_active(dev) &&
	    (dma_addressing_limited(dev) || is_swiotlb_force_bounce(dev) ||
	     force_dma_unencrypted(dev)))
		return swiotlb_max_mapping_size(dev);

	return SIZE_MAX;
}

bool dma_direct_need_sync(struct device *dev, dma_addr_t dma_addr)
{
	return !dev_is_dma_coherent(dev) ||
	       swiotlb_find_pool(dev, dma_to_phys(dev, dma_addr));
}

/**
 * dma_direct_set_offset - Assign scalar offset for a single DMA range.
 * @dev:	device pointer; needed to "own" the alloced memory.
 * @cpu_start:  beginning of memory region covered by this offset.
 * @dma_start:  beginning of DMA/PCI region covered by this offset.
 * @size:	size of the region.
 *
 * This is for the simple case of a uniform offset which cannot
 * be discovered by "dma-ranges".
 *
 * It returns -ENOMEM if out of memory, -EINVAL if a map
 * already exists, 0 otherwise.
 *
 * Note: any call to this from a driver is a bug.  The mapping needs
 * to be described by the device tree or other firmware interfaces.
 */
int dma_direct_set_offset(struct device *dev, phys_addr_t cpu_start,
			 dma_addr_t dma_start, u64 size)
{
	struct bus_dma_region *map;
	u64 offset = (u64)cpu_start - (u64)dma_start;

	if (dev->dma_range_map) {
		dev_err(dev, "attempt to add DMA range to existing map\n");
		return -EINVAL;
	}

	if (!offset)
		return 0;

	map = kzalloc_objs(*map, 2);
	if (!map)
		return -ENOMEM;
	map[0].cpu_start = cpu_start;
	map[0].dma_start = dma_start;
	map[0].size = size;
	dev->dma_range_map = map;
	return 0;
}
