diff options
author | Justin M. Forbes <jforbes@fedoraproject.org> | 2017-11-27 15:39:17 -0600 |
---|---|---|
committer | Justin M. Forbes <jforbes@fedoraproject.org> | 2017-11-27 15:39:17 -0600 |
commit | bff21f88c7129b709157e7cad97bcdef3d2040e1 (patch) | |
tree | b6e20d9f01ebfceb804a0d4245bf372e00a053e1 | |
parent | 4e31e9c164ab3ee11f41d4631028bf49e13040ab (diff) | |
download | kernel-bff21f88c7129b709157e7cad97bcdef3d2040e1.tar.gz kernel-bff21f88c7129b709157e7cad97bcdef3d2040e1.tar.xz kernel-bff21f88c7129b709157e7cad97bcdef3d2040e1.zip |
Add qxl fixes
-rw-r--r-- | kernel.spec | 3 | ||||
-rw-r--r-- | qxl-fixes.patch | 376 |
2 files changed, 379 insertions, 0 deletions
diff --git a/kernel.spec b/kernel.spec index ffc23c367..1c31fc1a2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -653,6 +653,9 @@ Patch625: v3-2-2-Input-synaptics---Lenovo-X1-Carbon-5-should-use-SMBUS-RMI.patch # rhbz 1490803 Patch626: 1-2-kvm-vmx-Reinstate-support-for-CPUs-without-virtual-NMI.patch +# Fixes for QXL issues +Patch627: qxl-fixes.patch + # END OF PATCH DEFINITIONS %endif diff --git a/qxl-fixes.patch b/qxl-fixes.patch new file mode 100644 index 000000000..933f27c4a --- /dev/null +++ b/qxl-fixes.patch @@ -0,0 +1,376 @@ +From 56cbcb6c41932b19ef0d838f1ff25a662a2e403d Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann <kraxel@redhat.com> +Date: Thu, 19 Oct 2017 08:21:49 +0200 +Subject: [PATCH] drm/qxl: replace QXL_INFO with DRM_DEBUG_DRIVER + +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +Reviewed-by: Dave Airlie <airlied@redhat.com> +Link: http://patchwork.freedesktop.org/patch/msgid/20171019062150.28090-2-kraxel@redhat.com +--- + drivers/gpu/drm/qxl/qxl_cmd.c | 16 +++++++--------- + drivers/gpu/drm/qxl/qxl_drv.h | 26 +------------------------- + drivers/gpu/drm/qxl/qxl_fb.c | 13 +++++-------- + drivers/gpu/drm/qxl/qxl_release.c | 5 ++--- + drivers/gpu/drm/qxl/qxl_ttm.c | 4 ++-- + 5 files changed, 17 insertions(+), 47 deletions(-) + +diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c +index 74fc9362ecf9..8ec53d5abd62 100644 +--- a/drivers/gpu/drm/qxl/qxl_cmd.c ++++ b/drivers/gpu/drm/qxl/qxl_cmd.c +@@ -219,7 +219,7 @@ int qxl_garbage_collect(struct qxl_device *qdev) + union qxl_release_info *info; + + while (qxl_ring_pop(qdev->release_ring, &id)) { +- QXL_INFO(qdev, "popped %lld\n", id); ++ DRM_DEBUG_DRIVER("popped %lld\n", id); + while (id) { + release = qxl_release_from_id_locked(qdev, id); + if (release == NULL) +@@ -229,8 +229,8 @@ int qxl_garbage_collect(struct qxl_device *qdev) + next_id = info->next; + qxl_release_unmap(qdev, release, info); + +- QXL_INFO(qdev, "popped %lld, next %lld\n", id, +- next_id); ++ DRM_DEBUG_DRIVER("popped %lld, next %lld\n", id, ++ next_id); + + switch (release->type) { + case QXL_RELEASE_DRAWABLE: +@@ -248,7 +248,7 @@ int qxl_garbage_collect(struct qxl_device *qdev) + } + } + +- QXL_INFO(qdev, "%s: %d\n", __func__, i); ++ DRM_DEBUG_DRIVER("%d\n", i); + + return i; + } +@@ -381,8 +381,7 @@ void qxl_io_create_primary(struct qxl_device *qdev, + { + struct qxl_surface_create *create; + +- QXL_INFO(qdev, "%s: qdev %p, ram_header %p\n", __func__, qdev, +- qdev->ram_header); ++ DRM_DEBUG_DRIVER("qdev %p, ram_header %p\n", qdev, qdev->ram_header); + create = &qdev->ram_header->create_surface; + create->format = bo->surf.format; + create->width = bo->surf.width; +@@ -390,8 +389,7 @@ void qxl_io_create_primary(struct qxl_device *qdev, + create->stride = bo->surf.stride; + create->mem = qxl_bo_physical_address(qdev, bo, offset); + +- QXL_INFO(qdev, "%s: mem = %llx, from %p\n", __func__, create->mem, +- bo->kptr); ++ DRM_DEBUG_DRIVER("mem = %llx, from %p\n", create->mem, bo->kptr); + + create->flags = QXL_SURF_FLAG_KEEP_DATA; + create->type = QXL_SURF_TYPE_PRIMARY; +@@ -401,7 +399,7 @@ void qxl_io_create_primary(struct qxl_device *qdev, + + void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id) + { +- QXL_INFO(qdev, "qxl_memslot_add %d\n", id); ++ DRM_DEBUG_DRIVER("qxl_memslot_add %d\n", id); + wait_for_io_cmd(qdev, id, QXL_IO_MEMSLOT_ADD_ASYNC); + } + +diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h +index 3397a1907336..d707b351875c 100644 +--- a/drivers/gpu/drm/qxl/qxl_drv.h ++++ b/drivers/gpu/drm/qxl/qxl_drv.h +@@ -62,33 +62,9 @@ + + #define QXL_DEBUGFS_MAX_COMPONENTS 32 + +-extern int qxl_log_level; + extern int qxl_num_crtc; + extern int qxl_max_ioctls; + +-enum { +- QXL_INFO_LEVEL = 1, +- QXL_DEBUG_LEVEL = 2, +-}; +- +-#define QXL_INFO(qdev, fmt, ...) do { \ +- if (qxl_log_level >= QXL_INFO_LEVEL) { \ +- qxl_io_log(qdev, fmt, __VA_ARGS__); \ +- } \ +- } while (0) +-#define QXL_DEBUG(qdev, fmt, ...) do { \ +- if (qxl_log_level >= QXL_DEBUG_LEVEL) { \ +- qxl_io_log(qdev, fmt, __VA_ARGS__); \ +- } \ +- } while (0) +-#define QXL_INFO_ONCE(qdev, fmt, ...) do { \ +- static int done; \ +- if (!done) { \ +- done = 1; \ +- QXL_INFO(qdev, fmt, __VA_ARGS__); \ +- } \ +- } while (0) +- + #define DRM_FILE_OFFSET 0x100000000ULL + #define DRM_FILE_PAGE_OFFSET (DRM_FILE_OFFSET >> PAGE_SHIFT) + +@@ -351,7 +327,7 @@ int qxl_check_idle(struct qxl_ring *ring); + static inline void * + qxl_fb_virtual_address(struct qxl_device *qdev, unsigned long physical) + { +- QXL_INFO(qdev, "not implemented (%lu)\n", physical); ++ DRM_DEBUG_DRIVER("not implemented (%lu)\n", physical); + return 0; + } + +diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c +index 844c4a31ca13..23af3e352673 100644 +--- a/drivers/gpu/drm/qxl/qxl_fb.c ++++ b/drivers/gpu/drm/qxl/qxl_fb.c +@@ -240,18 +240,15 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev, + return ret; + + qbo = gem_to_qxl_bo(gobj); +- QXL_INFO(qdev, "%s: %dx%d %d\n", __func__, mode_cmd.width, +- mode_cmd.height, mode_cmd.pitches[0]); ++ DRM_DEBUG_DRIVER("%dx%d %d\n", mode_cmd.width, ++ mode_cmd.height, mode_cmd.pitches[0]); + + shadow = vmalloc(mode_cmd.pitches[0] * mode_cmd.height); + /* TODO: what's the usual response to memory allocation errors? */ + BUG_ON(!shadow); +- QXL_INFO(qdev, +- "surface0 at gpu offset %lld, mmap_offset %lld (virt %p, shadow %p)\n", +- qxl_bo_gpu_offset(qbo), +- qxl_bo_mmap_offset(qbo), +- qbo->kptr, +- shadow); ++ DRM_DEBUG_DRIVER("surface0 at gpu offset %lld, mmap_offset %lld (virt %p, shadow %p)\n", ++ qxl_bo_gpu_offset(qbo), qxl_bo_mmap_offset(qbo), ++ qbo->kptr, shadow); + size = mode_cmd.pitches[0] * mode_cmd.height; + + info = drm_fb_helper_alloc_fbi(&qfbdev->helper); +diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c +index e6ec845b5be0..a6da6fa6ad58 100644 +--- a/drivers/gpu/drm/qxl/qxl_release.c ++++ b/drivers/gpu/drm/qxl/qxl_release.c +@@ -154,7 +154,7 @@ qxl_release_alloc(struct qxl_device *qdev, int type, + return handle; + } + *ret = release; +- QXL_INFO(qdev, "allocated release %d\n", handle); ++ DRM_DEBUG_DRIVER("allocated release %d\n", handle); + release->id = handle; + return handle; + } +@@ -179,8 +179,7 @@ void + qxl_release_free(struct qxl_device *qdev, + struct qxl_release *release) + { +- QXL_INFO(qdev, "release %d, type %d\n", release->id, +- release->type); ++ DRM_DEBUG_DRIVER("release %d, type %d\n", release->id, release->type); + + if (release->surface_release_id) + qxl_surface_id_dealloc(qdev, release->surface_release_id); +diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c +index 7ecf8a4b9fe6..ab4823875311 100644 +--- a/drivers/gpu/drm/qxl/qxl_ttm.c ++++ b/drivers/gpu/drm/qxl/qxl_ttm.c +@@ -136,8 +136,8 @@ int qxl_mmap(struct file *filp, struct vm_area_struct *vma) + "filp->private_data->minor->dev->dev_private == NULL\n"); + return -EINVAL; + } +- QXL_INFO(qdev, "%s: filp->private_data = 0x%p, vma->vm_pgoff = %lx\n", +- __func__, filp->private_data, vma->vm_pgoff); ++ DRM_DEBUG_DRIVER("filp->private_data = 0x%p, vma->vm_pgoff = %lx\n", ++ filp->private_data, vma->vm_pgoff); + + r = ttm_bo_mmap(filp, vma, &qdev->mman.bdev); + if (unlikely(r != 0)) +-- +2.14.3 + +From 62676d10b483a2ff6e8b08c5e7c7d63a831343f5 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann <kraxel@redhat.com> +Date: Thu, 19 Oct 2017 08:21:50 +0200 +Subject: [PATCH] qxl: alloc & use shadow for dumb buffers + +This patch changes the way the primary surface is used for dumb +framebuffers. Instead of configuring the bo itself as primary surface +a shadow bo is created and used instead. Framebuffers can share the +shadow bo in case they have the same format and resolution. + +On atomic plane updates we don't have to update the primary surface in +case we pageflip from one framebuffer to another framebuffer which +shares the same shadow. This in turn avoids the flicker caused by the +primary-destroy + primary-create cycle, which is very annonying when +running wayland on qxl. + +The qxl driver never actually writes to the shadow bo. It sends qxl +blit commands which update it though, and the spice server might +actually execute them (and thereby write to the shadow) in case the +local rendering is kicked for some reason. This happens for example in +case qemu is asked to write out a dump of the guest display (screendump +monitor command). + +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +Reviewed-by: Dave Airlie <airlied@redhat.com> +Link: http://patchwork.freedesktop.org/patch/msgid/20171019062150.28090-3-kraxel@redhat.com +--- + drivers/gpu/drm/qxl/qxl_cmd.c | 6 ++++- + drivers/gpu/drm/qxl/qxl_display.c | 49 ++++++++++++++++++++++++++++++++++++--- + drivers/gpu/drm/qxl/qxl_drv.h | 2 ++ + drivers/gpu/drm/qxl/qxl_dumb.c | 1 + + 4 files changed, 54 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c +index 8ec53d5abd62..c0fb52c6d4ca 100644 +--- a/drivers/gpu/drm/qxl/qxl_cmd.c ++++ b/drivers/gpu/drm/qxl/qxl_cmd.c +@@ -387,7 +387,11 @@ void qxl_io_create_primary(struct qxl_device *qdev, + create->width = bo->surf.width; + create->height = bo->surf.height; + create->stride = bo->surf.stride; +- create->mem = qxl_bo_physical_address(qdev, bo, offset); ++ if (bo->shadow) { ++ create->mem = qxl_bo_physical_address(qdev, bo->shadow, offset); ++ } else { ++ create->mem = qxl_bo_physical_address(qdev, bo, offset); ++ } + + DRM_DEBUG_DRIVER("mem = %llx, from %p\n", create->mem, bo->kptr); + +diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c +index afbf50d0c08f..4756b3c9bf2c 100644 +--- a/drivers/gpu/drm/qxl/qxl_display.c ++++ b/drivers/gpu/drm/qxl/qxl_display.c +@@ -305,7 +305,9 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = { + void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb) + { + struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb); ++ struct qxl_bo *bo = gem_to_qxl_bo(qxl_fb->obj); + ++ WARN_ON(bo->shadow); + drm_gem_object_unreference_unlocked(qxl_fb->obj); + drm_framebuffer_cleanup(fb); + kfree(qxl_fb); +@@ -508,6 +510,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane, + .x2 = qfb->base.width, + .y2 = qfb->base.height + }; ++ bool same_shadow = false; + + if (old_state->fb) { + qfb_old = to_qxl_framebuffer(old_state->fb); +@@ -519,15 +522,23 @@ static void qxl_primary_atomic_update(struct drm_plane *plane, + if (bo == bo_old) + return; + ++ if (bo_old && bo_old->shadow && bo->shadow && ++ bo_old->shadow == bo->shadow) { ++ same_shadow = true; ++ } ++ + if (bo_old && bo_old->is_primary) { +- qxl_io_destroy_primary(qdev); ++ if (!same_shadow) ++ qxl_io_destroy_primary(qdev); + bo_old->is_primary = false; + } + + if (!bo->is_primary) { +- qxl_io_create_primary(qdev, 0, bo); ++ if (!same_shadow) ++ qxl_io_create_primary(qdev, 0, bo); + bo->is_primary = true; + } ++ + qxl_draw_dirty_fb(qdev, qfb, bo, 0, 0, &norect, 1, 1); + } + +@@ -679,8 +690,9 @@ static void qxl_cursor_atomic_disable(struct drm_plane *plane, + static int qxl_plane_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *new_state) + { ++ struct qxl_device *qdev = plane->dev->dev_private; + struct drm_gem_object *obj; +- struct qxl_bo *user_bo; ++ struct qxl_bo *user_bo, *old_bo = NULL; + int ret; + + if (!new_state->fb) +@@ -689,6 +701,32 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane, + obj = to_qxl_framebuffer(new_state->fb)->obj; + user_bo = gem_to_qxl_bo(obj); + ++ if (plane->type == DRM_PLANE_TYPE_PRIMARY && ++ user_bo->is_dumb && !user_bo->shadow) { ++ if (plane->state->fb) { ++ obj = to_qxl_framebuffer(plane->state->fb)->obj; ++ old_bo = gem_to_qxl_bo(obj); ++ } ++ if (old_bo && old_bo->shadow && ++ user_bo->gem_base.size == old_bo->gem_base.size && ++ plane->state->crtc == new_state->crtc && ++ plane->state->crtc_w == new_state->crtc_w && ++ plane->state->crtc_h == new_state->crtc_h && ++ plane->state->src_x == new_state->src_x && ++ plane->state->src_y == new_state->src_y && ++ plane->state->src_w == new_state->src_w && ++ plane->state->src_h == new_state->src_h && ++ plane->state->rotation == new_state->rotation && ++ plane->state->zpos == new_state->zpos) { ++ drm_gem_object_get(&old_bo->shadow->gem_base); ++ user_bo->shadow = old_bo->shadow; ++ } else { ++ qxl_bo_create(qdev, user_bo->gem_base.size, ++ true, true, QXL_GEM_DOMAIN_VRAM, NULL, ++ &user_bo->shadow); ++ } ++ } ++ + ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL); + if (ret) + return ret; +@@ -713,6 +751,11 @@ static void qxl_plane_cleanup_fb(struct drm_plane *plane, + obj = to_qxl_framebuffer(old_state->fb)->obj; + user_bo = gem_to_qxl_bo(obj); + qxl_bo_unpin(user_bo); ++ ++ if (user_bo->shadow && !user_bo->is_primary) { ++ drm_gem_object_put_unlocked(&user_bo->shadow->gem_base); ++ user_bo->shadow = NULL; ++ } + } + + static const uint32_t qxl_cursor_plane_formats[] = { +diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h +index d707b351875c..08752c0ffb35 100644 +--- a/drivers/gpu/drm/qxl/qxl_drv.h ++++ b/drivers/gpu/drm/qxl/qxl_drv.h +@@ -89,6 +89,8 @@ struct qxl_bo { + /* Constant after initialization */ + struct drm_gem_object gem_base; + bool is_primary; /* is this now a primary surface */ ++ bool is_dumb; ++ struct qxl_bo *shadow; + bool hw_surf_alloc; + struct qxl_surface surf; + uint32_t surface_id; +diff --git a/drivers/gpu/drm/qxl/qxl_dumb.c b/drivers/gpu/drm/qxl/qxl_dumb.c +index 5e65d5d2d937..11085ab01374 100644 +--- a/drivers/gpu/drm/qxl/qxl_dumb.c ++++ b/drivers/gpu/drm/qxl/qxl_dumb.c +@@ -63,6 +63,7 @@ int qxl_mode_dumb_create(struct drm_file *file_priv, + &handle); + if (r) + return r; ++ qobj->is_dumb = true; + args->pitch = pitch; + args->handle = handle; + return 0; +-- +2.14.3 + |