From: Jan Maslak <jan.maslak@intel.com>
To: intel-xe@lists.freedesktop.org
Cc: matthew.auld@intel.com, matthew.brost@intel.com,
thomas.hellstrom@linux.intel.com, rodrigo.vivi@intel.com,
Jan Maslak <jan.maslak@intel.com>,
Christoph Manszewski <christoph.manszewski@intel.com>
Subject: [PATCH v3 3/4] drm/xe/xe_migrate: Optimize unaligned access_memory copies
Date: Wed, 9 Sep 2026 08:18:44 +0200 [thread overview]
Message-ID: <20260909061845.4048047-4-jan.maslak@intel.com> (raw)
In-Reply-To: <20260909061845.4048047-1-jan.maslak@intel.com>
When xe_migrate_access_memory() falls back to a smaller pitch for an
unaligned destination, the copy can end up running linearly for the
entire transfer.
Reduce the number of copy jobs by first using a short linear copy to
reach a better destination alignment, then using the largest matrix copy
pitch that alignment supports, and finally using a linear copy for any
remaining tail bytes.
Signed-off-by: Christoph Manszewski <christoph.manszewski@intel.com>
Signed-off-by: Jan Maslak <jan.maslak@intel.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
---
drivers/gpu/drm/xe/xe_migrate.c | 151 ++++++++++++++++++++++++++++++--
1 file changed, 142 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index c40e0cc7499e..0bf63d3de56b 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -2225,6 +2225,86 @@ static u32 xe_migrate_copy_pitch(struct xe_device *xe, u32 len, u64 dst_addr)
return pitch;
}
+/**
+ * xe_migrate_dst_pitch() - Determine max pitch supported by dst alignment
+ * @dst_addr: Destination address (page offset)
+ *
+ * Returns the largest pitch (PAGE_SIZE, SZ_4K, SZ_256, or 4) that dst_addr
+ * supports based solely on its alignment. Returns 1 if not even 4-byte aligned.
+ */
+static u32 xe_migrate_dst_pitch(u64 dst_addr)
+{
+ if (IS_ALIGNED(dst_addr, PAGE_SIZE))
+ return PAGE_SIZE;
+ if (IS_ALIGNED(dst_addr, SZ_4K))
+ return SZ_4K;
+ if (IS_ALIGNED(dst_addr, SZ_256))
+ return SZ_256;
+ if (IS_ALIGNED(dst_addr, 4))
+ return 4;
+ return 1;
+}
+
+/**
+ * xe_migrate_bytes_to_align() - Calculate bytes needed to reach target alignment
+ * @dst_addr: Current destination address
+ * @alignment: Target alignment (PAGE_SIZE, SZ_4K, SZ_256, or 4)
+ *
+ * Returns: Number of bytes to copy to reach the target alignment.
+ */
+static u32 xe_migrate_bytes_to_align(u64 dst_addr, u32 alignment)
+{
+ return round_up(dst_addr, alignment) - dst_addr;
+}
+
+/**
+ * xe_migrate_best_alignment() - Find the best alignment reachable within max_bytes
+ * @dst_addr: Current destination address
+ * @max_bytes: Maximum bytes we can copy to reach alignment (typically U16_MAX)
+ *
+ * Returns the largest alignment (PAGE_SIZE, SZ_4K, SZ_256, or 4) that dst_addr
+ * can reach by copying at most max_bytes. Returns 0 if already at best alignment
+ * or if no useful alignment can be reached.
+ */
+static u32 xe_migrate_best_alignment(u64 dst_addr, u32 max_bytes)
+{
+ u32 bytes_to_page = xe_migrate_bytes_to_align(dst_addr, PAGE_SIZE);
+ u32 bytes_to_4k = xe_migrate_bytes_to_align(dst_addr, SZ_4K);
+ u32 bytes_to_256 = xe_migrate_bytes_to_align(dst_addr, SZ_256);
+ u32 bytes_to_4 = xe_migrate_bytes_to_align(dst_addr, 4);
+
+ if (bytes_to_page == 0)
+ return 0;
+
+ if (bytes_to_page <= max_bytes)
+ return PAGE_SIZE;
+
+ if (bytes_to_4k > 0 && bytes_to_4k <= max_bytes)
+ return SZ_4K;
+
+ if (bytes_to_256 > 0 && bytes_to_256 <= max_bytes)
+ return SZ_256;
+
+ if (bytes_to_4 > 0 && bytes_to_4 <= max_bytes)
+ return 4;
+
+ return 0;
+}
+
+/**
+ * xe_migrate_aligned_copy_len() - Calculate the aligned copy length for matrix copy
+ * @len: Remaining bytes
+ * @pitch: The pitch to use for matrix copy
+ *
+ * Returns: Length rounded down to pitch, or 0 if less than pitch.
+ */
+static u32 xe_migrate_aligned_copy_len(u32 len, u32 pitch)
+{
+ if (len < pitch)
+ return 0;
+ return round_down(len, pitch);
+}
+
static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
unsigned long len,
unsigned long sram_offset,
@@ -2558,15 +2638,68 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,
else
current_bytes = min_t(int, bytes_left, cursor.size);
- pitch = xe_migrate_copy_pitch(xe, current_bytes,
- write ? vram_addr :
- (unsigned long)buf & ~PAGE_MASK);
- if (xe->info.has_mem_copy_instr)
- current_bytes = min_t(int, current_bytes, U16_MAX * pitch);
- else
- current_bytes = min_t(int, current_bytes,
- round_down(S16_MAX * pitch,
- XE_CACHELINE_BYTES));
+ {
+ /*
+ * Optimized copy strategy to minimize number of jobs:
+ * 1. Linear copy to align dst to best reachable alignment
+ * 2. Matrix copy for bulk data copy
+ * 3. Single linear copy for remaining bytes
+ *
+ * The phase logic controls transfer chunking; emit_copy() selects
+ * MEM_COPY_CMD or XY_FAST_COPY_BLT based on hardware support.
+ */
+ u64 dst_addr = write ? vram_addr :
+ (unsigned long)buf & ~PAGE_MASK;
+ u32 max_linear = xe->info.has_mem_copy_instr ? U16_MAX :
+ round_down(S16_MAX, XE_CACHELINE_BYTES);
+ u32 best_align = xe_migrate_best_alignment(dst_addr, max_linear);
+ u32 bytes_to_align = best_align ?
+ xe_migrate_bytes_to_align(dst_addr, best_align) : 0;
+
+ if (bytes_to_align > 0 && bytes_to_align <= (u32)current_bytes) {
+ /*
+ * Phase 1: Linear copy to reach best alignment.
+ * Copy just enough bytes to align dst_addr.
+ */
+ pitch = 1;
+ current_bytes = min_t(int, bytes_to_align, max_linear);
+ } else if (IS_ALIGNED(dst_addr, 4)) {
+ /*
+ * Phase 2: Matrix copy for aligned bulk data.
+ * Use the best pitch that dst alignment supports,
+ * then round down len to that pitch.
+ */
+ u32 dst_pitch = xe_migrate_dst_pitch(dst_addr);
+ u32 aligned_len = xe_migrate_aligned_copy_len(current_bytes,
+ dst_pitch);
+
+ if (aligned_len >= dst_pitch) {
+ pitch = dst_pitch;
+ if (xe->info.has_mem_copy_instr) {
+ current_bytes = min_t(int, aligned_len,
+ U16_MAX * pitch);
+ } else {
+ current_bytes = min_t(int, aligned_len,
+ round_down(S16_MAX * pitch,
+ XE_CACHELINE_BYTES));
+ }
+ } else {
+ /*
+ * Phase 3: Linear copy for remainder.
+ * Not enough for matrix copy - do single linear copy.
+ */
+ pitch = 1;
+ current_bytes = min_t(int, current_bytes, max_linear);
+ }
+ } else {
+ /*
+ * Phase 3: Linear copy for remainder.
+ * dst not 4-aligned and can't reach alignment - linear copy.
+ */
+ pitch = 1;
+ current_bytes = min_t(int, current_bytes, max_linear);
+ }
+ }
__fence = xe_migrate_vram(m, current_bytes,
(unsigned long)buf & ~PAGE_MASK,
--
2.43.0
next prev parent reply other threads:[~2026-09-09 6:19 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-09 6:18 [PATCH v3 0/4] drm/xe/xe_migrate: Fix memory corruption with unaligned dst in MEM_COPY Jan Maslak
2026-09-09 6:18 ` [PATCH v3 1/4] drm/xe/xe_migrate: Align MEM_COPY pitch with destination address Jan Maslak
2026-09-09 6:32 ` sashiko-bot
2026-09-09 6:18 ` [PATCH v3 2/4] drm/xe/xe_migrate: Fix page tracking in access_memory Jan Maslak
2026-09-09 6:30 ` sashiko-bot
2026-09-09 6:18 ` Jan Maslak [this message]
2026-09-09 6:31 ` [PATCH v3 3/4] drm/xe/xe_migrate: Optimize unaligned access_memory copies sashiko-bot
2026-09-09 6:18 ` [PATCH v3 4/4] drm/xe/tests: Add xe_migrate_access_memory subtest Jan Maslak
2026-09-09 6:28 ` sashiko-bot
2026-09-09 6:25 ` ✗ CI.checkpatch: warning for drm/xe/xe_migrate: Fix memory corruption with unaligned dst in MEM_COPY (rev3) Patchwork
2026-09-09 6:27 ` ✓ CI.KUnit: success " Patchwork
2026-09-09 7:04 ` ✗ Xe.CI.BAT: failure " Patchwork
2026-09-09 11:36 ` ✗ Xe.CI.FULL: " Patchwork
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=20260909061845.4048047-4-jan.maslak@intel.com \
--to=jan.maslak@intel.com \
--cc=christoph.manszewski@intel.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=matthew.auld@intel.com \
--cc=matthew.brost@intel.com \
--cc=rodrigo.vivi@intel.com \
--cc=thomas.hellstrom@linux.intel.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.