]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Jun 2016 05:22:49 +0000 (22:22 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Jun 2016 05:22:49 +0000 (22:22 -0700)
added patches:
drm-core-do-not-preserve-framebuffer-on-rmfb-v4.patch

queue-4.4/drm-core-do-not-preserve-framebuffer-on-rmfb-v4.patch [new file with mode: 0644]
queue-4.4/series

diff --git a/queue-4.4/drm-core-do-not-preserve-framebuffer-on-rmfb-v4.patch b/queue-4.4/drm-core-do-not-preserve-framebuffer-on-rmfb-v4.patch
new file mode 100644 (file)
index 0000000..4bd2ad4
--- /dev/null
@@ -0,0 +1,143 @@
+From f2d580b9a8149735cbc4b59c4a8df60173658140 Mon Sep 17 00:00:00 2001
+From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Date: Wed, 4 May 2016 14:38:26 +0200
+Subject: drm/core: Do not preserve framebuffer on rmfb, v4.
+
+From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+
+commit f2d580b9a8149735cbc4b59c4a8df60173658140 upstream.
+
+It turns out that preserving framebuffers after the rmfb call breaks
+vmwgfx userspace. This was originally introduced because it was thought
+nobody relied on the behavior, but unfortunately it seems there are
+exceptions.
+
+drm_framebuffer_remove may fail with -EINTR now, so a straight revert
+is impossible. There is no way to remove the framebuffer from the lists
+and active planes without introducing a race because of the different
+locking requirements. Instead call drm_framebuffer_remove from a
+workqueue, which is unaffected by signals.
+
+Changes since v1:
+- Add comment.
+Changes since v2:
+- Add fastpath for refcount = 1. (danvet)
+Changes since v3:
+- Rebased.
+- Restore lastclose framebuffer removal too.
+
+Fixes: 13803132818c ("drm/core: Preserve the framebuffer after removing it.")
+Testcase: kms_rmfb_basic
+References: https://lists.freedesktop.org/archives/dri-devel/2016-March/102876.html
+Cc: Thomas Hellstrom <thellstrom@vmware.com>
+Cc: David Herrmann <dh.herrmann@gmail.com>
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Tested-by: Thomas Hellstrom <thellstrom@vmware.com> #v3
+Tested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Link: http://patchwork.freedesktop.org/patch/msgid/6c63ca37-0e7e-ac7f-a6d2-c7822e3d611f@linux.intel.com
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_crtc.c |   60 +++++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 55 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpu/drm/drm_crtc.c
++++ b/drivers/gpu/drm/drm_crtc.c
+@@ -3316,6 +3316,24 @@ int drm_mode_addfb2(struct drm_device *d
+       return 0;
+ }
++struct drm_mode_rmfb_work {
++      struct work_struct work;
++      struct list_head fbs;
++};
++
++static void drm_mode_rmfb_work_fn(struct work_struct *w)
++{
++      struct drm_mode_rmfb_work *arg = container_of(w, typeof(*arg), work);
++
++      while (!list_empty(&arg->fbs)) {
++              struct drm_framebuffer *fb =
++                      list_first_entry(&arg->fbs, typeof(*fb), filp_head);
++
++              list_del_init(&fb->filp_head);
++              drm_framebuffer_remove(fb);
++      }
++}
++
+ /**
+  * drm_mode_rmfb - remove an FB from the configuration
+  * @dev: drm device for the ioctl
+@@ -3356,7 +3374,25 @@ int drm_mode_rmfb(struct drm_device *dev
+       mutex_unlock(&dev->mode_config.fb_lock);
+       mutex_unlock(&file_priv->fbs_lock);
+-      drm_framebuffer_unreference(fb);
++      /*
++       * we now own the reference that was stored in the fbs list
++       *
++       * drm_framebuffer_remove may fail with -EINTR on pending signals,
++       * so run this in a separate stack as there's no way to correctly
++       * handle this after the fb is already removed from the lookup table.
++       */
++      if (atomic_read(&fb->refcount.refcount) > 1) {
++              struct drm_mode_rmfb_work arg;
++
++              INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
++              INIT_LIST_HEAD(&arg.fbs);
++              list_add_tail(&fb->filp_head, &arg.fbs);
++
++              schedule_work(&arg.work);
++              flush_work(&arg.work);
++              destroy_work_on_stack(&arg.work);
++      } else
++              drm_framebuffer_unreference(fb);
+       return 0;
+@@ -3509,7 +3545,6 @@ out_err1:
+       return ret;
+ }
+-
+ /**
+  * drm_fb_release - remove and free the FBs on this file
+  * @priv: drm file for the ioctl
+@@ -3524,6 +3559,9 @@ out_err1:
+ void drm_fb_release(struct drm_file *priv)
+ {
+       struct drm_framebuffer *fb, *tfb;
++      struct drm_mode_rmfb_work arg;
++
++      INIT_LIST_HEAD(&arg.fbs);
+       /*
+        * When the file gets released that means no one else can access the fb
+@@ -3536,10 +3574,22 @@ void drm_fb_release(struct drm_file *pri
+        * at it any more.
+        */
+       list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
+-              list_del_init(&fb->filp_head);
++              if (atomic_read(&fb->refcount.refcount) > 1) {
++                      list_move_tail(&fb->filp_head, &arg.fbs);
++              } else {
++                      list_del_init(&fb->filp_head);
+-              /* This drops the fpriv->fbs reference. */
+-              drm_framebuffer_unreference(fb);
++                      /* This drops the fpriv->fbs reference. */
++                      drm_framebuffer_unreference(fb);
++              }
++      }
++
++      if (!list_empty(&arg.fbs)) {
++              INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
++
++              schedule_work(&arg.work);
++              flush_work(&arg.work);
++              destroy_work_on_stack(&arg.work);
+       }
+ }
index 8500a0cb1b5610875036036ed577228881e31e85..16d158f598277cdb341ca064760037cf1730d444 100644 (file)
@@ -62,3 +62,4 @@ netfilter-x_tables-validate-e-target_offset-early.patch
 netfilter-x_tables-make-sure-e-next_offset-covers-remaining-blob-size.patch
 netfilter-x_tables-fix-unconditional-helper.patch
 crypto-qat-fix-adf_ctl_drv.c-undefined-reference-to-adf_init_pf_wq.patch
+drm-core-do-not-preserve-framebuffer-on-rmfb-v4.patch