dma_handle 포인터와 cpu_addr 를 각각 관리하는 이유

 

  1. DMA 장치와 CPU 간의 메모리 구조의 차이: 일반적으로 DMA 장치는 메모리에 직접 접근하여 데이터를 전송합니다. 이 때 DMA 장치는 메모리 주소 공간을 CPU가 사용하는 것과 다르게 볼 수 있습니다. 예를 들어, 일부 시스템에서는 DMA 장치가 접근할 수 있는 주소 공간이 제한되어 있거나 물리적인 주소 공간이 특정한 형식을 따를 수 있습니다. 그러므로 DMA 장치가 접근하는 주소와 CPU가 접근하는 주소가 다를 수 있습니다.
  2. 캐시 일관성(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

+ Recent posts