From: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
To: Matthew Brost <matthew.brost@intel.com>
Cc: intel-xe@lists.freedesktop.org, dri-devel@lists.freedesktop.org,
"Carlos Santa" <carlos.santa@intel.com>,
"Ryan Neph" <ryanneph@google.com>,
"Christian Koenig" <christian.koenig@amd.com>,
"Huang Rui" <ray.huang@amd.com>,
"Matthew Auld" <matthew.auld@intel.com>,
"Maarten Lankhorst" <maarten.lankhorst@linux.intel.com>,
"Maxime Ripard" <mripard@kernel.org>,
"Thomas Zimmermann" <tzimmermann@suse.de>,
"David Airlie" <airlied@gmail.com>,
"Simona Vetter" <simona@ffwll.ch>,
linux-kernel@vger.kernel.org,
"Thomas Hellström" <thomas.hellstrom@linux.intel.com>
Subject: Re: [PATCH v3 31/33] drm/xe: Blit src-natural to dst-packed for defrag-IOVA copies
Date: Fri, 13 Nov 2026 17:57:40 -0800 [thread overview]
Message-ID: <avfAFMt0eQysdiq7@nvishwa1-desk> (raw)
In-Reply-To: <20260711025619.2540575-32-matthew.brost@intel.com>
On Fri, Jul 10, 2026 at 07:56:17PM -0700, Matthew Brost wrote:
>A defrag move with IOVA enabled only DMA-maps the changed (non-borrowed)
>pages of the new tt, packed contiguously into the front of its IOVA
>reservation (xe_tt_map_iova_copy()). The GPU copy therefore has an
>asymmetric geometry: the source is read from the old tt at its natural
>page offsets (via the old tt's full IOVA), while the destination only
>exposes the changed pages, packed.
>
>Teach __xe_migrate_copy() about this packed-destination mode:
>
>- Add a @dst_packed_pages argument. When non-zero the destination tt
> cursor walks just that many packed pages and the source (not the
> destination) drives the chunk size, so the smaller packed prefix never
> clamps the source walk.
>
>- Size the destination PTE update for each chunk from the changed-page
> count (xe_migrate_count_changed_pages()) rather than the full chunk,
> and skip the destination PTEs entirely for an all-borrowed chunk.
>
>- Extend emit_copy_chunks() with a @pack_dst flag so each emitted run is
> blitted from its natural source offset into a running packed
> destination offset that only advances for changed runs. The
> all-borrowed skip leaves the packed destination cursor untouched.
>
>Expose this via xe_migrate_copy_defrag_iova(). It is only valid when the
>BO needs no CCS pass, since the separate CCS pass migrates aux state for
>all pages and would require the full destination mapping. The existing
>xe_migrate_copy_defrag() (full destination mapping) remains the path for
>CCS BOs and the non-IOVA fallback.
>
>No users yet; xe_bo_move() is wired to this path in a later patch.
>
>Cc: Carlos Santa <carlos.santa@intel.com>
>Cc: Ryan Neph <ryanneph@google.com>
>Cc: Christian Koenig <christian.koenig@amd.com>
>Cc: Huang Rui <ray.huang@amd.com>
>Cc: Matthew Auld <matthew.auld@intel.com>
>Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>Cc: Maxime Ripard <mripard@kernel.org>
>Cc: Thomas Zimmermann <tzimmermann@suse.de>
>Cc: David Airlie <airlied@gmail.com>
>Cc: Simona Vetter <simona@ffwll.ch>
>Cc: dri-devel@lists.freedesktop.org
>Cc: linux-kernel@vger.kernel.org
>Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>Assisted-by: GitHub_Copilot:claude-opus-4.8
>Signed-off-by: Matthew Brost <matthew.brost@intel.com>
>---
> drivers/gpu/drm/xe/xe_migrate.c | 307 ++++++++++++++++++++++++++++++--
> drivers/gpu/drm/xe/xe_migrate.h | 8 +
> 2 files changed, 296 insertions(+), 19 deletions(-)
>
>diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
>index 666c715a9067..e1dc2fb5c5cb 100644
>--- a/drivers/gpu/drm/xe/xe_migrate.c
>+++ b/drivers/gpu/drm/xe/xe_migrate.c
>@@ -811,6 +811,64 @@ static void emit_copy(struct xe_gt *gt, struct xe_bb *bb,
> emit_xy_fast_copy(gt, bb, src_ofs, dst_ofs, size, pitch);
> }
>
>+/*
>+ * xe_migrate_count_changed_pages() - Count non-borrowed pages in a defrag chunk.
>+ * @src_tt: Source (old) tt providing the page pointers.
>+ * @dst_tt: Destination (new) tt providing the page pointers.
>+ * @start_page: Page offset of this L0 chunk within the tt page arrays.
>+ * @npages: Number of pages in the L0 chunk.
>+ *
>+ * A defragmentation move may harvest already beneficial-order chunks from the
>+ * old tt, so the new tt references (borrows) some of the same physical pages.
>+ * Count the pages that actually differ (src page != dst page) within the chunk.
>+ *
>+ * Return: The number of non-borrowed (changed) pages.
>+ */
>+static u32 xe_migrate_count_changed_pages(struct ttm_tt *src_tt,
>+ struct ttm_tt *dst_tt,
>+ pgoff_t start_page, u32 npages)
>+{
>+ u32 i, nchg = 0;
>+
>+ for (i = 0; i < npages; i++)
>+ if (src_tt->pages[start_page + i] !=
>+ dst_tt->pages[start_page + i])
>+ nchg++;
>+
>+ return nchg;
>+}
>+
>+/*
>+ * xe_migrate_leading_borrowed_pages() - Count the run of borrowed pages at the
>+ * head of the remaining copy.
>+ * @src_tt: Source (old) tt providing the page pointers.
>+ * @dst_tt: Destination (new) tt providing the page pointers.
>+ * @start_page: Page offset of the next page to copy within the tt page arrays.
>+ * @max_pages: Pages left to copy.
>+ *
>+ * A defragmentation move borrows the already beneficial-order chunks from the
>+ * old tt, so the new tt references (borrows) the same physical pages for the
>+ * unchanged majority of a large object. Those pages alias on both the source
>+ * and destination GPU mappings and need no copy. Count how many consecutive
>+ * pages starting at @start_page are borrowed so the caller can advance past the
>+ * whole run at once instead of rediscovering it one L0 chunk at a time.
>+ *
>+ * Return: The number of leading borrowed (src page == dst page) pages, capped
>+ * at @max_pages.
>+ */
>+static u32 xe_migrate_leading_borrowed_pages(struct ttm_tt *src_tt,
>+ struct ttm_tt *dst_tt,
>+ pgoff_t start_page, u32 max_pages)
>+{
>+ u32 n = 0;
>+
>+ while (n < max_pages &&
>+ src_tt->pages[start_page + n] == dst_tt->pages[start_page + n])
>+ n++;
>+
>+ return n;
>+}
>+
> /*
> * emit_copy_chunks() - Emit the data blits for one defrag L0 chunk, skipping
> * borrowed pages.
>@@ -822,6 +880,9 @@ static void emit_copy(struct xe_gt *gt, struct xe_bb *bb,
> * @src_tt: Source (old) tt providing the page pointers.
> * @dst_tt: Destination (new) tt providing the page pointers.
> * @start_page: Page offset of this L0 chunk within the tt page arrays.
>+ * @pack_dst: If true the destination only maps the changed pages packed
>+ * contiguously, so the destination offset advances by changed-page
>+ * runs instead of tracking the source page index.
> *
> * A defragmentation move may harvest already beneficial-order chunks from the
> * old tt, so the new tt references (borrows) some of the same physical pages.
>@@ -830,16 +891,21 @@ static void emit_copy(struct xe_gt *gt, struct xe_bb *bb,
> * only blit runs of pages that actually differ (src page != dst page),
> * coalescing contiguous to-copy pages into a single blit.
> *
>+ * When @pack_dst is set the source pages are read from their natural offsets
>+ * (@src_L0_ofs + page index) while the destination pages were packed into a
>+ * contiguous prefix, so the destination offset is a running counter that only
>+ * advances for emitted (changed) runs.
>+ *
> * Return: The number of blits emitted (or that would be emitted when @bb is
> * NULL).
> */
> static u32 emit_copy_chunks(struct xe_gt *gt, struct xe_bb *bb,
> u64 src_L0_ofs, u64 dst_L0_ofs, u32 src_L0,
> struct ttm_tt *src_tt, struct ttm_tt *dst_tt,
>- pgoff_t start_page)
>+ pgoff_t start_page, bool pack_dst)
> {
> u32 npages = src_L0 >> PAGE_SHIFT;
>- u32 i = 0, nblits = 0;
>+ u32 i = 0, pack = 0, nblits = 0;
>
> while (i < npages) {
> u32 run = 0;
>@@ -859,9 +925,71 @@ static u32 emit_copy_chunks(struct xe_gt *gt, struct xe_bb *bb,
>
> if (bb)
> emit_copy(gt, bb, src_L0_ofs + (u64)i * PAGE_SIZE,
>- dst_L0_ofs + (u64)i * PAGE_SIZE,
>+ dst_L0_ofs +
>+ (u64)(pack_dst ? pack : i) * PAGE_SIZE,
> run * PAGE_SIZE, XE_PAGE_SIZE);
> nblits++;
>+ pack += run;
>+ i += run;
>+ }
>+
>+ return nblits;
>+}
>+
>+/*
>+ * emit_ccs_copy_chunks() - Emit the indirect CCS aux copies for one packed
>+ * defrag L0 chunk, skipping borrowed pages.
>+ * @gt: The GT.
>+ * @bb: The batch buffer to emit into, or NULL to only count the copies needed.
>+ * @src_L0_ofs: GPU offset of the source pages mapped (comp PAT) for this chunk.
>+ * @dst_L0_ofs: GPU offset of the destination pages mapped (comp PAT) for this
>+ * chunk (the packed changed-page prefix).
>+ * @src_L0: Byte size of the L0 chunk (page aligned).
>+ * @src_tt: Source (old) tt providing the page pointers.
>+ * @dst_tt: Destination (new) tt providing the page pointers.
>+ * @start_page: Page offset of this L0 chunk within the tt page arrays.
>+ *
>+ * Companion to emit_copy_chunks() for the packed defrag CCS pass. The flat-CCS
>+ * aux state is migrated indirectly through the data-page mappings, so it
>+ * follows the physical page regardless of the (packed) GPU VA layout. Borrowed
>+ * pages alias the same physical page on both sides, so their aux is already
>+ * identical and is skipped; only the changed runs are copied, from the source
>+ * at its natural offset to the destination at its packed offset.
>+ *
>+ * Return: The number of CCS copies emitted (or that would be emitted when @bb
>+ * is NULL).
>+ */
>+static u32 emit_ccs_copy_chunks(struct xe_gt *gt, struct xe_bb *bb,
>+ u64 src_L0_ofs, u64 dst_L0_ofs, u32 src_L0,
>+ struct ttm_tt *src_tt, struct ttm_tt *dst_tt,
>+ pgoff_t start_page)
>+{
>+ u32 npages = src_L0 >> PAGE_SHIFT;
>+ u32 i = 0, pack = 0, nblits = 0;
>+
>+ while (i < npages) {
>+ u32 run = 0;
>+
>+ /* Skip a run of borrowed pages (src and dst alias). */
>+ if (src_tt->pages[start_page + i] ==
>+ dst_tt->pages[start_page + i]) {
>+ i++;
>+ continue;
>+ }
>+
>+ /* Coalesce a run of pages whose aux must be migrated. */
>+ while (i + run < npages &&
>+ src_tt->pages[start_page + i + run] !=
>+ dst_tt->pages[start_page + i + run])
>+ run++;
>+
>+ if (bb)
>+ emit_copy_ccs(gt, bb,
>+ dst_L0_ofs + (u64)pack * PAGE_SIZE, true,
>+ src_L0_ofs + (u64)i * PAGE_SIZE, true,
>+ run * PAGE_SIZE);
>+ nblits++;
>+ pack += run;
> i += run;
> }
>
>@@ -949,6 +1077,7 @@ static struct dma_fence *__xe_migrate_copy(struct xe_migrate *m,
> struct ttm_resource *src,
> struct ttm_resource *dst,
> struct ttm_tt *src_tt,
>+ pgoff_t dst_packed_pages,
> struct xe_migrate_copy_flags flags)
> {
> struct xe_gt *gt = m->tile->primary_gt;
>@@ -981,6 +1110,23 @@ static struct dma_fence *__xe_migrate_copy(struct xe_migrate *m,
> */
> struct ttm_tt *dst_tt = dst_bo->ttm.ttm;
> bool skip_borrowed = flags.defrag_copy && src_tt && dst_tt;
>+ /*
>+ * Defrag-IOVA copy: the destination tt only maps the changed
>+ * (non-borrowed) pages, packed contiguously into the first
>+ * @dst_packed_pages pages of its IOVA. The source is read from the old
>+ * tt at natural offsets and each changed run is blitted into the packed
>+ * destination prefix.
>+ */
>+ bool pack_dst = dst_packed_pages != 0;
>+ /*
>+ * Packed defrag CCS pass: migrate the flat-CCS aux state of the changed
>+ * pages only, from the source at its natural offset to the destination
>+ * packed prefix. Borrowed pages share the physical page (and thus its
>+ * aux) on both sides, so they are skipped exactly like the data pass.
>+ */
>+ bool ccs_pack = flags.defrag_ccs && pack_dst && src_tt && dst_tt;
>+ /* Per-run, borrowed-skipping defrag emission (data or packed CCS). */
>+ bool defrag_runs = skip_borrowed || ccs_pack;
>
> /*
> * For decompression operation, always use the compression PAT index.
>@@ -1009,7 +1155,9 @@ static struct dma_fence *__xe_migrate_copy(struct xe_migrate *m,
> else
> xe_res_first(src, 0, size, &src_it);
> if (!dst_is_vram)
>- xe_res_first_tt(dst_bo->ttm.ttm, 0, size, &dst_it);
>+ xe_res_first_tt(dst_bo->ttm.ttm, 0,
>+ pack_dst ? (u64)dst_packed_pages << PAGE_SHIFT :
>+ size, &dst_it);
> else
> xe_res_first(dst, 0, size, &dst_it);
>
>@@ -1030,29 +1178,86 @@ static struct dma_fence *__xe_migrate_copy(struct xe_migrate *m,
> u32 pte_flags;
> pgoff_t start_page = (xe_bo_size(src_bo) - size) >> PAGE_SHIFT;
> u32 ndata_blits = 1;
>+ u32 nchg = 0;
>+ u64 dst_size;
>
> bool usm = xe->info.has_usm;
> u32 avail_pts = max_mem_transfer_per_pass(xe) / LEVEL0_PAGE_TABLE_ENCODE_SIZE;
>
>+ /*
>+ * Defrag fast-forward: the new (destination) tt borrows the
>+ * unchanged beneficial-order chunks from the old tt, so for a
>+ * large object the bulk of the copy is borrowed pages that alias
>+ * the same memory on both sides. Skip the entire leading
>+ * borrowed run in a single cursor stride rather than discovering
>+ * it one (8 MB) L0 chunk at a time - each such pass would
>+ * otherwise pay xe_migrate_res_sizes() + pte_update_size() + a
>+ * full chunk walk only to copy nothing. The non-vram tt cursors
>+ * are normally advanced by emit_pte(); replicate that with
>+ * xe_res_next(). In pack_dst mode the destination only maps the
>+ * changed pages, so its cursor must not advance for borrowed
>+ * pages.
>+ */
>+ if (defrag_runs) {
>+ u32 brun = xe_migrate_leading_borrowed_pages(src_tt,
>+ dst_tt,
>+ start_page,
>+ size >> PAGE_SHIFT);
>+
>+ if (brun) {
>+ u64 brun_bytes = (u64)brun << PAGE_SHIFT;
>+
>+ xe_res_next(&src_it, brun_bytes);
>+ if (!pack_dst)
>+ xe_res_next(&dst_it, brun_bytes);
>+ size -= brun_bytes;
>+ continue;
>+ }
>+ }
>+
> src_L0 = xe_migrate_res_sizes(m, &src_it);
> dst_L0 = xe_migrate_res_sizes(m, &dst_it);
>
> drm_dbg(&xe->drm, "Pass %u, sizes: %llu & %llu\n",
> pass++, src_L0, dst_L0);
>
Assisted-by: LLM
With above 'continue', this drm_dbg never gets printed, is that fine?
>- src_L0 = min(src_L0, dst_L0);
>+ /*
>+ * In pack_dst mode the destination is the (smaller) packed
>+ * prefix, so it must not clamp the source chunk size; the
>+ * source drives the walk and the destination is sized
>+ * independently from the changed-page count below.
>+ */
>+ if (!pack_dst)
>+ src_L0 = min(src_L0, dst_L0);
>
> pte_flags = src_is_vram ? PTE_UPDATE_FLAG_IS_VRAM : 0;
> pte_flags |= use_comp_pat ? PTE_UPDATE_FLAG_IS_COMP_PTE : 0;
> batch_size += pte_update_size(m, pte_flags, src, &src_it, &src_L0,
> &src_L0_ofs, &src_L0_pt, 0, 0,
> avail_pts);
>+ /*
>+ * The source chunk size may have been clamped above, so derive
>+ * the packed destination size from the changed-page count of
>+ * the final chunk.
>+ */
>+ if (pack_dst) {
>+ nchg = xe_migrate_count_changed_pages(src_tt, dst_tt,
>+ start_page,
>+ src_L0 >> PAGE_SHIFT);
>+ dst_size = (u64)nchg << PAGE_SHIFT;
>+ } else {
>+ dst_size = src_L0;
>+ }
> if (flags.copy_only_ccs) {
> dst_L0_ofs = src_L0_ofs;
>+ } else if (pack_dst && !nchg) {
>+ /* All borrowed: no destination PTEs for this chunk. */
>+ dst_L0_ofs = 0;
>+ dst_L0_pt = 0;
> } else {
> pte_flags = dst_is_vram ? PTE_UPDATE_FLAG_IS_VRAM : 0;
> batch_size += pte_update_size(m, pte_flags, dst,
>- &dst_it, &src_L0,
>+ &dst_it, &dst_size,
> &dst_L0_ofs, &dst_L0_pt,
> 0, avail_pts, avail_pts);
> }
>@@ -1072,26 +1277,31 @@ static struct dma_fence *__xe_migrate_copy(struct xe_migrate *m,
> * is split into one command per run of non-borrowed pages, so
> * size for the number of runs actually needed.
> */
>- if (skip_borrowed)
>+ if (defrag_runs)
> ndata_blits = emit_copy_chunks(gt, NULL, 0, 0, src_L0,
>- src_tt, dst_tt, start_page);
>+ src_tt, dst_tt, start_page,
>+ pack_dst);
>
> /*
> * If every page in this chunk was borrowed there is nothing to
> * copy: don't build a batch or issue any GPU commands, just
> * advance the cursors past the chunk. The non-vram tt cursors
>- * would otherwise be advanced by emit_pte().
>+ * would otherwise be advanced by emit_pte(). In pack_dst mode
>+ * the destination consumed no packed pages, so leave its cursor
>+ * untouched.
> */
>- if (skip_borrowed && !ndata_blits) {
>+ if (defrag_runs && !ndata_blits) {
LLM says this 'if' clause is dead code now as defrag_runs will
always have non-zero ndata_blits.
> xe_res_next(&src_it, src_L0);
>- xe_res_next(&dst_it, src_L0);
>+ if (!pack_dst)
>+ xe_res_next(&dst_it, src_L0);
> size -= src_L0;
> continue;
> }
>
> batch_size += ((flags.copy_only_ccs || flags.defrag_ccs) ? 0 :
> ndata_blits * emit_copy_cmd_len(xe)) +
>- ((needs_ccs_emit ? EMIT_COPY_CCS_DW : 0));
>+ (ccs_pack ? ndata_blits * EMIT_COPY_CCS_DW :
>+ (needs_ccs_emit ? EMIT_COPY_CCS_DW : 0));
We are using ndata_blits returned from emit_copy_chunks to find calculate
the batch size for ccs part. Though it might work, shouldn't we be getting
that from emit_ccs_copy_chunks() with 'bb' set to NULL?
Niranjana
>
> bb = xe_bb_new(gt, batch_size, usm);
> if (IS_ERR(bb)) {
>@@ -1111,7 +1321,7 @@ static struct dma_fence *__xe_migrate_copy(struct xe_migrate *m,
> else if (!flags.copy_only_ccs)
> emit_pte(m, bb, dst_L0_pt, dst_is_vram,
> copy_system_ccs || flags.defrag_ccs,
>- &dst_it, src_L0, dst);
>+ &dst_it, dst_size, dst);
>
> if (copy_system_ccs)
> emit_pte(m, bb, ccs_pt, false, false, &ccs_it, ccs_size, src);
>@@ -1121,16 +1331,22 @@ static struct dma_fence *__xe_migrate_copy(struct xe_migrate *m,
>
> if (skip_borrowed)
> emit_copy_chunks(gt, bb, src_L0_ofs, dst_L0_ofs, src_L0,
>- src_tt, dst_tt, start_page);
>+ src_tt, dst_tt, start_page, pack_dst);
> else if (!flags.copy_only_ccs && !flags.defrag_ccs)
> emit_copy(gt, bb, src_L0_ofs, dst_L0_ofs, src_L0, XE_PAGE_SIZE);
>
>- if (needs_ccs_emit)
>+ if (ccs_pack) {
>+ if (emit_ccs_copy_chunks(gt, bb, src_L0_ofs, dst_L0_ofs,
>+ src_L0, src_tt, dst_tt,
>+ start_page))
>+ flush_flags = MI_FLUSH_DW_CCS;
>+ } else if (needs_ccs_emit) {
> flush_flags = xe_migrate_ccs_copy(m, bb, src_L0_ofs,
> IS_DGFX(xe) ? src_is_vram : src_is_pltt,
> dst_L0_ofs,
> IS_DGFX(xe) ? dst_is_vram : dst_is_pltt,
> src_L0, ccs_ofs, copy_ccs);
>+ }
>
> job = xe_bb_create_migration_job(m->q, bb,
> xe_migrate_batch_base(m, usm),
>@@ -1218,7 +1434,7 @@ struct dma_fence *xe_migrate_copy(struct xe_migrate *m,
> struct ttm_resource *dst,
> bool copy_only_ccs)
> {
>- return __xe_migrate_copy(m, src_bo, dst_bo, src, dst, NULL,
>+ return __xe_migrate_copy(m, src_bo, dst_bo, src, dst, NULL, 0,
> (struct xe_migrate_copy_flags) {
> .copy_only_ccs = copy_only_ccs,
> });
>@@ -1267,7 +1483,7 @@ struct dma_fence *xe_migrate_copy_defrag(struct xe_migrate *m,
> bool need_ccs)
> {
> struct dma_fence *fence2, *fence =
>- __xe_migrate_copy(m, bo, bo, src, dst, src_tt,
>+ __xe_migrate_copy(m, bo, bo, src, dst, src_tt, 0,
> (struct xe_migrate_copy_flags) {
> .defrag_copy = true,
> });
>@@ -1275,7 +1491,7 @@ struct dma_fence *xe_migrate_copy_defrag(struct xe_migrate *m,
> if (IS_ERR(fence) || !need_ccs)
> return fence;
>
>- fence2 = __xe_migrate_copy(m, bo, bo, src, dst, src_tt,
>+ fence2 = __xe_migrate_copy(m, bo, bo, src, dst, src_tt, 0,
> (struct xe_migrate_copy_flags) {
> .defrag_ccs = true,
> });
>@@ -1286,6 +1502,59 @@ struct dma_fence *xe_migrate_copy_defrag(struct xe_migrate *m,
> return fence2;
> }
>
>+/**
>+ * xe_migrate_copy_defrag_iova() - Copy a defrag move into a packed IOVA dst.
>+ * @m: The migration context.
>+ * @bo: The buffer object being defragmented.
>+ * @src: The source (old) TTM resource.
>+ * @dst: The destination (new) TTM resource.
>+ * @src_tt: The stashed source (old) tt providing the page pointers, fully
>+ * IOVA-mapped at natural offsets.
>+ * @dst_packed_pages: Number of changed pages packed into the destination tt's
>+ * IOVA prefix by xe_tt_map_iova_copy().
>+ * @need_ccs: Whether the BO has flat-CCS aux state that must be migrated too.
>+ *
>+ * Defrag copy variant for IOVA-mapped BOs where the destination only maps the
>+ * changed (non-borrowed) pages, packed contiguously into the first
>+ * @dst_packed_pages of its IOVA. The source is read from the old tt at its
>+ * natural offsets and each changed run is blitted into the packed destination
>+ * prefix. When @need_ccs is set a second pass migrates the flat-CCS aux state
>+ * of the same changed pages indirectly through their (packed) data mappings;
>+ * borrowed pages share the physical page and its aux, so only the changed runs
>+ * are touched.
>+ *
>+ * Return: Pointer to a dma_fence representing the last copy batch, or an error
>+ * pointer on failure.
>+ */
>+struct dma_fence *xe_migrate_copy_defrag_iova(struct xe_migrate *m,
>+ struct xe_bo *bo,
>+ struct ttm_resource *src,
>+ struct ttm_resource *dst,
>+ struct ttm_tt *src_tt,
>+ pgoff_t dst_packed_pages,
>+ bool need_ccs)
>+{
>+ struct dma_fence *fence2, *fence =
>+ __xe_migrate_copy(m, bo, bo, src, dst, src_tt, dst_packed_pages,
>+ (struct xe_migrate_copy_flags) {
>+ .defrag_copy = true,
>+ });
>+
>+ if (IS_ERR(fence) || !need_ccs)
>+ return fence;
>+
>+ fence2 = __xe_migrate_copy(m, bo, bo, src, dst, src_tt,
>+ dst_packed_pages,
>+ (struct xe_migrate_copy_flags) {
>+ .defrag_ccs = true,
>+ });
>+ if (IS_ERR(fence2))
>+ dma_fence_wait(fence, false);
>+ dma_fence_put(fence);
>+
>+ return fence2;
>+}
>+
> /**
> * xe_migrate_resolve() - Resolve and decompress a buffer object if required.
> * @m: The migrate context
>@@ -1301,7 +1570,7 @@ struct dma_fence *xe_migrate_resolve(struct xe_migrate *m,
> struct xe_bo *bo,
> struct ttm_resource *res)
> {
>- return __xe_migrate_copy(m, bo, bo, res, res, NULL,
>+ return __xe_migrate_copy(m, bo, bo, res, res, NULL, 0,
> (struct xe_migrate_copy_flags) {
> .is_vram_resolve = true,
> });
>diff --git a/drivers/gpu/drm/xe/xe_migrate.h b/drivers/gpu/drm/xe/xe_migrate.h
>index 4094ea1c19c1..da066cdf01bf 100644
>--- a/drivers/gpu/drm/xe/xe_migrate.h
>+++ b/drivers/gpu/drm/xe/xe_migrate.h
>@@ -141,6 +141,14 @@ struct dma_fence *xe_migrate_copy_defrag(struct xe_migrate *m,
> struct ttm_tt *src_tt,
> bool need_ccs);
>
>+struct dma_fence *xe_migrate_copy_defrag_iova(struct xe_migrate *m,
>+ struct xe_bo *bo,
>+ struct ttm_resource *src,
>+ struct ttm_resource *dst,
>+ struct ttm_tt *src_tt,
>+ pgoff_t dst_packed_pages,
>+ bool need_ccs);
>+
> struct dma_fence *xe_migrate_resolve(struct xe_migrate *m,
> struct xe_bo *bo,
> struct ttm_resource *res);
>--
>2.34.1
>
next prev parent reply other threads:[~2026-11-14 1:59 UTC|newest]
Thread overview: 74+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-11 2:55 [PATCH v3 00/33] drm/ttm, drm/xe: Minimize dma-resv hold times and defragment sub-optimally backed BOs Matthew Brost
2026-07-11 2:55 ` [PATCH v3 01/33] drm/ttm/pool: Allow backing off reclaim at the beneficial order Matthew Brost
2026-11-06 2:55 ` Niranjana Vishwanathapura
2026-07-11 2:55 ` [PATCH v3 02/33] drm/ttm/pool: Add ttm_pool_page_order_nodma() helper Matthew Brost
2026-11-05 11:27 ` Matthew Auld
2026-11-06 2:30 ` Niranjana Vishwanathapura
2026-07-11 2:55 ` [PATCH v3 03/33] drm/ttm: Record sub-optimal page order allocations in ttm_tt Matthew Brost
2026-11-06 2:34 ` Niranjana Vishwanathapura
2026-11-06 20:06 ` Matthew Brost
2026-07-11 2:55 ` [PATCH v3 04/33] drm/ttm: Introduce ttm_pool_alloc_iter for __ttm_pool_alloc() Matthew Brost
2026-11-06 2:39 ` Niranjana Vishwanathapura
2026-07-11 2:55 ` [PATCH v3 05/33] drm/ttm: Support defragmentation moves Matthew Brost
2026-11-06 2:51 ` Niranjana Vishwanathapura
2026-07-11 2:55 ` [PATCH v3 06/33] drm/ttm: Add fault injection for beneficial-order allocation failures Matthew Brost
2026-11-06 2:54 ` Niranjana Vishwanathapura
2026-07-11 2:55 ` [PATCH v3 07/33] drm/ttm: Harvest beneficial-order pages on defragmentation moves Matthew Brost
2026-11-10 2:37 ` Niranjana Vishwanathapura
2026-07-11 2:55 ` [PATCH v3 08/33] drm/ttm: Bound page (re)allocation per defragmentation move Matthew Brost
2026-11-10 2:44 ` Niranjana Vishwanathapura
2026-07-11 2:55 ` [PATCH v3 09/33] drm/ttm: Preallocate beneficial-order defrag pages outside the lock Matthew Brost
2026-11-11 0:29 ` Niranjana Vishwanathapura
2026-11-11 7:49 ` Niranjana Vishwanathapura
2026-07-11 2:55 ` [PATCH v3 10/33] drm/ttm: Add full out-of-lock preallocation for ttm_pool_alloc() Matthew Brost
2026-11-11 7:31 ` Niranjana Vishwanathapura
2026-07-11 2:56 ` [PATCH v3 15/33] drm/xe: Track BOs backed at a sub-optimal page order Matthew Brost
2026-11-07 4:49 ` Niranjana Vishwanathapura
2026-07-11 2:56 ` [PATCH v3 16/33] drm/xe: Back off beneficial-order reclaim under defrag pressure Matthew Brost
2026-11-07 5:02 ` Niranjana Vishwanathapura
2026-07-11 2:56 ` [PATCH v3 17/33] drm/xe: Add xe_migrate_copy_defrag() for on-GPU defrag copies Matthew Brost
2026-11-03 12:58 ` Matthew Auld
2026-11-03 20:08 ` Matthew Brost
2026-11-04 12:37 ` Matthew Auld
2026-11-07 5:07 ` Niranjana Vishwanathapura
2026-07-11 2:56 ` [PATCH v3 18/33] drm/xe: Handle defrag moves in xe_bo_move() Matthew Brost
2026-11-07 5:12 ` Niranjana Vishwanathapura
2026-07-11 2:56 ` [PATCH v3 19/33] drm/xe: Skip self-copies for borrowed pages on defrag moves Matthew Brost
2026-11-10 4:25 ` Niranjana Vishwanathapura
2026-07-11 2:56 ` [PATCH v3 20/33] drm/xe: Add a page defragmentation worker Matthew Brost
2026-11-07 5:27 ` Niranjana Vishwanathapura
2026-07-11 2:56 ` [PATCH v3 21/33] drm/xe: Add defrag GT stats Matthew Brost
2026-11-09 1:10 ` Niranjana Vishwanathapura
2026-07-11 2:56 ` [PATCH v3 22/33] drm/xe: Add Kconfig.profile options for BO defrag configuration Matthew Brost
2026-11-09 1:31 ` Niranjana Vishwanathapura
2026-07-11 2:56 ` [PATCH v3 23/33] drm/xe: Defrag using out-of-lock page preallocation Matthew Brost
2026-11-11 0:39 ` Niranjana Vishwanathapura
2026-07-11 2:56 ` [PATCH v3 24/33] drm/xe: Add defrag profiling tracepoints Matthew Brost
2026-11-09 4:34 ` Niranjana Vishwanathapura
2026-07-11 2:56 ` [PATCH v3 25/33] drm/xe: Preallocate system BO backing outside the dma-resv lock Matthew Brost
2026-11-11 7:36 ` Niranjana Vishwanathapura
2026-07-11 2:56 ` [PATCH v3 26/33] drm/xe: Add tracepoint for xe_gem_create_ioctl Matthew Brost
2026-11-11 7:37 ` Niranjana Vishwanathapura
2026-07-11 2:56 ` [PATCH v3 27/33] drm/xe: Add IOVA-based xe_res_cursor variant Matthew Brost
2026-11-04 12:23 ` Matthew Auld
2026-11-13 6:14 ` Niranjana Vishwanathapura
2026-07-11 2:56 ` [PATCH v3 28/33] drm/xe: Use IOVA-based DMA mapping for eligible tt BOs Matthew Brost
2026-11-03 19:00 ` Matthew Auld
2026-11-03 20:21 ` Matthew Brost
2026-11-04 11:39 ` Matthew Auld
2026-11-05 3:04 ` Matthew Brost
2026-11-13 6:28 ` Niranjana Vishwanathapura
2026-11-13 20:09 ` Matthew Brost
2026-07-11 2:56 ` [PATCH v3 29/33] drm/xe: Add per-device dependency scheduler for IOVA defrag finalize Matthew Brost
2026-11-14 1:47 ` Niranjana Vishwanathapura
2026-07-11 2:56 ` [PATCH v3 30/33] drm/xe: Add packed copy-step IOVA mapping for defrag Matthew Brost
2026-11-14 1:52 ` Niranjana Vishwanathapura
2026-07-11 2:56 ` [PATCH v3 31/33] drm/xe: Blit src-natural to dst-packed for defrag-IOVA copies Matthew Brost
2026-11-14 1:57 ` Niranjana Vishwanathapura [this message]
2026-07-11 2:56 ` [PATCH v3 32/33] drm/xe: Finalize defrag-IOVA moves with post-copy job Matthew Brost
2026-11-14 2:02 ` Niranjana Vishwanathapura
2026-07-11 2:56 ` [PATCH v3 33/33] drm/amdgpu: Preallocate system BO pages outside the reservation lock Matthew Brost
2026-07-11 10:46 ` Christian König
2026-07-13 20:24 ` Matthew Brost
2026-07-14 9:17 ` Christian König
2026-07-14 15:15 ` Matthew Brost
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=avfAFMt0eQysdiq7@nvishwa1-desk \
--to=niranjana.vishwanathapura@intel.com \
--cc=airlied@gmail.com \
--cc=carlos.santa@intel.com \
--cc=christian.koenig@amd.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=intel-xe@lists.freedesktop.org \
--cc=linux-kernel@vger.kernel.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=matthew.auld@intel.com \
--cc=matthew.brost@intel.com \
--cc=mripard@kernel.org \
--cc=ray.huang@amd.com \
--cc=ryanneph@google.com \
--cc=simona@ffwll.ch \
--cc=thomas.hellstrom@linux.intel.com \
--cc=tzimmermann@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®