[PATCH v4 2/3] drm/xe: Teach Xe how to use objects with XeLink connectivity

David Kershner david.kershner at intel.com
Wed Dec 20 23:17:09 UTC 2023


The XeLink device offers fabric backed memory.  Page table entries
need to be aware of this fact so that the access occur over the
fabric rather than to the system or local device memory.

Objects are shared via dma-buf, and then fabric connectivity is
checked during the _get_pages() pass.

Objects do NOT need to be dma mapped because system dma does not
occur.

The Device Physical Address (DPA) is the memory range assigned
to the fabric device at driver init.  This address is what will
need to be programmed into the page table entry.  In addition
the PTE_LM bit needs to be set.

Address information is provided in a scatter/gather table.

Teach the dma-buf interface and the page table entries all about
fabric backed memory.

Signed-off-by: David Kershner <david.kershner at intel.com>
---
 drivers/gpu/drm/xe/xe_bo.c           |  46 +++++-
 drivers/gpu/drm/xe/xe_bo.h           |   2 +
 drivers/gpu/drm/xe/xe_dma_buf.c      | 209 +++++++++++++++++++--------
 drivers/gpu/drm/xe/xe_dma_buf.h      |   3 +
 drivers/gpu/drm/xe/xe_ggtt.c         |   3 +
 drivers/gpu/drm/xe/xe_link.c         |  12 ++
 drivers/gpu/drm/xe/xe_link.h         |   2 +
 drivers/gpu/drm/xe/xe_pt.c           |   2 +
 drivers/gpu/drm/xe/xe_trace.h        |  29 ++++
 drivers/gpu/drm/xe/xe_ttm_vram_mgr.c |  17 ++-
 drivers/gpu/drm/xe/xe_vm.c           |   3 +-
 11 files changed, 258 insertions(+), 70 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index 8e4a3b1f6b93..8b30ba47b447 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -8,6 +8,7 @@
 #include <linux/dma-buf.h>
 
 #include <drm/drm_drv.h>
+#include <drm/drm_gem.h>
 #include <drm/drm_gem_ttm_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/ttm/ttm_device.h>
@@ -20,6 +21,7 @@
 #include "xe_drm_client.h"
 #include "xe_ggtt.h"
 #include "xe_gt.h"
+#include "xe_link.h"
 #include "xe_map.h"
 #include "xe_migrate.h"
 #include "xe_preempt_fence.h"
@@ -521,6 +523,32 @@ static int xe_bo_trigger_rebind(struct xe_device *xe, struct xe_bo *bo,
 	return ret;
 }
 
