Page MenuHomeFreeBSD

drm-kmod-mtl-mapping-and-capture-f252a30f27d1.patch

Authored By
oleglelchuk_gmail.com
Tue, Sep 29, 3:03 PM
Size
10 KB
Referenced Files
None
Subscribers
None

drm-kmod-mtl-mapping-and-capture-f252a30f27d1.patch

diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c
index 8d466e285d79447da387767ebfba7ec92a7c425f..7ebe8f52b82558ff087e07111365b5dd9029a32c 100644
--- a/drivers/gpu/drm/i915/display/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/display/intel_fbdev.c
@@ -59,6 +59,7 @@ struct intel_fbdev {
struct i915_vma *vma;
unsigned long vma_flags;
int preferred_bpp;
+ struct drm_i915_gem_object *screen_base_object;
/* Whether or not fbdev hpd processing is temporarily suspended */
bool hpd_suspended: 1;
@@ -133,24 +134,40 @@ static int intel_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
return intel_bo_fb_mmap(obj, vma);
}
+#ifdef __FreeBSD__
+static void intel_fbdev_unpin_screen_base(struct intel_fbdev *ifbdev)
+{
+ struct drm_i915_gem_object *obj = ifbdev->screen_base_object;
+
+ if (obj == NULL)
+ return;
+
+ ifbdev->screen_base_object = NULL;
+ i915_gem_object_unpin_map(obj);
+}
+#endif
+
static void intel_fbdev_fb_destroy(struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
struct intel_fbdev *ifbdev = container_of(fb_helper, struct intel_fbdev, helper);
#ifdef __FreeBSD__
- unregister_fictitious_range(
- fb_helper->dev,
- ifbdev->helper.info->fix.smem_start,
- ifbdev->helper.info->fix.smem_len);
+ if (!(info->flags & FBINFO_VIRTFB))
+ unregister_fictitious_range(fb_helper->dev,
+ info->fix.smem_start, info->fix.smem_len);
#endif
drm_fb_helper_fini(&ifbdev->helper);
+#ifdef __FreeBSD__
+ intel_fbdev_unpin_screen_base(ifbdev);
+#endif
+
/*
- * We rely on the object-free to release the VMA pinning for
- * the info->screen_base mmaping. Leaking the VMA is simpler than
- * trying to rectify all the possible error paths leading here.
+ * The GGTT iomap path relies on object-free to release the extra VMA
+ * pin associated with info->screen_base. Leaking the VMA is simpler
+ * than trying to rectify all the possible error paths leading here.
*/
intel_fb_unpin_vma(ifbdev->vma, ifbdev->vma_flags);
drm_framebuffer_remove(&ifbdev->fb->base);
@@ -254,7 +271,8 @@ static int intelfb_create(struct drm_fb_helper *helper,
obj = intel_fb_bo(&fb->base);
- ret = intel_fbdev_fb_fill_info(dev_priv, info, obj, vma);
+ ret = intel_fbdev_fb_fill_info(dev_priv, info, obj, vma,
+ &ifbdev->screen_base_object);
if (ret)
goto out_unpin;
@@ -272,7 +290,10 @@ static int intelfb_create(struct drm_fb_helper *helper,
* values passed to register_fictitious_range() below are unavailable
* from a generic structure set by both drivers.
*/
- register_fictitious_range(dev, info->fix.smem_start, info->fix.smem_len);
+ /* System RAM already has real vm_page structures. */
+ if (!(info->flags & FBINFO_VIRTFB))
+ register_fictitious_range(dev, info->fix.smem_start,
+ info->fix.smem_len);
#endif
drm_fb_helper_fill_info(info, &ifbdev->helper, sizes);
@@ -304,11 +325,59 @@ out_unlock:
return ret;
}
+#ifdef __FreeBSD__
+static void intel_fbdev_flush_object_map(struct drm_fb_helper *helper,
+ struct drm_clip_rect *clip)
+{
+ struct intel_fbdev *ifbdev = to_intel_fbdev(helper);
+ struct drm_framebuffer *fb = helper->fb;
+ struct drm_i915_gem_object *obj;
+ u64 offset, end;
+ u32 cpp, pitch, x1, x2, y1, y2;
+
+ if (ifbdev->screen_base_object == NULL || fb == NULL)
+ return;
+
+ x1 = min_t(u32, clip->x1, fb->width);
+ x2 = min_t(u32, clip->x2, fb->width);
+ y1 = min_t(u32, clip->y1, fb->height);
+ y2 = min_t(u32, clip->y2, fb->height);
+ if (x1 >= x2 || y1 >= y2)
+ return;
+
+ cpp = fb->format->cpp[0];
+ pitch = fb->pitches[0];
+ offset = mul_u32_u32(y1, pitch);
+ if (check_add_overflow(offset, mul_u32_u32(x1, cpp), &offset) ||
+ check_add_overflow(offset, (u64)fb->offsets[0], &offset))
+ return;
+
+ end = mul_u32_u32(y2 - 1, pitch);
+ if (check_add_overflow(end, mul_u32_u32(x2, cpp), &end) ||
+ check_add_overflow(end, (u64)fb->offsets[0], &end))
+ return;
+
+ obj = ifbdev->screen_base_object;
+ if (offset >= obj->base.size)
+ return;
+
+ end = min_t(u64, end, obj->base.size);
+ if (offset < end) {
+ /* Make WB console writes visible to the display engine. */
+ __i915_gem_object_flush_map(obj, offset, end - offset);
+ }
+}
+#endif
+
static int intelfb_dirty(struct drm_fb_helper *helper, struct drm_clip_rect *clip)
{
if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2))
return 0;
+#ifdef __FreeBSD__
+ intel_fbdev_flush_object_map(helper, clip);
+#endif
+
if (helper->fb->funcs->dirty)
return helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, clip, 1);
@@ -661,6 +730,9 @@ static int intel_fbdev_client_hotplug(struct drm_client_dev *client)
err_drm_fb_helper_fini:
drm_fb_helper_fini(fb_helper);
+#ifdef __FreeBSD__
+ intel_fbdev_unpin_screen_base(to_intel_fbdev(fb_helper));
+#endif
err_drm_err:
drm_err(dev, "Failed to setup i915 fbdev emulation (ret=%d)\n", ret);
return ret;
diff --git a/drivers/gpu/drm/i915/display/intel_fbdev_fb.c b/drivers/gpu/drm/i915/display/intel_fbdev_fb.c
index 4991c35a2632fe4c927d884b31d333abceccbcb3..1e79978ca09d30ddfd16974c60d35cdc37407e08 100644
--- a/drivers/gpu/drm/i915/display/intel_fbdev_fb.c
+++ b/drivers/gpu/drm/i915/display/intel_fbdev_fb.c
@@ -68,13 +68,16 @@ struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper,
}
int intel_fbdev_fb_fill_info(struct drm_i915_private *i915, struct fb_info *info,
- struct drm_gem_object *_obj, struct i915_vma *vma)
+ struct drm_gem_object *_obj, struct i915_vma *vma,
+ struct drm_i915_gem_object **screen_base_object)
{
struct drm_i915_gem_object *obj = to_intel_bo(_obj);
struct i915_gem_ww_ctx ww;
void __iomem *vaddr;
int ret;
+ *screen_base_object = NULL;
+
if (i915_gem_object_is_lmem(obj)) {
struct intel_memory_region *mem = obj->mm.region;
@@ -84,6 +87,14 @@ int intel_fbdev_fb_fill_info(struct drm_i915_private *i915, struct fb_info *info
i915_gem_object_get_dma_address(obj, 0) -
mem->region.start);
info->fix.smem_len = obj->base.size;
+#ifdef __FreeBSD__
+ } else if (!i915_ggtt_has_aperture(to_gt(i915)->ggtt) &&
+ i915_gem_object_is_shmem(obj)) {
+ /* vt_fb_mmap() resolves each page through screen_base. */
+ info->fix.smem_start = 0;
+ info->fix.smem_len = obj->base.size;
+ info->flags |= FBINFO_VIRTFB;
+#endif
} else {
struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
@@ -99,7 +110,23 @@ int intel_fbdev_fb_fill_info(struct drm_i915_private *i915, struct fb_info *info
if (ret)
continue;
- vaddr = i915_vma_pin_iomap(vma);
+#ifdef __FreeBSD__
+ /*
+ * MTL fbdev uses shmem because Wa_22018444074 excludes stolen
+ * memory. Map those backing pages directly: on FreeBSD, CPU
+ * writes through MTL's GMADR aperture can miss the pages scanned
+ * out by the display engine after the EFI framebuffer handoff.
+ * Use WB for VT performance; the damage callback flushes writes.
+ */
+ if (!i915_ggtt_has_aperture(to_gt(i915)->ggtt) &&
+ i915_gem_object_is_shmem(obj)) {
+ vaddr = (void __iomem *)i915_gem_object_pin_map(obj,
+ I915_MAP_WB);
+ if (!IS_ERR(vaddr))
+ *screen_base_object = obj;
+ } else
+#endif
+ vaddr = i915_vma_pin_iomap(vma);
if (IS_ERR(vaddr)) {
drm_err(&i915->drm,
"Failed to remap framebuffer into virtual memory (%pe)\n", vaddr);
diff --git a/drivers/gpu/drm/i915/display/intel_fbdev_fb.h b/drivers/gpu/drm/i915/display/intel_fbdev_fb.h
index e502ae375fc03e644a403a806b180cbf2c08f84e..af7d75106116e4bd6a9926d9109bbf11afa193f8 100644
--- a/drivers/gpu/drm/i915/display/intel_fbdev_fb.h
+++ b/drivers/gpu/drm/i915/display/intel_fbdev_fb.h
@@ -10,12 +10,14 @@ struct drm_fb_helper;
struct drm_fb_helper_surface_size;
struct drm_gem_object;
struct drm_i915_private;
+struct drm_i915_gem_object;
struct fb_info;
struct i915_vma;
struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes);
int intel_fbdev_fb_fill_info(struct drm_i915_private *i915, struct fb_info *info,
- struct drm_gem_object *obj, struct i915_vma *vma);
+ struct drm_gem_object *_obj, struct i915_vma *vma,
+ struct drm_i915_gem_object **screen_base_object);
#endif
diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c
index 11705938bdeccf3f6580ba515f4d68738a148e35..3da2471dd9896879c1c973e93ad3692a34a306ec 100644
--- a/drivers/gpu/drm/i915/gt/intel_ggtt.c
+++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c
@@ -1229,22 +1229,12 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
unsigned int size;
u16 snb_gmch_ctl;
-#ifdef __linux__
- if (!HAS_LMEM(i915) && !HAS_LMEMBAR_SMEM_STOLEN(i915)) {
-#elif defined(__FreeBSD__)
/*
- * We need to initialize GMADR on freebsd in order to use shmem
- * framebuffers. We are falling back to shmem framebuffers on freebsd
- * because the Wa_22018444074 mtl hardware workaround disabled using stolen
- * memory on mtl. Unlike on linux, when this happens we end up passing an
- * invalid phys address to register_fictitious_range which causes a panic.
- * Because GMADR is not valid we end up with a value such as 0x2000 instead
- * of a valid pointer.
- * MTL has LMEMBAR for stolen but still needs GMADR for shmem objects.
+ * On MTL, BAR2 exposes stolen memory, not a CPU GGTT aperture.
+ * Advertising it as mappable redirects CPU writes away from the
+ * backing pages that the GPU fetches through the GGTT.
*/
- if ((!HAS_LMEM(i915) && !HAS_LMEMBAR_SMEM_STOLEN(i915))
- || HAS_LMEMBAR_SMEM_STOLEN(i915)) {
-#endif
+ if (!HAS_LMEM(i915) && !HAS_LMEMBAR_SMEM_STOLEN(i915)) {
if (!i915_pci_resource_valid(pdev, GEN4_GMADR_BAR))
return -ENXIO;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index eb0885e9f7cc759c3845ac4117b7f4def5228a9f..f768e4c2553960017b0a823858c2a50584ccc97c 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1142,7 +1142,9 @@ i915_vma_coredump_create(const struct intel_gt *gt,
dst->unused = 0;
ret = -EINVAL;
- if (drm_mm_node_allocated(&ggtt->error_capture)) {
+ /* MTL BAR2 maps stolen memory, not a CPU GGTT aperture. */
+ if (drm_mm_node_allocated(&ggtt->error_capture) &&
+ !HAS_LMEMBAR_SMEM_STOLEN(gt->i915)) {
void __iomem *s;
dma_addr_t dma;

File Metadata

Mime Type
text/x-diff
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39951465
Default Alt Text
drm-kmod-mtl-mapping-and-capture-f252a30f27d1.patch (10 KB)

Event Timeline