Потоковое DMA в драйвере ядра Linux PCIE - PullRequest
6 голосов
/ 21 февраля 2012

Я работаю над драйвером FPGA для ядра Linux.Код, кажется, работает нормально на x86, но на x86_64 у меня есть некоторые проблемы.Я реализовал потоковое DMA.Таким образом, это выглядит как

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

Но pci_map_sg возвращает адреса, такие как 0xbd285800, которые не выровнены по PAGE_SIZE, поэтому я не могу отправить полную первую страницу, потому что спецификация PCIE говорит

"Запросы не должны указывать комбинацию адрес / длина, которая приводит к тому, что доступ к пространству памяти пересекает границу 4 КБ."

Есть ли способ получить выровненные адреса илия только что пропустил что-то важное?

Исходный код DMA .

1 Ответ

3 голосов
/ 22 февраля 2012

Первая возможность, которая приходит на ум, заключается в том, что входящий пользовательский буфер не начинается на границе страницы. Если ваш начальный адрес составляет 0x800 байт на странице, то смещение при первом вызове sg_set_page будет 0x800. Это даст адрес DMA, заканчивающийся 0x800. Это нормальное явление, а не ошибка.

Поскольку pci_map_sg объединяет страницы, этот первый сегмент может быть больше, чем одна страница. Важно то, что pci_map_sg создает непрерывные блоки адресуемой памяти DMA, но не создает список транзакций PCIe низкого уровня. На x64 у вас больше шансов получить большой регион, потому что большинство платформ x64 имеют IOMMU.

Многие устройства, с которыми я имею дело, имеют механизмы DMA, которые позволяют указывать логическую длину передачи в несколько мегабайт. Обычно реализация DMA в конечной точке PCIe отвечает за запуск новой транзакции PCIe на каждой границе 4 КБ, и программист может игнорировать это ограничение. Если ресурсы в FPGA слишком ограничены, чтобы справиться с этим, вы можете написать код драйвера для преобразования списка блоков памяти Linux в (гораздо более длинный) список транзакций PCIe.

...