*参照元 [#g67f836d] #backlinks *説明 [#b144c45e] -パス: [[linux-4.4.1/arch/arm/mm/dma-mapping.c]] -FIXME: これは何? --説明 **引数 [#i200bce6] -struct device *dev -- --[[linux-4.4.1/device]] -size_t size -- -dma_addr_t *handle -- --[[linux-4.4.1/dma_addr_t]] -gfp_t gfp -- --[[linux-4.4.1/gfp_t]] -pgprot_t prot -- --[[linux-4.4.1/pgprot_t]] -bool is_coherent -- -struct dma_attrs *attrs -- --[[linux-4.4.1/dma_attrs]] -const void *caller -- **返り値 [#y8721785] -void * -- **参考 [#u85ffe64] *実装 [#j8654022] static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, pgprot_t prot, bool is_coherent, struct dma_attrs *attrs, const void *caller) { u64 mask = get_coherent_dma_mask(dev); struct page *page = NULL; void *addr; bool want_vaddr; - --[[linux-4.4.1/get_coherent_dma_mask()]] --[[linux-4.4.1/page]] #ifdef CONFIG_DMA_API_DEBUG - --[[linux-4.4.1/CONFIG_DMA_API_DEBUG]] u64 limit = (mask + 1) & ~mask; if (limit && size >= limit) { dev_warn(dev, "coherent allocation too big (requested %#x mask %#llx)\n", size, mask); - --[[linux-4.4.1/dev_warn()]] return NULL; } #endif if (!mask) return NULL; if (mask < 0xffffffffULL) gfp |= GFP_DMA; /* * Following is a work-around (a.k.a. hack) to prevent pages * with __GFP_COMP being passed to split_page() which cannot * handle them. The real problem is that this flag probably * should be 0 on ARM as it is not supported on this * platform; see CONFIG_HUGETLBFS. */ gfp &= ~(__GFP_COMP); *handle = DMA_ERROR_CODE; size = PAGE_ALIGN(size); want_vaddr = !dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs); - --[[linux-4.4.1/PAGE_ALIGN()]] --[[linux-4.4.1/dma_get_attr()]] if (nommu()) addr = __alloc_simple_buffer(dev, size, gfp, &page); - --[[linux-4.4.1/nommu()]] --[[linux-4.4.1/__alloc_simple_buffer()]] else if (dev_get_cma_area(dev) && (gfp & __GFP_DIRECT_RECLAIM)) addr = __alloc_from_contiguous(dev, size, prot, &page, caller, want_vaddr); - --[[linux-4.4.1/dev_get_cma_area()]] --[[linux-4.4.1/__alloc_from_contiguous()]] else if (is_coherent) addr = __alloc_simple_buffer(dev, size, gfp, &page); else if (!gfpflags_allow_blocking(gfp)) addr = __alloc_from_pool(size, &page); - --[[linux-4.4.1/gfpflags_allow_blocking()]] --[[linux-4.4.1/__alloc_from_pool()]] else addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller, want_vaddr); - --[[linux-4.4.1/__alloc_remap_buffer()]] if (page) *handle = pfn_to_dma(dev, page_to_pfn(page)); - --[[linux-4.4.1/pfn_to_dma()]] --[[linux-4.4.1/page_to_pfn()]] return want_vaddr ? addr : page; } *コメント [#g21e54ba]