+/**
+ * map_xelink_connectivity - check for XeLink and create a mappable sgt
+ * if available
+ * @bo: object to check XeLink connectivity
+ *
+ * Returns sgt or -errno on error, -EIO indicates no XeLink connectivity.
+ */
+static struct sg_table *map_xelink_connectivity(struct xe_bo *bo)
+{
+	struct dma_buf_attachment *attach = bo->ttm.base.import_attach;
+	struct xe_bo *import;
+
+	if (!(bo->flags & XE_BO_XELINK_AVAIL))
+		return ERR_PTR(-EIO);
+
+	import = gem_to_xe_bo(attach->dmabuf->priv);
+
+	/* Make sure the object didn't migrate */
+	if (!xe_bo_is_vram(import)) {
+		bo->flags &= ~XE_BO_XELINK_AVAIL;
+		return ERR_PTR(-EIO);
+	}
+
+	return xe_dma_buf_map(attach, DMA_NONE);
+}
+
 /*
  * The dma-buf map_attachment() / unmap_attachment() is hooked up here.
  * Note that unmapping the attachment is deferred to the next
@@ -538,6 +566,7 @@ static int xe_bo_move_dmabuf(struct ttm_buffer_object *ttm_bo,
 					       ttm);
 	struct xe_device *xe = ttm_to_xe_device(ttm_bo->bdev);
 	struct sg_table *sg;
+	struct xe_bo *bo, *export;
 
 	xe_assert(xe, attach);
 	xe_assert(xe, ttm_bo->ttm);
@@ -545,12 +574,25 @@ static int xe_bo_move_dmabuf(struct ttm_buffer_object *ttm_bo,
 	if (new_res->mem_type == XE_PL_SYSTEM)
 		goto out;
 
+	bo = ttm_to_xe_bo(ttm_bo);
 	if (ttm_bo->sg) {
-		dma_buf_unmap_attachment(attach, ttm_bo->sg, DMA_BIDIRECTIONAL);
+		if (bo->flags & XE_BO_XELINK_AVAIL) {
+			export = gem_to_xe_bo(attach->dmabuf->priv);
+			xe_link_mapping_put(to_xe_device(export->ttm.base.dev));
+			xe_link_mapping_put(to_xe_device(ttm_bo->base.dev));
+			sg_free_table(ttm_bo->sg);
+			kfree(ttm_bo->sg);
+		} else {
+			dma_buf_unmap_attachment(attach, ttm_bo->sg, DMA_BIDIRECTIONAL);
+		}
 		ttm_bo->sg = NULL;
 	}
 
-	sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+	sg = map_xelink_connectivity(bo);
+
+	if (IS_ERR(sg) && PTR_ERR(sg) == -EIO)
+		sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+
 	if (IS_ERR(sg))
 		return PTR_ERR(sg);
 
diff --git a/drivers/gpu/drm/xe/xe_bo.h b/drivers/gpu/drm/xe/xe_bo.h
index 97b32528c600..48b8f27099e3 100644
--- a/drivers/gpu/drm/xe/xe_bo.h
+++ b/drivers/gpu/drm/xe/xe_bo.h
@@ -45,6 +45,8 @@
 #define XE_BO_PAGETABLE			BIT(12)
 #define XE_BO_NEEDS_CPU_ACCESS		BIT(13)
 #define XE_BO_NEEDS_UC			BIT(14)
+#define XE_BO_XELINK_AVAIL		BIT(15)
+
 /* this one is trigger internally only */
 #define XE_BO_INTERNAL_TEST		BIT(30)
 #define XE_BO_INTERNAL_64K		BIT(31)
diff --git a/drivers/gpu/drm/xe/xe_dma_buf.c b/drivers/gpu/drm/xe/xe_dma_buf.c
index 64ed303728fd..bfff479ac1f2 100644
--- a/drivers/gpu/drm/xe/xe_dma_buf.c
+++ b/drivers/gpu/drm/xe/xe_dma_buf.c
@@ -11,36 +11,35 @@
 
 #include <drm/drm_device.h>
 #include <drm/drm_prime.h>
+#include <drm/xelink_platform.h>
 #include <drm/ttm/ttm_tt.h>
 
 #include "tests/xe_test.h"
 #include "xe_bo.h"
 #include "xe_device.h"
+#include "xe_link.h"
 #include "xe_ttm_vram_mgr.h"
+#include "xe_trace.h"
 #include "xe_vm.h"
 
 MODULE_IMPORT_NS(DMA_BUF);
 
-static int xe_dma_buf_attach(struct dma_buf *dmabuf,
-			     struct dma_buf_attachment *attach)
-{
-	struct drm_gem_object *obj = attach->dmabuf->priv;
-
-	if (attach->peer2peer &&
-	    pci_p2pdma_distance(to_pci_dev(obj->dev->dev), attach->dev, false) < 0)
-		attach->peer2peer = false;
-
-	if (!attach->peer2peer && !xe_bo_can_migrate(gem_to_xe_bo(obj), XE_PL_TT))
-		return -EOPNOTSUPP;
-
-	xe_device_mem_access_get(to_xe_device(obj->dev));
-	return 0;
-}
 
 static void xe_dma_buf_detach(struct dma_buf *dmabuf,
 			      struct dma_buf_attachment *attach)
 {
 	struct drm_gem_object *obj = attach->dmabuf->priv;
+	struct xe_bo *bo = gem_to_xe_bo(obj);
+
+	if (attach->importer_priv) {
+		struct drm_gem_object *im_obj = attach->importer_priv;
+		struct xe_bo *im_bo = gem_to_xe_bo(im_obj);
+
+		if (im_bo->flags & XE_BO_XELINK_AVAIL) {
+			xe_link_mapping_put(xe_bo_device(bo));
+			xe_link_mapping_put(xe_bo_device(im_bo));
+		}
+	}
 
 	xe_device_mem_access_put(to_xe_device(obj->dev));
 }
@@ -85,20 +84,29 @@ static void xe_dma_buf_unpin(struct dma_buf_attachment *attach)
 	xe_bo_unpin_external(bo);
 }
 
