Как правильно использовать scatterlists в ядре Linux - PullRequest
0 голосов
/ 05 сентября 2018

SO! Возможно, этот вопрос уже задавался, но я не смог найти ничего, что бы соответствовало моим потребностям. Я хочу создать буфер, который можно отобразить в пользовательское пространство (виртуальную непрерывную память), а также создать из него список рассеяния для операций DMA.

Вот как я это представляю:

  1. Выделить буфер (vmalloc)
  2. Найти адрес шины для каждого байта этого буфера, построить следующую таблицу (вставьте новую строку в нее, только если физический адрес больше, чем PAGE_SIZE)

    • (struct scatterlist*: адрес шины | длина)
  3. Звоните dma_map_sg, он заполнит dma_address полей.

  4. Отправка dma_addresses на устройство вместе с длиной каждого физического буфера.
  5. Как-то привязать виртуальный буфер к пользовательскому пространству.

Проблемы, которые я вижу при таком подходе:

  1. Вы не можете указать, сколько частей непрерывной памяти вам нужно, используя vmalloc, что может привести к получению большего, чем может принять устройство PCI, хотя мое устройство может принимать только 8192 адреса шины, не более.
  2. Я не нашел ничего на шаге 2) алгоритма, описанного выше, кроме этого , и он на самом деле не компилируется.
  3. ioremap используется для отображения физической памяти в ядре, remap_pfn_range - для отображения физической памяти в пространство пользователя с помощью операций MMAP. Они оба ожидают физический адрес в качестве параметра. Как мне сопоставить виртуальный адрес ядра с пользовательским пространством?

По сути, я думаю, что есть кое-что, чего я не понимаю, и я не могу найти небольшой хороший пример того, как сделать это правильно. Интернет полон справочных таблиц, списков рассылки и прочего, но каждый реальный пример - это проект, состоящий из тысяч файлов, которые очень трудно быстро прогнать для новичка. Для подхода, который я пытаюсь реализовать, мне кажется, что я пытаюсь решить проблему X / Y . Есть ли лучший способ сделать это?

РЕДАКТИРОВАТЬ : найдено это . Похоже, я не могу напрямую получить все физические адреса памяти, выделенные с помощью vmalloc. Что я должен использовать вместо этого?

РЕДАКТИРОВАТЬ 2 : Некоторые думают, что я могу вместо этого просто использовать CMA и вообще не беспокоиться о списках разброса - из-за определенных правил проекта я не могу пересобрать ядро, и оно собрано без Поддержка CMA по умолчанию. Мне нужно как-то выделить 3 порции памяти по 4 ГБ для работы моих устройств.

РЕДАКТИРОВАТЬ 3 : Я не знаю, поможет ли это кому-нибудь ... Не буду отвечать на вопросы, хотя бы до тех пор, пока не узнаю, что это работает.

В принципе, то, что у меня есть на данный момент, позволяет мне выделить 12 ГБ памяти без паники ядра (для этого требуется, чтобы ваше устройство поддерживало 64-битные адреса):

dma_set_mask_and_coherent(pdev, DMA_BIT_MASK(64));
dma_pool_create(...);
dma_pool_alloc(...) for as many chunks of memory as you need.

Теперь вопрос стоит, смогу ли я отобразить все эти фрагменты памяти и эффективно прокрутить их.

...