dma_handle 포인터와 cpu_addr 를 각각 관리하는 이유
- DMA 장치와 CPU 간의 메모리 구조의 차이: 일반적으로 DMA 장치는 메모리에 직접 접근하여 데이터를 전송합니다. 이 때 DMA 장치는 메모리 주소 공간을 CPU가 사용하는 것과 다르게 볼 수 있습니다. 예를 들어, 일부 시스템에서는 DMA 장치가 접근할 수 있는 주소 공간이 제한되어 있거나 물리적인 주소 공간이 특정한 형식을 따를 수 있습니다. 그러므로 DMA 장치가 접근하는 주소와 CPU가 접근하는 주소가 다를 수 있습니다.
- 캐시 일관성(Cache Coherency): 많은 시스템에서 CPU는 캐시를 사용하여 성능을 향상시킵니다. 그러나 DMA 장치는 이러한 캐시 구조에 직접적으로 접근할 수 없기 때문에, CPU가 쓴 데이터가 캐시에 존재하는 경우에도 DMA 장치에서 해당 데이터를 읽을 때 문제가 발생할 수 있습니다. 이를 해결하기 위해서는 DMA 전송 전에 캐시를 플러시하거나(invalidate) DMA 전송 후에 캐시를 재설정해야 할 수 있습니다. 이러한 캐시 일관성 문제를 해결하기 위해 DMA 할당 함수는 CPU가 접근하는 메모리 주소와 DMA 장치가 접근하는 메모리 주소를 따로 관리합니다. 이를 통해 DMA 전송 시에 캐시 일관성을 유지할 수 있습니다.
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
typedef u64 dma_addr_t;
#else
typedef u32 dma_addr_t;
#endif
void *dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
gfp_t flag, unsigned long attrs)
{
const struct dma_map_ops *ops = get_dma_ops(dev);
void *cpu_addr;
WARN_ON_ONCE(!dev->coherent_dma_mask);
if (dma_alloc_from_dev_coherent(dev, size, dma_handle, &cpu_addr))
return cpu_addr;
/* let the implementation decide on the zone to allocate from: */
flag &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
if (dma_alloc_direct(dev, ops))
cpu_addr = dma_direct_alloc(dev, size, dma_handle, flag, attrs);
else if (ops->alloc)
cpu_addr = ops->alloc(dev, size, dma_handle, flag, attrs);
else
return NULL;
debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr);
return cpu_addr;
}
EXPORT_SYMBOL(dma_alloc_attrs);
반응형
'Interface' 카테고리의 다른 글
Linux : target is busy during unmount (0) | 2024.04.05 |
---|---|
USB | DWC3 Gadget initialization (UMS) (0) | 2024.03.21 |
USB | Quirks (0) | 2024.03.20 |