-static struct sg_table *xe_dma_buf_map(struct dma_buf_attachment *attach,
-				       enum dma_data_direction dir)
+struct sg_table *xe_dma_buf_map(struct dma_buf_attachment *attach,
+				enum dma_data_direction dir)
 {
 	struct dma_buf *dma_buf = attach->dmabuf;
 	struct drm_gem_object *obj = dma_buf->priv;
 	struct xe_bo *bo = gem_to_xe_bo(obj);
 	struct sg_table *sgt;
 	int r = 0;
+	bool xelink_avail = false;
+
+	if (attach->importer_priv) {
+		struct drm_gem_object *im_obj = attach->importer_priv;
+		struct xe_bo *im_bo = gem_to_xe_bo(im_obj);
 
-	if (!attach->peer2peer && !xe_bo_can_migrate(bo, XE_PL_TT))
+		xelink_avail = im_bo->flags & XE_BO_XELINK_AVAIL;
+	}
+
+	if (!attach->peer2peer && !xe_bo_can_migrate(bo, XE_PL_TT) &&
+	    !xelink_avail)
 		return ERR_PTR(-EOPNOTSUPP);
 
 	if (!xe_bo_is_pinned(bo)) {
-		if (!attach->peer2peer)
+		if (!attach->peer2peer && !xelink_avail)
 			r = xe_bo_migrate(bo, XE_PL_TT);
 		else
 			r = xe_bo_validate(bo, NULL, false);
@@ -175,41 +183,12 @@ static int xe_dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
 	return 0;
 }
 
-const struct dma_buf_ops xe_dmabuf_ops = {
-	.attach = xe_dma_buf_attach,
-	.detach = xe_dma_buf_detach,
-	.pin = xe_dma_buf_pin,
-	.unpin = xe_dma_buf_unpin,
-	.map_dma_buf = xe_dma_buf_map,
-	.unmap_dma_buf = xe_dma_buf_unmap,
-	.release = drm_gem_dmabuf_release,
-	.begin_cpu_access = xe_dma_buf_begin_cpu_access,
-	.mmap = drm_gem_dmabuf_mmap,
-	.vmap = drm_gem_dmabuf_vmap,
-	.vunmap = drm_gem_dmabuf_vunmap,
-};
-
-struct dma_buf *xe_gem_prime_export(struct drm_gem_object *obj, int flags)
-{
-	struct xe_bo *bo = gem_to_xe_bo(obj);
-	struct dma_buf *buf;
-
-	if (bo->vm)
-		return ERR_PTR(-EPERM);
-
-	buf = drm_gem_prime_export(obj, flags);
-	if (!IS_ERR(buf))
-		buf->ops = &xe_dmabuf_ops;
-
-	return buf;
-}
 
 static struct drm_gem_object *
-xe_dma_buf_init_obj(struct drm_device *dev, struct xe_bo *storage,
+xe_dma_buf_init_obj(struct xe_device *xe, struct xe_bo *storage,
 		    struct dma_buf *dma_buf)
 {
 	struct dma_resv *resv = dma_buf->resv;
-	struct xe_device *xe = to_xe_device(dev);
 	struct xe_bo *bo;
 	int ret;
 
@@ -256,6 +235,121 @@ struct dma_buf_test_params {
 	container_of(_priv, struct dma_buf_test_params, base)
 #endif
 
+static int xe_dma_buf_attach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach);
+
+const struct dma_buf_ops xe_dmabuf_ops = {
+	.attach = xe_dma_buf_attach,
+	.detach = xe_dma_buf_detach,
+	.pin = xe_dma_buf_pin,
+	.unpin = xe_dma_buf_unpin,
+	.map_dma_buf = xe_dma_buf_map,
+	.unmap_dma_buf = xe_dma_buf_unmap,
+	.release = drm_gem_dmabuf_release,
+	.begin_cpu_access = xe_dma_buf_begin_cpu_access,
+	.mmap = drm_gem_dmabuf_mmap,
+	.vmap = drm_gem_dmabuf_vmap,
+	.vunmap = drm_gem_dmabuf_vunmap,
+};
+
+/*
+ * update_xelink - check for XeLink connectivity if available
+ * @obj: object to check XeLink connectivity
+ *
+ * If the imported object is a i915 dma-buf, and LMEM based, query to see if
+ * there is a XeLink, and if the XeLink is connected set the XeLink bit.
+ *
+ * 0 no connectivity, use P2P if available
+ * 1 XeLink is available
+ * -1 XeLink only is requested, and there is no XeLink
+ *
+ */
+static int update_xelink(struct dma_buf *dma_buf, struct xe_bo *bo)
+{
+	struct xe_bo *import;
+	struct xe_device *src;
+	struct xe_device *dst;
+	struct query_info *qi;
+	int connected;
+	int i;
+	int n;
+
+	/* Verify that both sides are xe devices */
+	if (dma_buf->ops != &xe_dmabuf_ops || !bo)
+		return 0;
+
+	import = gem_to_xe_bo(dma_buf->priv);
+	if (!xe_bo_is_vram(import))
+		return 0;
+
+	src = xe_bo_device(bo);
+	dst = xe_bo_device(import);
+
+	qi = src->xelink.ops->connectivity_query(src->xelink.handle,
+						 dst->xelink.xelink_id);
+	if (IS_ERR(qi))
+		return 0;
+
+	/*
+	 * Examine the query information.  A zero bandwidth link indicates we
+	 * are NOT connected.
+	 */
+	connected = 1;
+	for (i = 0, n = qi->src_cnt * qi->dst_cnt; i < n && connected; i++)
+		if (!qi->sd2sd[i].bandwidth)
+			connected = 0;
+
+	/* we are responsible for freeing qi */
+	kfree(qi);
+
+	if (connected) {
+		if (xe_link_mapping_get(src))
+			return 0;
+		if (xe_link_mapping_get(dst)) {
+			xe_link_mapping_put(src);
+			return 0;
+		}
+		bo->flags |= XE_BO_XELINK_AVAIL;
+	}
+
+	return connected;
+}
+
+static int xe_dma_buf_attach(struct dma_buf *dmabuf,
+			     struct dma_buf_attachment *attach)
+{
+	struct drm_gem_object *obj = attach->dmabuf->priv;
+	struct xe_bo *bo = gem_to_xe_bo(attach->importer_priv);
+	int xelink;
+
+	xelink = update_xelink(dmabuf, bo);
+
+	if (attach->peer2peer &&
+	    pci_p2pdma_distance(to_pci_dev(obj->dev->dev), attach->dev, false) < 0)
+		attach->peer2peer = false;
+
+	trace_xe_dma_buf_attach(gem_to_xe_bo(obj), bo, xelink, attach->peer2peer);
+	if (!xelink && !attach->peer2peer && !xe_bo_can_migrate(gem_to_xe_bo(obj), XE_PL_TT))
+		return -EOPNOTSUPP;
+
+	xe_device_mem_access_get(to_xe_device(obj->dev));
+	return 0;
+}
+
+struct dma_buf *xe_gem_prime_export(struct drm_gem_object *obj, int flags)
+{
+	struct xe_bo *bo = gem_to_xe_bo(obj);
+	struct dma_buf *buf;
+
+	if (bo->vm)
+		return ERR_PTR(-EPERM);
+
+	buf = drm_gem_prime_export(obj, flags);
+	if (!IS_ERR(buf))
+		buf->ops = &xe_dmabuf_ops;
+
+	return buf;
+}
+
 struct drm_gem_object *xe_gem_prime_import(struct drm_device *dev,
 					   struct dma_buf *dma_buf)
 {
@@ -264,6 +358,7 @@ struct drm_gem_object *xe_gem_prime_import(struct drm_device *dev,
 			(xe_cur_kunit_priv(XE_TEST_LIVE_DMA_BUF));)
 	const struct dma_buf_attach_ops *attach_ops;
 	struct dma_buf_attachment *attach;
+	struct xe_device *xe = to_xe_device(dev);
 	struct drm_gem_object *obj;
 	struct xe_bo *bo;
 
@@ -295,26 +390,18 @@ struct drm_gem_object *xe_gem_prime_import(struct drm_device *dev,
 		attach_ops = test->attach_ops;
 #endif
 
-	attach = dma_buf_dynamic_attach(dma_buf, dev->dev, attach_ops, &bo->ttm.base);
-	if (IS_ERR(attach)) {
-		obj = ERR_CAST(attach);
-		goto out_err;
-	}
-
 	/* Errors here will take care of freeing the bo. */
-	obj = xe_dma_buf_init_obj(dev, bo, dma_buf);
+	obj = xe_dma_buf_init_obj(xe, bo, dma_buf);
 	if (IS_ERR(obj))
 		return obj;
 
+	attach = dma_buf_dynamic_attach(dma_buf, dev->dev, attach_ops, &bo->ttm.base);
+	if (IS_ERR(attach))
+		return ERR_CAST(attach);
 
 	get_dma_buf(dma_buf);
 	obj->import_attach = attach;
 	return obj;
-
-out_err:
-	xe_bo_free(bo);
-
-	return obj;
 }
 
 #if IS_ENABLED(CONFIG_DRM_XE_KUNIT_TEST)
diff --git a/drivers/gpu/drm/xe/xe_dma_buf.h b/drivers/gpu/drm/xe/xe_dma_buf.h
index 861dd28a862c..36771a50451e 100644
--- a/drivers/gpu/drm/xe/xe_dma_buf.h
+++ b/drivers/gpu/drm/xe/xe_dma_buf.h
@@ -7,9 +7,12 @@
 #define _XE_DMA_BUF_H_
 
 #include <drm/drm_gem.h>
+#include <linux/dma-direction.h>
 
 struct dma_buf *xe_gem_prime_export(struct drm_gem_object *obj, int flags);
 struct drm_gem_object *xe_gem_prime_import(struct drm_device *dev,
 					   struct dma_buf *dma_buf);
+struct sg_table *xe_dma_buf_map(struct dma_buf_attachment *attach,
+				enum dma_data_direction dir);
 
 #endif
diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c
index c639dbf3bdd2..2041a94ba80a 100644
--- a/drivers/gpu/drm/xe/xe_ggtt.c
+++ b/drivers/gpu/drm/xe/xe_ggtt.c
@@ -36,6 +36,9 @@ static u64 xelp_ggtt_pte_encode_bo(struct xe_bo *bo, u64 bo_offset,
 	if (xe_bo_is_vram(bo) || xe_bo_is_stolen_devmem(bo))
 		pte |= XE_GGTT_PTE_DM;
 
+	if (xe_bo_is_vram(bo) || bo->flags & XE_BO_XELINK_AVAIL)
+		pte |= XE_PPGTT_PTE_DM;
+
 	return pte;
 }
 
diff --git a/drivers/gpu/drm/xe/xe_link.c b/drivers/gpu/drm/xe/xe_link.c
index f1484fbb630d..ea6c10498b77 100644
--- a/drivers/gpu/drm/xe/xe_link.c
+++ b/drivers/gpu/drm/xe/xe_link.c
@@ -464,3 +464,15 @@ void xe_link_remove(struct xe_device *xe)
 
 	xe->xelink.ops = &default_ops;
 }
+
+int xe_link_mapping_get(struct xe_device *xe)
+{
+	return xe->xelink.ops->parent_event(xe->xelink.handle,
+					       XELINK_PARENT_MAPPING_GET);
+}
+
+int xe_link_mapping_put(struct xe_device *xe)
+{
+	return xe->xelink.ops->parent_event(xe->xelink.handle,
+					       XELINK_PARENT_MAPPING_PUT);
+}
diff --git a/drivers/gpu/drm/xe/xe_link.h b/drivers/gpu/drm/xe/xe_link.h
index 099fc9e20550..a443f674d2d1 100644
--- a/drivers/gpu/drm/xe/xe_link.h
+++ b/drivers/gpu/drm/xe/xe_link.h
@@ -13,6 +13,8 @@ void xe_link_init_early(struct xe_device *xe);
 void xe_link_init_mmio(struct xe_device *xe);
 void xe_link_init(struct xe_device *xe);
 void xe_link_init_aux(struct xe_device *xe);
+int xe_link_mapping_get(struct xe_device *xe);
+int xe_link_mapping_put(struct xe_device *xe);
 void xe_link_remove(struct xe_device *xe);
 
 #endif
diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index de1030a47588..0731cc009689 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -609,6 +609,8 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
 	if (is_devmem) {
 		xe_walk.default_pte |= XE_PPGTT_PTE_DM;
 		xe_walk.dma_offset = vram_region_gpu_offset(bo->ttm.resource);
+	} else if (!xe_vma_has_no_bo(vma) && bo->flags & XE_BO_XELINK_AVAIL) {
+		xe_walk.default_pte |= XE_PPGTT_PTE_DM;
 	}
 
 	if (!xe_vma_has_no_bo(vma) && xe_bo_is_stolen(bo))
diff --git a/drivers/gpu/drm/xe/xe_trace.h b/drivers/gpu/drm/xe/xe_trace.h
index 95163c303f3e..2ae9091c7e76 100644
--- a/drivers/gpu/drm/xe/xe_trace.h
+++ b/drivers/gpu/drm/xe/xe_trace.h
@@ -105,6 +105,35 @@ DEFINE_EVENT(xe_bo, xe_bo_move,
 	     TP_ARGS(bo)
 );
 
+DECLARE_EVENT_CLASS(xe_dma_buf,
+		    TP_PROTO(struct xe_bo *bo, struct xe_bo *imp_bo, int xelink, int p2p),
+		    TP_ARGS(bo, imp_bo, xelink, p2p),
+
+		    TP_STRUCT__entry(
+			     __field(struct xe_bo *, bo)
+			     __field(struct xe_bo *, imp_bo)
+			     __field(bool, xelink)
+			     __field(bool, p2p)
+			     ),
+
+		    TP_fast_assign(
+			   __entry->bo = bo;
+			   __entry->imp_bo = imp_bo;
+			   __entry->xelink = xelink;
+			   __entry->p2p = p2p;
+			   ),
+
+		    TP_printk("bo=: 0x%p-mem_type=%d, imp_bo: 0x%p-mem_type=%d, xelink=%d, p2p=%d",
+			      __entry->bo, __entry->bo->ttm.resource->mem_type,
+			      __entry->imp_bo, __entry->imp_bo->ttm.resource->mem_type,
+			      __entry->xelink, __entry->p2p)
+);
+
+DEFINE_EVENT(xe_dma_buf, xe_dma_buf_attach,
+	     TP_PROTO(struct xe_bo *bo, struct xe_bo *imp_bo, int xelink, int p2p),
+	     TP_ARGS(bo, imp_bo, xelink, p2p)
+);
+
 DECLARE_EVENT_CLASS(xe_exec_queue,
 		    TP_PROTO(struct xe_exec_queue *q),
 		    TP_ARGS(q),
diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
index 115ec745e502..71cb4ee9dce2 100644
--- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
+++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
@@ -412,15 +412,20 @@ int xe_ttm_vram_mgr_alloc_sgt(struct xe_device *xe,
 	 */
 	xe_res_first(res, offset, length, &cursor);
 	for_each_sgtable_sg((*sgt), sg, i) {
-		phys_addr_t phys = cursor.start + tile->mem.vram.io_start;
 		size_t size = cursor.size;
 		dma_addr_t addr;
 
-		addr = dma_map_resource(dev, phys, size, dir,
-					DMA_ATTR_SKIP_CPU_SYNC);
-		r = dma_mapping_error(dev, addr);
-		if (r)
-			goto error_unmap;
+		if (dir == DMA_NONE) {
+			addr = cursor.start + tile->mem.vram.dpa_base;
+		} else {
+			phys_addr_t phys = cursor.start + tile->mem.vram.io_start;
+
+			addr = dma_map_resource(dev, phys, size, dir,
+						DMA_ATTR_SKIP_CPU_SYNC);
+			r = dma_mapping_error(dev, addr);
+			if (r)
+				goto error_unmap;
+		}
 
 		sg_set_page(sg, NULL, size, 0);
 		sg_dma_address(sg) = addr;
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 1ca917b8315c..80cdead34488 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -1135,7 +1135,8 @@ static u64 xelp_pte_encode_bo(struct xe_bo *bo, u64 bo_offset,
 	pte |= pte_encode_pat_index(xe, pat_index, pt_level);
 	pte |= pte_encode_ps(pt_level);
 
-	if (xe_bo_is_vram(bo) || xe_bo_is_stolen_devmem(bo))
+	if (xe_bo_is_vram(bo) || xe_bo_is_stolen_devmem(bo) ||
+	    bo->flags & XE_BO_XELINK_AVAIL)
 		pte |= XE_PPGTT_PTE_DM;
 
 	return pte;
-- 
2.38.1



More information about the Intel-xe mailing list