Первая возможность, которая приходит на ум, заключается в том, что входящий пользовательский буфер не начинается на границе страницы. Если ваш начальный адрес составляет 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.