Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

vfio: Wait for dma-buf invalidation to complete

dma-buf invalidation is handled asynchronously by the hardware, so VFIO
must wait until all affected objects have been fully invalidated.

In addition, the dma-buf exporter is expecting that all importers unmap any
buffers they previously mapped.

Fixes: 5d74781ebc86 ("vfio/pci: Add dma-buf export support for MMIO regions")
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Alex Williamson <alex@shazbot.org>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Christian König <christian.koenig@amd.com>
Link: https://lore.kernel.org/r/20260131-dmabuf-revoke-v7-4-463d956bd527@nvidia.com

authored by

Leon Romanovsky and committed by
Christian König
1a8a5227 a408c0ca

+57 -4
+57 -4
drivers/vfio/pci/vfio_pci_dmabuf.c
··· 17 17 struct phys_vec *phys_vec; 18 18 struct p2pdma_provider *provider; 19 19 u32 nr_ranges; 20 + struct kref kref; 21 + struct completion comp; 20 22 u8 revoked : 1; 21 23 }; 22 24 ··· 46 44 return 0; 47 45 } 48 46 47 + static void vfio_pci_dma_buf_done(struct kref *kref) 48 + { 49 + struct vfio_pci_dma_buf *priv = 50 + container_of(kref, struct vfio_pci_dma_buf, kref); 51 + 52 + complete(&priv->comp); 53 + } 54 + 49 55 static struct sg_table * 50 56 vfio_pci_dma_buf_map(struct dma_buf_attachment *attachment, 51 57 enum dma_data_direction dir) 52 58 { 53 59 struct vfio_pci_dma_buf *priv = attachment->dmabuf->priv; 60 + struct sg_table *ret; 54 61 55 62 dma_resv_assert_held(priv->dmabuf->resv); 56 63 57 64 if (priv->revoked) 58 65 return ERR_PTR(-ENODEV); 59 66 60 - return dma_buf_phys_vec_to_sgt(attachment, priv->provider, 61 - priv->phys_vec, priv->nr_ranges, 62 - priv->size, dir); 67 + ret = dma_buf_phys_vec_to_sgt(attachment, priv->provider, 68 + priv->phys_vec, priv->nr_ranges, 69 + priv->size, dir); 70 + if (IS_ERR(ret)) 71 + return ret; 72 + 73 + kref_get(&priv->kref); 74 + return ret; 63 75 } 64 76 65 77 static void vfio_pci_dma_buf_unmap(struct dma_buf_attachment *attachment, 66 78 struct sg_table *sgt, 67 79 enum dma_data_direction dir) 68 80 { 81 + struct vfio_pci_dma_buf *priv = attachment->dmabuf->priv; 82 + 83 + dma_resv_assert_held(priv->dmabuf->resv); 84 + 69 85 dma_buf_free_sgt(attachment, sgt, dir); 86 + kref_put(&priv->kref, vfio_pci_dma_buf_done); 70 87 } 71 88 72 89 static void vfio_pci_dma_buf_release(struct dma_buf *dmabuf) ··· 307 286 goto err_dev_put; 308 287 } 309 288 289 + kref_init(&priv->kref); 290 + init_completion(&priv->comp); 291 + 310 292 /* dma_buf_put() now frees priv */ 311 293 INIT_LIST_HEAD(&priv->dmabufs_elm); 312 294 down_write(&vdev->memory_lock); ··· 354 330 355 331 if (priv->revoked != revoked) { 356 332 dma_resv_lock(priv->dmabuf->resv, NULL); 357 - priv->revoked = revoked; 333 + if (revoked) 334 + priv->revoked = true; 358 335 dma_buf_invalidate_mappings(priv->dmabuf); 336 + dma_resv_wait_timeout(priv->dmabuf->resv, 337 + DMA_RESV_USAGE_BOOKKEEP, false, 338 + MAX_SCHEDULE_TIMEOUT); 359 339 dma_resv_unlock(priv->dmabuf->resv); 340 + if (revoked) { 341 + kref_put(&priv->kref, vfio_pci_dma_buf_done); 342 + wait_for_completion(&priv->comp); 343 + } else { 344 + /* 345 + * Kref is initialize again, because when revoke 346 + * was performed the reference counter was decreased 347 + * to zero to trigger completion. 348 + */ 349 + kref_init(&priv->kref); 350 + /* 351 + * There is no need to wait as no mapping was 352 + * performed when the previous status was 353 + * priv->revoked == true. 354 + */ 355 + reinit_completion(&priv->comp); 356 + dma_resv_lock(priv->dmabuf->resv, NULL); 357 + priv->revoked = false; 358 + dma_resv_unlock(priv->dmabuf->resv); 359 + } 360 360 } 361 361 fput(priv->dmabuf->file); 362 362 } ··· 401 353 priv->vdev = NULL; 402 354 priv->revoked = true; 403 355 dma_buf_invalidate_mappings(priv->dmabuf); 356 + dma_resv_wait_timeout(priv->dmabuf->resv, 357 + DMA_RESV_USAGE_BOOKKEEP, false, 358 + MAX_SCHEDULE_TIMEOUT); 404 359 dma_resv_unlock(priv->dmabuf->resv); 360 + kref_put(&priv->kref, vfio_pci_dma_buf_done); 361 + wait_for_completion(&priv->comp); 405 362 vfio_device_put_registration(&vdev->vdev); 406 363 fput(priv->dmabuf->file); 407 364 }