2012-02-21 15 views
6

Estoy trabajando en el controlador FPGA para kernel de Linux. El código parece funcionar bien en x86, pero en x86_64 tengo algunos problemas. Implementé DMA de transmisión. Por lo tanto, va comoStreaming DMA en el controlador de kernel PCIE Linux

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

Pero pci_map_sg regresaron direcciones como 0xbd285800, que no están alineados por PAGE_SIZE, por lo que no puede enviar la página completa primero, porque la especificación PCI Express dice

"Las solicitudes no deben especificar una combinación de Dirección/Longitud que causa un acceso al Espacio de Memoria para cruzar un límite de 4 KB. "

¿Hay alguna forma de obtener direcciones alineadas, o acabo de perder algo importante?

Source code of DMA.

+0

¿Se puede incluir código de su fuente real? No hay suficiente allí para detectar el error. –

+0

Sí, por supuesto. Adjunto a la publicación original. – soh

+0

@soh: ¿Hay algún plan para lanzarlo al público? Estaba buscando un controlador abierto y no pude encontrar uno bueno. Siendo demasiado perezoso para escribir el mío, estaría más que contento de contribuir y ayudar con las pruebas. –

Respuesta

3

La primera posibilidad que me viene a la mente es que el búfer de usuario entrante no se inicia en un límite de página. Si su dirección de inicio es 0x800 bytes a través de una página, el desplazamiento en su primera llamada sg_set_page será 0x800. Esto producirá una dirección DMA que termina en 0x800. Esto es algo normal que sucede, y no un error.

Como pci_map_sg combina páginas, este primer segmento puede ser más grande que una página. Lo importante es que pci_map_sg produce bloques contiguos de memoria direccionable DMA, pero no produce una lista de transacciones PCIe de bajo nivel. En x64 es más probable que obtenga una región grande, porque la mayoría de las plataformas x64 tienen una IOMMU.

Muchos dispositivos con los que trato tienen motores DMA que me permiten especificar una longitud de transferencia lógica de varios megabytes. Normalmente, la implementación de DMA en el punto extremo PCIe es responsable de iniciar una nueva transacción PCIe en cada límite de 4 kB, y el programador puede ignorar esa restricción. Si los recursos en el FPGA son demasiado limitados para manejar eso, puede considerar escribir el código del controlador para convertir la lista de bloques de memoria de Linux en una lista (mucho más larga) de transacciones PCIe.

+0

Muchas gracias. El búfer de usuario estaba bien, pero el núcleo FPGA PCIE no maneja búferes largos. – soh

Cuestiones relacionadas