[Intel-xe] [PATCH 15/37] drm/xe: Rework initialisation ordering slightly so we can inherit fb

Rodrigo Vivi rodrigo.vivi at intel.com
Thu Jan 12 22:25:16 UTC 2023


From: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>

To inherit the framebuffer, we need to have TTM initialisation for
memory allocations, but not a single allocation needs to be done
because the FB is put at the start, and the first memory allocation
will likely wipe out the initial framebuffer.

There's still a small flicker, as we should probably set GGTT to exactly
the same adress, but the contents are preserved.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Cc: Matthew Brost <matthew.brost at intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi at intel.com>
---
 drivers/gpu/drm/xe/xe_device.c | 28 +++++++++----
 drivers/gpu/drm/xe/xe_ggtt.c   | 72 ++++++++++++++++++++++------------
 drivers/gpu/drm/xe/xe_ggtt.h   |  1 +
 drivers/gpu/drm/xe/xe_gt.c     | 41 +++++++++++++++++--
 drivers/gpu/drm/xe/xe_gt.h     |  1 +
 5 files changed, 105 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index 0b154c0a1381..bd6c54aa5649 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -335,7 +335,7 @@ static int xe_device_init_display_noirq(struct xe_device *xe)
 }
 
 #if IS_ENABLED(CONFIG_DRM_XE_DISPLAY)
-static inline void xe_device_fini_display_early(struct drm_device *dev, void *dummy)
+static void xe_device_fini_display_noaccel(struct drm_device *dev, void *dummy)
 {
 	struct xe_device *xe = to_xe_device(dev);
 
@@ -343,20 +343,20 @@ static inline void xe_device_fini_display_early(struct drm_device *dev, void *du
 }
 #endif
 
-static int xe_device_init_display_early(struct xe_device *xe)
+static int xe_device_init_display_noaccel(struct xe_device *xe)
 {
 #if IS_ENABLED(CONFIG_DRM_XE_DISPLAY)
 	int err = intel_modeset_init_nogem(xe);
 	if (err)
 		return err;
 
-	return drmm_add_action_or_reset(&xe->drm, xe_device_fini_display_early, NULL);
+	return drmm_add_action_or_reset(&xe->drm, xe_device_fini_display_noaccel, NULL);
 #else
 	return 0;
 #endif
 }
 
-static int xe_device_init_display_late(struct xe_device *xe)
+static int xe_device_init_display(struct xe_device *xe)
 {
 #if IS_ENABLED(CONFIG_DRM_XE_DISPLAY)
 	return intel_modeset_init(xe);
@@ -412,17 +412,29 @@ int xe_device_probe(struct xe_device *xe)
 	if (err)
 		goto err;
 
-	err = xe_device_init_display_early(xe);
+	for_each_gt(gt, xe, id) {
+		err = xe_gt_init_early(gt);
+		if (err)
+			goto err_irq_shutdown;
+	}
+
+	err = xe_mmio_probe_vram(xe);
 	if (err)
 		goto err_irq_shutdown;
 
 	for_each_gt(gt, xe, id) {
-		err = xe_gt_init_early(gt);
+		err = xe_gt_init_noalloc(gt);
 		if (err)
 			goto err_irq_shutdown;
 	}
 
-	err = xe_mmio_probe_vram(xe);
+	/*
+	 * Now that GT is initialized (TTM in particular),
+	 * we can try to init display, and inherit the initial fb.
+	 * This is the reason the first allocation needs to be done
+	 * inside display.
+	 */
+	err = xe_device_init_display_noaccel(xe);
 	if (err)
 		goto err_irq_shutdown;
 
@@ -432,7 +444,7 @@ int xe_device_probe(struct xe_device *xe)
 			goto err_irq_shutdown;
 	}
 
-	err = xe_device_init_display_late(xe);
+	err = xe_device_init_display(xe);
 	if (err)
 		goto err_fini_display;
 
diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c
index 3ace37d90f8d..d67f66b33aed 100644
--- a/drivers/gpu/drm/xe/xe_ggtt.c
+++ b/drivers/gpu/drm/xe/xe_ggtt.c
@@ -68,7 +68,10 @@ static void xe_ggtt_clear(struct xe_ggtt *ggtt, u64 start, u64 size)
 
 	XE_BUG_ON(start >= end);
 
-	scratch_pte = xe_ggtt_pte_encode(ggtt->scratch, 0);
+	if (ggtt->scratch)
+		scratch_pte = xe_ggtt_pte_encode(ggtt->scratch, 0);
+	else
+		scratch_pte = 0;
 
 	while (start < end) {
 		xe_ggtt_set_pte(ggtt, start, scratch_pte);
@@ -76,7 +79,7 @@ static void xe_ggtt_clear(struct xe_ggtt *ggtt, u64 start, u64 size)
 	}
 }
 
