Re: [PATCH v3 28/33] drm/xe: Use IOVA-based DMA mapping for eligible tt BOs

From: Matthew Brost

Date: Tue Nov 03 2026 - 15:21:41 EST


On Tue, Nov 03, 2026 at 07:00:24PM +0000, Matthew Auld wrote:
> On 11/07/2026 03:56, Matthew Brost wrote:
> > Add support for mapping a ttm_tt's pages using the IOVA-based DMA API
> > (dma_iova_try_alloc()/link()/sync()/unlink()/free()) as an alternative
> > to the scatter-gather list. An IOVA mapping is a single contiguous DMA
> > range, which is cheaper to walk and program than an sg list.
> >
> > Whether the IOVA API can be used depends on the IOMMU mode, so the
> > decision is made once per tt at xe_ttm_tt_create() time and recorded in
> > struct xe_ttm_tt::use_iova. To keep the scope limited, only device BOs
> > that are not GGTT-mapped are eligible: dma-buf imports manage their own
> > mapping and GGTT bindings are programmed directly from the sg list.
> > dma_iova_try_alloc() may still fail, in which case the tt transparently
> > falls back to the sg list, which remains the default.
> >
> > The IOVA reservation is allocated at tt creation and freed at tt
> > destroy. xe_tt_map_iova() links the tt pages (coalescing physically
> > contiguous runs) and syncs the IOTLB; xe_tt_unmap_iova() unlinks them
> > but keeps the reservation so the tt can be remapped without
> > re-allocating IOVA space. xe_tt_map()/xe_tt_unmap() dispatch between the
> > IOVA and sg backends, and xe_bo_dma_unmap_pinned() learns about the IOVA
> > case.
> >
> > Consumers that walked the sg list via xe_res_first_sg(xe_bo_sg()) now go
> > through the new xe_res_first_tt() helper, which initializes either an
> > IOVA cursor (xe_res_first_iova()) or an sg cursor depending on the tt's
> > mapping mode.
> >
> > Cc: Carlos Santa <carlos.santa@xxxxxxxxx>
> > Cc: Ryan Neph <ryanneph@xxxxxxxxxx>
> > Cc: Christian Koenig <christian.koenig@xxxxxxx>
> > Cc: Huang Rui <ray.huang@xxxxxxx>
> > Cc: Matthew Auld <matthew.auld@xxxxxxxxx>
> > Cc: Maarten Lankhorst <maarten.lankhorst@xxxxxxxxxxxxxxx>
> > Cc: Maxime Ripard <mripard@xxxxxxxxxx>
> > Cc: Thomas Zimmermann <tzimmermann@xxxxxxx>
> > Cc: David Airlie <airlied@xxxxxxxxx>
> > Cc: Simona Vetter <simona@xxxxxxxx>
> > Cc: dri-devel@xxxxxxxxxxxxxxxxxxxxx
> > Cc: linux-kernel@xxxxxxxxxxxxxxx
> > Cc: Thomas Hellström <thomas.hellstrom@xxxxxxxxxxxxxxx>
> > Assisted-by: GitHub_Copilot:claude-opus-4.8
> > Signed-off-by: Matthew Brost <matthew.brost@xxxxxxxxx>
>
>
> <snip>
>
> > static void xe_ttm_tt_destroy(struct ttm_device *ttm_dev, struct ttm_tt *tt)
> > {
> > + struct xe_ttm_tt *xe_tt = container_of(tt, struct xe_ttm_tt, ttm);
> > +
> > + /*
> > + * Release the IOVA reservation made in xe_ttm_tt_create(). The pages
> > + * must already have been unlinked by xe_tt_unmap().
> > + */
> > + if (xe_tt->use_iova) {
> > + struct xe_device *xe = ttm_to_xe_device(ttm_dev);
> > +
> > + xe_assert(xe, !xe_tt->iova_linked);
> > + dma_iova_free(xe->drm.dev, &xe_tt->iova);
>
> Do we know if this is allowed? I think there is xe_bo_pci_dev_remove_all()
> which requires that evict_all will correctly tear down iommu mappings on
> stuff like pci unplug and I don't think tt_destroy is called in that flow?

But unpopulate is called which unlinks / syncs (TLB flush for the IOVA).

> Does having the iova here cause issues? Also, for VRAM flow I think there is
> a tt_create() via pipeline gutting which will now create a new iova?
>

Maybe we shuffle this around a bit so the iova alloc is tied to
populate/unpopulate. It was been a while I forget exactly why I did this
way.

> Aside from that, maybe we can land 27/28 as standalone?

Yes, let me extract these two into standalone patches today and
reworking if needed.

Matt