То, что вы делаете, действительно неправильно. Со страницы руководства для virt_to_phys()
:
Эта функция не дает сопоставления шины для передач DMA. Почти во всех возможных случаях драйвер устройства не должен использовать эту функцию.
Эквивалентная функция для адресов DMA: dma_to_phys()
, определенная в include/linux/dma-direct.h
следующим образом:
phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
Поэтому вы можете сделать:
dma_to_phys(&pcie->dev, bus_addr) >> PAGE_SHIFT;
Обратите внимание, что я использую bus_addr
, возвращаемое dma_alloc_coherent()
, а не buffer
, поскольку вам, очевидно, нужно пройти DMA адрес (dma_addr_t
) этой функции, а не виртуальный адрес.
Кажется также, что есть макрос PHYS_PFN()
, определенный в include/linux/pfn.h
для получения PFN для данного физического адрес, если вы предпочитаете использовать это:
PHYS_PFN(dma_to_phys(&pcie->dev, bus_addr));