*参照元 [#r3c540e1] #backlinks *説明 [#p2bacbcf] -パス: [[linux-4.4.1/arch/arm64/mm/dma-mapping.c]] -FIXME: これは何? --説明 --CMA が使えそうなら CMA から取得しようとする。そうでなければ swiotlb から取得しようとする。 --確保された領域は 0 で初期化される。 **引数 [#of6b9568] -struct device *dev --デバイス --[[linux-4.4.1/device]] -size_t size --確保したい領域のサイズ -dma_addr_t *dma_handle --確保した領域の DMA アドレスが返される --[[linux-4.4.1/dma_addr_t]] -gfp_t flags -- --[[linux-4.4.1/gfp_t]] -struct dma_attrs *attrs -- --属性を指定するが、この関数では使わない --[[linux-4.4.1/dma_attrs]] **返り値 [#e724921e] -void * --確保した領域の先頭を指すポインタ。失敗した場合は NULL。 **参考 [#oaacd9cc] *実装 [#w4f04f7c] static void *__dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flags, struct dma_attrs *attrs) { if (dev == NULL) { WARN_ONCE(1, "Use an actual device structure for DMA allocation\n"); return NULL; } - --[[linux-4.4.1/WARN_ONCE()]] if (IS_ENABLED(CONFIG_ZONE_DMA) && dev->coherent_dma_mask <= DMA_BIT_MASK(32)) flags |= GFP_DMA; - --[[linux-4.4.1/IS_ENABLED()]] --[[linux-4.4.1/CONFIG_ZONE_DMA]] --[[linux-4.4.1/DMA_BIT_MASK()]] if (dev_get_cma_area(dev) && gfpflags_allow_blocking(flags)) { struct page *page; void *addr; - --[[linux-4.4.1/dev_get_cma_area()]] --[[linux-4.4.1/gfpflags_allow_blocking()]] --[[linux-4.4.1/page]] page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT, get_order(size)); if (!page) return NULL; -2番めの引数は何ページ確保するか。サイズからページ数に変換している。 -3番目の引数はアラインメント。要求されたサイズが大きくなると、アラインメントも大きくなる。 --[[linux-4.4.1/dma_alloc_from_contiguous()]] --[[linux-4.4.1/PAGE_SHIFT]] --[[linux-4.4.1/get_order()]] *dma_handle = phys_to_dma(dev, page_to_phys(page)); addr = page_address(page); memset(addr, 0, size); - --[[linux-4.4.1/phys_to_dma()]] --[[linux-4.4.1/page_to_phys()]] --[[linux-4.4.1/page_address()]] return addr; } else { return swiotlb_alloc_coherent(dev, size, dma_handle, flags); - --[[linux-4.4.1/swiotlb_alloc_coherent()]] } } *コメント [#e22f79db]