Вопрос:

Mmap очень медленно при использовании O_SYNC

c linux-device-driver embedded-linux mmap ethernet

551 просмотра

1 ответ

89 Репутация автора

Краткое описание нашего проекта: мы используем CycloneV в нашем проекте, FPGA будет записывать данные в DDR, используя шину AXI, и наше приложение должно отправлять данные через Ethernet. Мы измеряем нашу пропускную способность Ethernet с помощью iperf, и она может достигать скорости около 700 Мбит / с. Когда мы тестируем производительность нашего приложения, мы получаем только 400 Мбит / с. Мы пишем простой код сервера без использования /dev/mem, затем заполняем память случайными данными, используя ddкоманду, и приложение считывает файл для отправки. Мы замечаем, что пропускная способность на самом деле близка к эталону iperf. Мы выяснили, что когда мы удаляем O_SYNC во время открытия /dev/mem, пропускная способность может быть достигнута близкой к пропускной способности iperf. Но проблема в том, что мы получаем периодически неправильные данные, если не используем O_SYNC.

Мы выделяем непрерывную память, используя dma_alloc_coherent:

p_ximageConfig->fpgamem_virt = dma_alloc_coherent(NULL, Dma_Size, &(p_ximageConfig->fpgamem_phys), GFP_KERNEL);

и мы передаем физическую память пользовательскому пространству в mmap, используя IOCTL:

uint32 DMAPHYSADDR = getDmaPhysAddr();
pImagePool = ((volatile unsigned char*)mmap( 0,MAPPED_SIZE_BUFFER, PROT_READ|PROT_WRITE, MAP_SHARED, _fdFpga, DMAPHYSADDR));

Мы попробовали следующие методы:

  1. Написание нашего собственного mmap в нашем драйвере: мы все равно периодически получаем неправильные данные, если не синхронизируемся. Мы использовали метод синхронизации pgprot_noncached и pgprot_dmacoherent, но он может достигать только 300 Мбит / с.

  2. Мы попытались использовать dma_mmap_coherent : полученный результат составляет около 500 Мбит / с.

Есть ли способ, который может помочь нам достичь производительности, близкой к производительности iperf?

Автор: WWJ Источник Размещён: 10.01.2018 01:35

Ответы (1)


1 плюс

26 Репутация автора

Решение

Я не знаю, почему iperfтак быстро, но как mmapработает память устройства.

Давайте посмотрим на mmap_mem()функцию , которая вызывается при вызове пользователя mmap. Согласно этой строке , эта функция отображает память как некэшированную, если O_SYNCона указана, и как (возможно) обратную запись еще. Это vma->vm_page_prot = __pgprot_modify(vma->vm_page_prot, L_PTE_MT_MASK, L_PTE_MT_WRITEBACK);может сделать это быстрее.

Итак, здесь мы включили кэш области памяти. Тогда как синхронизировать контент с FPGA?

Одним из способов является синхронизация с помощью программного обеспечения. Есть dmac_map_area()и dmac_unmap_area()звонки, которые соответствуют v7_dma_map_area()и v7_dma_unmap_area()соответственно. Эти функции принимают три параметра: адрес пользователя addr, размер sizeи направление DMA dir.

Когда мы вызываем dmac_map_area(addr, size, DMA_TO_DEVICE), содержимое кэша процессора записывается в память. Сделайте это, когда процессор закончит запись в память, а устройство начнет считывать данные из этого места.

Когда мы вызываем dmac_unmap_area(addr, size, DMA_FROM_DEVICE), содержимое кэша ЦП помечается как «недействительное», и когда мы читаем из местоположения, новый контент с устройства считывается в кэш ЦП. Так что сделайте это, когда устройство завершит запись в память, а ЦП начнет считывать данные из этого места.

Другой способ - использовать выделенное оборудование. Согласно этому PDF , Cyclone V имеет порт когерентности ускорителя (ACP), который позволяет FPGA считывать содержимое кэша ARM. Я думаю, что это может быть быстрее, чем программное обеспечение, но, поскольку я не знаю, как использовать ACP, попробуйте поискать в Google.

Автор: y s Размещён: 12.01.2018 03:28
Вопросы из категории :
32x32