2012-02-21 6 views
6

리눅스 커널 용 FPGA 드라이버에서 일하고 있습니다. 코드는 x86에서 잘 작동하는 것처럼 보이지만 x86_64에서는 몇 가지 문제가 있습니다. 스트리밍 DMA를 구현했습니다.PCIE 리눅스 커널 드라이버에서 스트리밍 DMA

get_user_pages(...); 
for (...) { 
    sg_set_page(); 
} 
pci_map_sg(); 

그러나 pci_map_sgPAGE_SIZE으로 정렬되지 0xbd285800 같은 주소를 반환, 그래서 전체 첫 페이지를 보낼 수 없습니다처럼 PCIE 사양

"요청이 지정하지해야한다고 때문에 그래서, 간다 메모리 공간 액세스가 4KB 경계를 넘는 주소/길이 조합. "

주소를 정렬하는 방법이 있습니까? 아니면 중요한 것을 놓친 적이 있습니까?

Source code of DMA.

+0

실제 소스의 코드를 포함 할 수 있습니까? 버그를 발견 할만큼 충분하지 않습니다. –

+0

물론입니다. 원래 게시물에 첨부되었습니다. – soh

+0

@soh : 대중에게 공개 할 계획이 있습니까? 나는 열린 드라이버를 찾고 있었고 좋은 드라이버를 찾을 수 없었다. 자신 만의 글을 쓰기에는 너무 게으르므로 테스트에 참여하고 도움을주는 데 기꺼이 나만의 것이 아닙니다. –

답변

3

마음에 오는 첫 번째 가능성은 사용자 버퍼가 페이지 경계에서 시작하지 않는다는 것입니다. 시작 주소가 페이지를 통해 0x800 바이트 인 경우 첫 번째 sg_set_page 호출의 오프셋은 0x800이됩니다. 그러면 0x800로 끝나는 DMA 주소가 생성됩니다. 이것은 정상적인 일이며 버그가 아닙니다.

pci_map_sg은 페이지를 합칩니다.이 첫 번째 세그먼트는 한 페이지보다 클 수 있습니다. 중요한 것은 pci_map_sg이 DMA 주소 지정 가능 메모리의 연속 블록을 생성하지만 저수준 PCIe 트랜잭션 목록을 생성하지 않는다는 것입니다. x64에서는 대부분의 x64 플랫폼에 IOMMU가 있기 때문에 큰 영역을 차지할 가능성이 큽니다.

내가 다루는 많은 장치에는 몇 메가 바이트의 논리적 전송 길이를 지정할 수있는 DMA 엔진이 있습니다. 일반적으로 PCIe 엔드 포인트의 DMA 구현은 각 4kB 경계에서 새로운 PCIe 트랜잭션을 시작하는 책임이 있으며 프로그래머는 해당 제약 조건을 무시할 수 있습니다. FPGA의 리소스가 너무 제한적일 경우 드라이버의 코드를 작성하여 Linux 메모리 목록을 (훨씬 더 긴) PCIe 트랜잭션 목록으로 변환 할 수 있습니다.

+0

고마워요. 사용자 버퍼는 괜찮지 만 FPGA PCIE 코어는 긴 버퍼를 처리하지 않습니다. – soh