kernel/dma/direct.c
Source file repositories/reference/linux-study-clean/kernel/dma/direct.c
File Facts
- System
- Linux kernel
- Corpus path
kernel/dma/direct.c- Extension
.c- Size
- 18488 bytes
- Lines
- 679
- Domain
- Core OS
- Bucket
- Scheduler, Processes, Timers, Sync, And Syscalls
- Inferred role
- Core OS: implementation source
- Status
- source implementation candidate
Why This File Exists
Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/memblock.hlinux/export.hlinux/mm.hlinux/dma-map-ops.hlinux/scatterlist.hlinux/pfn.hlinux/vmalloc.hlinux/set_memory.hlinux/slab.hlinux/pci-p2pdma.hdirect.h
Detected Declarations
function phys_to_dma_directfunction dma_direct_get_required_maskfunction dma_direct_optimal_gfp_maskfunction dma_coherent_okfunction dma_set_decryptedfunction dma_set_encryptedfunction __dma_direct_free_pagesfunction dma_direct_use_poolfunction dma_direct_freefunction dma_direct_free_pagesfunction definedfunction for_each_sgfunction definedfunction for_each_sgfunction dma_direct_unmap_sgfunction for_each_sgfunction dma_direct_map_sgfunction for_each_sgfunction dma_direct_get_sgtablefunction dma_direct_can_mmapfunction dma_direct_mmapfunction dma_direct_supportedfunction check_ram_in_range_mapfunction dma_direct_all_ram_mappedfunction dma_direct_max_mapping_sizefunction dma_direct_need_syncfunction dma_direct_set_offset
Annotated Snippet
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.
*/
if ((remap || force_dma_unencrypted(dev)) &&
dma_direct_use_pool(dev, gfp))
return dma_direct_alloc_from_pool(dev, size, dma_handle, gfp);
/* we always manually zero the memory once we are done */
page = __dma_direct_alloc_pages(dev, size, gfp & ~__GFP_ZERO, true);
if (!page)
return NULL;
/*
* 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 (remap) {
pgprot_t prot = dma_pgprot(dev, PAGE_KERNEL, attrs);
if (force_dma_unencrypted(dev))
prot = pgprot_decrypted(prot);
/* remove any dirty cache lines on the kernel alias */
arch_dma_prep_coherent(page, size);
/* create a coherent mapping */
ret = dma_common_contiguous_remap(page, size, prot,
__builtin_return_address(0));
if (!ret)
goto out_free_pages;
} else {
ret = page_address(page);
if (dma_set_decrypted(dev, ret, size))
goto out_leak_pages;
}
memset(ret, 0, size);
if (set_uncached) {
arch_dma_prep_coherent(page, size);
ret = arch_dma_set_uncached(ret, size);
if (IS_ERR(ret))
goto out_encrypt_pages;
}
*dma_handle = phys_to_dma_direct(dev, page_to_phys(page));
return ret;
out_encrypt_pages:
if (dma_set_encrypted(dev, page_address(page), size))
return NULL;
out_free_pages:
__dma_direct_free_pages(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)
{
unsigned int page_order = get_order(size);
if ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
!force_dma_unencrypted(dev) && !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;
}
Annotation
- Immediate include surface: `linux/memblock.h`, `linux/export.h`, `linux/mm.h`, `linux/dma-map-ops.h`, `linux/scatterlist.h`, `linux/pfn.h`, `linux/vmalloc.h`, `linux/set_memory.h`.
- Detected declarations: `function phys_to_dma_direct`, `function dma_direct_get_required_mask`, `function dma_direct_optimal_gfp_mask`, `function dma_coherent_ok`, `function dma_set_decrypted`, `function dma_set_encrypted`, `function __dma_direct_free_pages`, `function dma_direct_use_pool`, `function dma_direct_free`, `function dma_direct_free_pages`.
- Atlas domain: Core OS / Scheduler, Processes, Timers, Sync, And Syscalls.
- Implementation status: source implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.