// SPDX-License-Identifier: GPL-2.0-only/* * A fairly generic DMA-API to IOMMU-API glue layer. * * Copyright (C) 2014-2015 ARM Ltd. * * based in part on arch/arm/mm/dma-mapping.c: * Copyright (C) 2000-2004 Russell King */#include<linux/acpi_iort.h>#include<linux/device.h>#include<linux/dma-map-ops.h>#include<linux/dma-iommu.h>#include<linux/gfp.h>#include<linux/huge_mm.h>#include<linux/iommu.h>#include<linux/iova.h>#include<linux/irq.h>#include<linux/mm.h>#include<linux/mutex.h>#include<linux/pci.h>#include<linux/scatterlist.h>#include<linux/vmalloc.h>#include<linux/crash_dump.h>structiommu_dma_msi_page{structlist_headlist;dma_addr_tiova;phys_addr_tphys;};enumiommu_dma_cookie_type{IOMMU_DMA_IOVA_COOKIE,IOMMU_DMA_MSI_COOKIE,};structiommu_dma_cookie{enumiommu_dma_cookie_typetype;union{/* Full allocator for IOMMU_DMA_IOVA_COOKIE */structiova_domainiovad;/* Trivial linear page allocator for IOMMU_DMA_MSI_COOKIE */dma_addr_tmsi_iova;};structlist_headmsi_page_list;/* Domain for flush queue callback; NULL if flush queue not in use */structiommu_domain*fq_domain;};voidiommu_dma_free_cpu_cached_iovas(unsignedintcpu,structiommu_domain*domain){structiommu_dma_cookie*cookie=domain->iova_cookie;structiova_domain*iovad=&cookie->iovad;free_cpu_cached_iovas(cpu,iovad);}staticvoidiommu_dma_entry_dtor(unsignedlongdata){structpage*freelist=(structpage*)data;while(freelist){unsignedlongp=(unsignedlong)page_address(freelist);freelist=freelist->freelist;free_page(p);}}staticinlinesize_tcookie_msi_granule(structiommu_dma_cookie*cookie){if(cookie->type==IOMMU_DMA_IOVA_COOKIE)returncookie->iovad.granule;returnPAGE_SIZE;}staticstructiommu_dma_cookie*cookie_alloc(enumiommu_dma_cookie_typetype){structiommu_dma_cookie*cookie;cookie=kzalloc(sizeof(*cookie),GFP_KERNEL);if(cookie){INIT_LIST_HEAD(&cookie->msi_page_list);cookie->type=type;}returncookie;}/** * iommu_get_dma_cookie - Acquire DMA-API resources for a domain * @domain: IOMMU domain to prepare for DMA-API usage * * IOMMU drivers should normally call this from their domain_alloc * callback when domain->type == IOMMU_DOMAIN_DMA. */