칸드로이드 저널- "Beyond Android" 
ARM 관련 DMA 맵핑 코드 재작업 - lwn 번역
작성자
작성일 2012-04-09 (월) 20:39
ㆍ추천: 0  ㆍ조회: 5711      
IP: 125.xxx.222
 
Kernel prepatch 3.4-rc2
 
3.4-rc2 프리패치가 나왔는데 이 안에는 DMA 맵핑 재작업이 포함되었다고 합니다.
DMA 맵핑 코드 재작업이 ARM과 매우 밀접히 관련되어 있는 내용이어서, 이와 관련된 2011년 11월 16일
Jonathan Corbet의 글을 번역해서 올립니다.
아래의 글이 쓰여질 당시에는 DMA mapping code 재작업이 프리패치항목으로 결정나기 전이었고,
현재는 결정난 시점입니다. 하지만 내용은 유효합니다.
 
-----

Reworking the DMA mapping code (especially on ARM)

                                                                        - By Jonathan Corbet (November 16, 2011)
 
DMA(Direct Memory Access) /O는 단순하게 들리는 개념이다. 이 개념은 디바이스가 CPU를 통하지 않고
메모리를 직접 접근해서 데이터를 전송할 수 있다는 것이다. 물론 실제로 이 개념은, 실세계와 이상한 아키텍처
차이와 문제가 있는 디바이스, 그리고 다양한 I/O 요구들과 마주하게 되면 복잡한 문제가 된다. DMA 맵핑 API는
드라이버가 처리해야 하는 DMA에 관련된 복잡한 것들을 최소화시키기 위한 방안으로 만들어졌으며, 그 목적을
꽤 잘 달성했다. 그럼에도 불구하고, 변화하는 필요들과 증가하는 하드웨어 복잡도는 부수적 이익으로 ARM
아키텍처 또한 잘 정리하는 것과 함께 이 영역에 몇가지 변화를 이끌고 있다.
 
많은 영역들에 있는 경우지만, ARM 아키텍처에는 사용될 수 있는 유용한 아키텍처 독립적인 것이 꽤 있음에도
불구하고 자체 구현한 DMA API를 가지고 있다. 여기에도 통상적인 이유가 적용된다. 즉 ARM 트리에서만 작업
하는 개발자 집단과 해당 아키텍처에만 한정된 특이성이 그것이다. 이러한 것은 많은 다른 곳에서도 보이는
패턴이다. 분명히 ARM에 한정된 것은 아니다.
 
Marek Szyprowski의 ARM DMA 재디자인 패치 셋에 의해 이루어진 첫번째 것들 중 하나는, 보편적인 DMA
프레임워크에 ARM을 연결하는 것이었다. 그것은 확실히 많은 양의 코드를 제거하고 보편적인 코드로 대체하는
것을 가능하게 했다. 여러가지 것들 중에서도, 이 작업은 ARM 아키텍처 자체 내부에 있는 차이들을 처리하는
것을 단순화하고 있다. 보편적인 struct dma_map_ops의 사용에도 불구하고, 하나의 아키텍처는 주어진 상황에
한정된 맵핑 오퍼레이션들 셋을 제공할 수 있다. 예를 들어, 다른 디바이스들은 다른 DMA 오퍼레이션을 가질 수
있다.
 
그러나 보편적인 인터페이스보다 ARM의 DMA 구현물에는 더 많은 것이 있다. ARM의 API는 다음과 같은 특별한
함수를 가진다.
 
void *dma_alloc_writecombine(struct device *dev, size_t len, 
                                            dma_addr_t *dma_addr, gfp_t flags);
 
이 함수는 "write combining" 애트리뷰트를 가진 DMA 버퍼를 할당한다. 이것은 (CPU에 의해) 메모리에 쓰여지는
데이터가 메모리 하드웨어에 의해 유보되었다가 한꺼번에 처리될 수 있다는  것을 의미한다. write combining
메모리의 사용은 몇몇 디바이스 유형에 대해서는 의미있는 성능 개선을 이뤄낼 수 있지만, 이 메모리는 지체된
쓰기가 디바이스에 의한 접근과 섞이지 않도록 명백하게 조심스럽게 취급되어야 한다. 여러개의 드라이버들이
이 함수를 사용하지만, 이것을 제공하는 다른 아키텍처는 avr32 오직 하나뿐이다.
 
ARM은 또한 DMA 버퍼를 사용자 공간에 맵핑하는 특수한 함수를 가지고 있다.
 
int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma, 
                                    void *cpu_addr, dma_addr_t dma_addr, size_t len);
 
대부분의 아키텍처에서, 일관성이 유지되는 버퍼를 메모리 맵핑하는 것은 어떤 특별한 처리도 필요로 하지 않는다.
그러므로 일반적인 DMA 코드는 이러한 오퍼레이션에 대한 어떤 특별한 지원도 제공하지 않는다. 다른 아키텍처
중에 오직 PowerPC 하나만이 이 함수를 추가할 필요성를 느꼈었다.
 
분명히, ARM DMA API를 보편적인 코드를 가진 라인으로 바꾸는 것은 이러한 특별한 함수들을 처리하는 몇가지
방법을 요구할 것이다. 위의 함수들 각각에 대해, 다른 아키텍처에선 하나씩만이 그것을 구현했다는 사실은 ARM
만큼 이상하게 확장된 API를 필요로하는 것이 혼자는 아니라는 것을 가리킨다. 그러므로 해야할 논리적인 것은
이러한 함수에 대한 지원을 보편적인 DMA 코어 구현내로 이동시키는 것이다.
 
