Implement get_pfn() callback for exported MMIO resources. Signed-off-by: Xu Yilun <yilun.xu@xxxxxxxxxxxxxxx> --- drivers/vfio/pci/dma_buf.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/vfio/pci/dma_buf.c b/drivers/vfio/pci/dma_buf.c index 1d5f46744922..ad12cfb85099 100644 --- a/drivers/vfio/pci/dma_buf.c +++ b/drivers/vfio/pci/dma_buf.c @@ -33,8 +33,34 @@ static int vfio_pci_dma_buf_pin(struct dma_buf_attachment *attachment) static int vfio_pci_dma_buf_get_pfn(struct dma_buf_attachment *attachment, pgoff_t pgoff, u64 *pfn, int *max_order) { - /* TODO */ - return -EOPNOTSUPP; + struct vfio_pci_dma_buf *priv = attachment->dmabuf->priv; + struct vfio_region_dma_range *dma_ranges = priv->dma_ranges; + u64 offset = pgoff << PAGE_SHIFT; + int i; + + dma_resv_assert_held(priv->dmabuf->resv); + + if (priv->revoked) + return -ENODEV; + + if (offset >= priv->dmabuf->size) + return -EINVAL; + + for (i = 0; i < priv->nr_ranges; i++) { + if (offset < dma_ranges[i].length) + break; + + offset -= dma_ranges[i].length; + } + + *pfn = PHYS_PFN(pci_resource_start(priv->vdev->pdev, dma_ranges[i].region_index) + + dma_ranges[i].offset + offset); + + /* TODO: large page mapping is yet to be supported */ + if (max_order) + *max_order = 0; + + return 0; } static void vfio_pci_dma_buf_release(struct dma_buf *dmabuf) -- 2.25.1