From: Greg Kroah-Hartman Date: Wed, 22 Jun 2016 05:22:49 +0000 (-0700) Subject: 4.4-stable patches X-Git-Tag: v3.14.73~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b607fb54e730b6e0f072d779990b679a23121d8f;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: drm-core-do-not-preserve-framebuffer-on-rmfb-v4.patch --- 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 index 00000000000..4bd2ad4da87 --- /dev/null +++ b/queue-4.4/drm-core-do-not-preserve-framebuffer-on-rmfb-v4.patch @@ -0,0 +1,143 @@ +From f2d580b9a8149735cbc4b59c4a8df60173658140 Mon Sep 17 00:00:00 2001 +From: Maarten Lankhorst +Date: Wed, 4 May 2016 14:38:26 +0200 +Subject: drm/core: Do not preserve framebuffer on rmfb, v4. + +From: Maarten Lankhorst + +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 +Cc: David Herrmann +Reviewed-by: Daniel Vetter +Tested-by: Thomas Hellstrom #v3 +Tested-by: Tvrtko Ursulin +Signed-off-by: Daniel Vetter +Link: http://patchwork.freedesktop.org/patch/msgid/6c63ca37-0e7e-ac7f-a6d2-c7822e3d611f@linux.intel.com +Signed-off-by: Hans de Goede +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + } + } + diff --git a/queue-4.4/series b/queue-4.4/series index 8500a0cb1b5..16d158f5982 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -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