-static void ggtt_fini(struct drm_device *drm, void *arg)
+static void ggtt_fini_noalloc(struct drm_device *drm, void *arg)
 {
 	struct xe_ggtt *ggtt = arg;
 
@@ -86,12 +89,11 @@ static void ggtt_fini(struct drm_device *drm, void *arg)
 	xe_bo_unpin_map_no_vm(ggtt->scratch);
 }
 
-int xe_ggtt_init(struct xe_gt *gt, struct xe_ggtt *ggtt)
+int xe_ggtt_init_noalloc(struct xe_gt *gt, struct xe_ggtt *ggtt)
 {
 	struct xe_device *xe = gt_to_xe(gt);
 	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
 	unsigned int gsm_size;
-	int err;
 
 	XE_BUG_ON(xe_gt_is_media_type(gt));
 
@@ -104,22 +106,7 @@ int xe_ggtt_init(struct xe_gt *gt, struct xe_ggtt *ggtt)
 	}
 
 	ggtt->gsm = gt->mmio.regs + SZ_8M;
-	ggtt->scratch = xe_bo_create_locked(xe, gt, NULL, GEN8_PAGE_SIZE,
-					    ttm_bo_type_kernel,
-					    XE_BO_CREATE_VRAM_IF_DGFX(gt) |
-					    XE_BO_CREATE_PINNED_BIT);
-	if (IS_ERR(ggtt->scratch)) {
-		err = PTR_ERR(ggtt->scratch);
-		goto err_iomap;
-	}
-
-	err = xe_bo_pin(ggtt->scratch);
-	xe_bo_unlock_no_vm(ggtt->scratch);
-	if (err)
-		goto err_scratch;
-
 	ggtt->size = (gsm_size / 8) * (u64)GEN8_PAGE_SIZE;
-	xe_ggtt_clear(ggtt, 0, ggtt->size - 1);
 
 	/*
 	 * 8B per entry, each points to a 4KB page.
@@ -142,15 +129,48 @@ int xe_ggtt_init(struct xe_gt *gt, struct xe_ggtt *ggtt)
 		    ggtt->size - xe_wopcm_size(xe));
 	mutex_init(&ggtt->lock);
 
-	err = drmm_add_action_or_reset(&xe->drm, ggtt_fini, ggtt);
-	if (err)
-		return err;
+	return drmm_add_action_or_reset(&xe->drm, ggtt_fini_noalloc, ggtt);
+}
 
-	return 0;
+static void xe_ggtt_initial_clear(struct xe_ggtt *ggtt)
+{
+	struct drm_mm_node *hole;
+	u64 start, end;
+
+	/* Display may have allocated inside ggtt, so be careful with clearing here */
+	mutex_lock(&ggtt->lock);
+	drm_mm_for_each_hole(hole, &ggtt->mm, start, end)
+		xe_ggtt_clear(ggtt, start, end - start);
 
-err_scratch:
-	xe_bo_put(ggtt->scratch);
-err_iomap:
+	xe_ggtt_invalidate(ggtt->gt);
+	mutex_unlock(&ggtt->lock);
+}
+
+int xe_ggtt_init(struct xe_gt *gt, struct xe_ggtt *ggtt)
+{
+	struct xe_device *xe = gt_to_xe(gt);
+	int err;
+
+	ggtt->scratch = xe_bo_create_locked(xe, gt, NULL, GEN8_PAGE_SIZE,
+					    ttm_bo_type_kernel,
+					    XE_BO_CREATE_VRAM_IF_DGFX(gt) |
+					    XE_BO_CREATE_PINNED_BIT);
+	if (IS_ERR(ggtt->scratch)) {
+		err = PTR_ERR(ggtt->scratch);
+		goto err;
+	}
+
+	err = xe_bo_pin(ggtt->scratch);
+	xe_bo_unlock_no_vm(ggtt->scratch);
+	if (err) {
+		xe_bo_put(ggtt->scratch);
+		goto err;
+	}
+
+	xe_ggtt_initial_clear(ggtt);
+	return 0;
+err:
+	ggtt->scratch = NULL;
 	return err;
 }
 
diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h
index ebb5c312f331..289c6852ad1a 100644
--- a/drivers/gpu/drm/xe/xe_ggtt.h
+++ b/drivers/gpu/drm/xe/xe_ggtt.h
@@ -11,6 +11,7 @@
 u64 xe_ggtt_pte_encode(struct xe_bo *bo, u64 bo_offset);
 void xe_ggtt_set_pte(struct xe_ggtt *ggtt, u64 addr, u64 pte);
 void xe_ggtt_invalidate(struct xe_gt *gt);
+int xe_ggtt_init_noalloc(struct xe_gt *gt, struct xe_ggtt *ggtt);
 int xe_ggtt_init(struct xe_gt *gt, struct xe_ggtt *ggtt);
 void xe_ggtt_printk(struct xe_ggtt *ggtt, const char *prefix);
 
diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
index ccb87a7c6554..6cea15725cae 100644
--- a/drivers/gpu/drm/xe/xe_gt.c
+++ b/drivers/gpu/drm/xe/xe_gt.c
@@ -389,6 +389,43 @@ int xe_gt_init_early(struct xe_gt *gt)
 	return 0;
 }
 
+/**
+ * xe_gt_init_noalloc - Init GT up to the point where allocations can happen.
+ * @gt: The GT to initialize.
+ *
+ * This function prepares the GT to allow memory allocations to VRAM, but is not
+ * allowed to allocate memory itself. This state is useful for display readout,
+ * because the inherited display framebuffer will otherwise be overwritten as it
+ * is usually put at the start of VRAM.
+ *
+ * Returns: 0 on success, negative error code on error.
+ */
+int xe_gt_init_noalloc(struct xe_gt *gt)
+{
+	int err, err2;
+
+	if (xe_gt_is_media_type(gt))
+		return 0;
+
+	xe_device_mem_access_get(gt_to_xe(gt));
+	err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
+	if (err)
+		goto err;
+
+	err = gt_ttm_mgr_init(gt);
+	if (err)
+		goto err_force_wake;
+
+	err = xe_ggtt_init_noalloc(gt, gt->mem.ggtt);
+
+err_force_wake:
+	err2 = xe_force_wake_put(gt_to_fw(gt), XE_FW_GT);
+	XE_WARN_ON(err2);
+	xe_device_mem_access_put(gt_to_xe(gt));
+err:
+	return err;
+}
+
 static int gt_fw_domain_init(struct xe_gt *gt)
 {
 	int err, i;
@@ -399,10 +436,6 @@ static int gt_fw_domain_init(struct xe_gt *gt)
 		goto err_hw_fence_irq;
 
 	if (!xe_gt_is_media_type(gt)) {
-		err = gt_ttm_mgr_init(gt);
-		if (err)
-			goto err_force_wake;
-
 		err = xe_ggtt_init(gt, gt->mem.ggtt);
 		if (err)
 			goto err_force_wake;
diff --git a/drivers/gpu/drm/xe/xe_gt.h b/drivers/gpu/drm/xe/xe_gt.h
index 1e070ab4e5aa..5dc08a993cfe 100644
--- a/drivers/gpu/drm/xe/xe_gt.h
+++ b/drivers/gpu/drm/xe/xe_gt.h
@@ -18,6 +18,7 @@
 
 int xe_gt_alloc(struct xe_device *xe, struct xe_gt *gt);
 int xe_gt_init_early(struct xe_gt *gt);
+int xe_gt_init_noalloc(struct xe_gt *gt);
 int xe_gt_init(struct xe_gt *gt);
 int xe_gt_record_default_lrcs(struct xe_gt *gt);
 void xe_gt_suspend_prepare(struct xe_gt *gt);
-- 
2.38.1



More information about the Intel-xe mailing list