그것은 신규 alloc_writecombine()과 mmap_coherent() 함수들(그리고, mmap_writecombine() 역시 그렇다)을
struct dma_map_ops에 추가함으로써 이뤄질 수 있다. 그럼에도 불구하고 오퍼레이션 조합 갯수와 메모리
애트리뷰트들이 증가함에 따라, 그 structure의 크기 또한 증가할 것이다. Marek는 다른 접근을 하기로 결정했다.
그의 패치는 기존에 존재하던 alloc_cohrent()와 free_cohreent() 멤버를 제거하고, 다음과 같이 대체하는 것이다.
 
void* (*alloc)(struct device *dev, size_t size, dma_addr_t *dma_handle,
                   gfp_t gfp, struct dma_attrs *attrs);
void (*free)(struct device *dev, size_t size, void *vaddr,
                  dma_addr_t dma_handle, struct dma_attrs *attrs);
int (*mmap)(struct device *dev, struct vm_area_struct *vma, void *cpu_addr,
                  dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs);

 
마침, struct dma_attrs은 이미 현재 커널에 있었다. 그럼에도 불구하고 그것은 많이 사용되지는 않는다. 현재는
오직 두개의 애트리뷰트가 정의되어 있다. (Documentation/DMA-attributes.txt에 설명되어 있다)  이것은 오직
ia64와 PowerPC/Cell 아키텍처에서만 구현된 것처럼 보인다. 오직 이들 중 하나(DMA_ATTR_WRITE_BARRIER)
만이 실제도 사용되는 것 같다. 그리고 오직 한곳(InfiniBand 코드)에서만 사용된다. 그러나 메커니즘은 이미
존재한다. 그러므로 "write combining"과 같은 것들을 표현하기 위한 신규 방법을 추가하는 것 보다는 더 많은
애트리뷰트를 추가하는 것이 더 나은 접근처럼 보인다. Marek의 패치는 "cohrerent"를 의미하는 null attrs 포인터와
noncohrent와 write-combining 맵핑에 대한 애트리뷰트를 추가하는 규약을 추가하고 있다. 그런 다음에 다양한
할당 함수들이 다음과 같이 대체되었다.
 
void *dma_alloc_attrs(struct device *dev, size_t size,
                               dma_addr_t *dma_handle, gfp_t flag,
                                struct dma_attrs *attrs);

 
이 함수는 그 아래 놓인 플랫폼이 지원할 수 있는 임의의 애트리뷰트 집합을 가진 맵핑을 요구하기 위해 사용될
수 있다. DMA 버퍼 해제와 메모리 맵핑에 대한 유사한 함수들이 있다. Marek 패치는 이 함수들을 그 밖의 다른
아키텍처로 확대하지는 않는다. 심지어 추가했던 함수들은 ARM에서 사용되는 것들과 유사하다. 그러나 그것은
분명히 다음 단계일 것 같아 보인다.
 
일단 그 단계가 끝나면, Marek은 아마도 그의 실제 목표였던, ARM DMA API에 디바이스별 I/O 메모리 관리
단위(IOMMUs) 지원을 추가하는 것을 얻을 수 있을 것이다. 몇몇 하드웨어는 다른 디바이스에서는 사용할 수
없도록 만들어진 분리된 IOMMU를 가지고 있다. 그러므로 그 IOMMU는 시스템 전체에 유용하게 될 수는 없다.
그러나 심지어 디바이스 드라이버가 IOMMU에 대해 알 필요없이 그것을 사용하기 위해 DMA API를 호출할
그러한 디바이스에, 디바이스 제한적인 dma_map_ops structure를 연결하는 것은 가능하다. 그리고 그것은
물론 더 간단 하고 더 신뢰할만한 코드를 이끌어 낼 것이다.
 
이 작업 이전에는, IOMMU 인식이 특별한 드라이버에서 직접적으로 만들어졌다. 그러나 그것은 검사시간의
문제를 야기했다. 그런 방식으로 작성된 드라이버는 실제로 메인라인에 합쳐질 수 없다. 그가 LinuxCon Prague
에서 이 작업에 대해 말했을 때, Marek은 경험에서 그가 배웠던 몇가지 교훈을 전수했다. 그것들 중 첫째는
누구든 가능하다면 항상 존재하는 API를 사용해야 한다는 것이었다. 모든 개발자는 그들이 어떤 것을 더 잘 할 수
있다고 생각한다. 그것은 사실일 수도 아닐 수도 있다. 그러나 일반적인 코드를 사용하는 것이 결국에는 더 잘
동작한다. 그러나 그는 개발자들이 그 필요가 있을때, 코어 인터페이스를 확장하는 것을 두려워해서는 안된다고
말했다. 그것이 문제가 해결되는 방법이고 코어가 더 좋아지는 방법이다. 마지막 교훈은 이러한 종류의 문제를
해결해야 할 때, 일정 시간이 걸린다고 생각하라는 것이다.
 
시간에 관하여, 이 작업이 메인라인으로 들어갈 수 있을 지는 분명하지 않다. 그것은 아직 실제로 포함되도록
제출되지는 않았다. 현재 패치들은 그것들이 준비상태에 이르기 전에 해야하는 몇가지 분명한 작업이 있다.
그러나 Marek는 여러번의 시도를 통해, 과거에 심각한 기술적 이이제기를 받았던 것으로 보이며, 이제는 세부
사항들을 제대로 얻는 작업을 하고 있는 것 같다. 그러므로 누군가가 그의 충고를 따라야 하고 일정 시간이 걸린다고
생각한다면, 일정한 시간이라는 가치는 합리적으로 작은 수로 접근되어야 한다.

 
덧글 쓰기 0
3500
※ 회원등급 레벨 0 이상 읽기가 가능한 게시판입니다.