--- /dev/null
+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
+@@ -3434,6 +3434,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
+@@ -3474,7 +3492,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;
+
+@@ -3627,7 +3663,6 @@ out_err1:
+ return ret;
+ }
+
+-
+ /**
+ * drm_fb_release - remove and free the FBs on this file
+ * @priv: drm file for the ioctl
+@@ -3642,6 +3677,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
+@@ -3654,10 +3692,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);
+ }
+ }
+
--- /dev/null
+From 615d23f80efc60f8c5146223f305d19207c742e4 Mon Sep 17 00:00:00 2001
+From: Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
+Date: Mon, 4 Apr 2016 23:44:06 +0530
+Subject: gpio: zynq: Fix the error path
+
+From: Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
+
+commit 615d23f80efc60f8c5146223f305d19207c742e4 upstream.
+
+pm_runtime_disable is called only in remove it is missed
+out in the error path.
+Fix the same.
+
+Signed-off-by: Shubhrajyoti Datta <shubhraj@xilinx.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Cc: Helmut Grohne <h.grohne@intenta.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpio/gpio-zynq.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpio/gpio-zynq.c
++++ b/drivers/gpio/gpio-zynq.c
+@@ -713,7 +713,7 @@ static int zynq_gpio_probe(struct platfo
+ pm_runtime_enable(&pdev->dev);
+ ret = pm_runtime_get_sync(&pdev->dev);
+ if (ret < 0)
+- return ret;
++ goto err_pm_dis;
+
+ /* report a bug if gpio chip registration fails */
+ ret = gpiochip_add_data(chip, gpio);
+@@ -745,6 +745,8 @@ err_rm_gpiochip:
+ gpiochip_remove(chip);
+ err_pm_put:
+ pm_runtime_put(&pdev->dev);
++err_pm_dis:
++ pm_runtime_disable(&pdev->dev);
+
+ return ret;
+ }
--- /dev/null
+From 0f84f29ff30bdb1bca23017b118b4ea3999cac32 Mon Sep 17 00:00:00 2001
+From: Helmut Grohne <h.grohne@intenta.de>
+Date: Fri, 3 Jun 2016 14:15:32 +0200
+Subject: gpio: zynq: initialize clock even without CONFIG_PM
+
+From: Helmut Grohne <h.grohne@intenta.de>
+
+commit 0f84f29ff30bdb1bca23017b118b4ea3999cac32 upstream.
+
+When the PM initialization was moved in the commit referenced below, the
+code enabling the clock was removed from the probe function. On
+CONFIG_PM=y kernels, this is not a problem as the pm resume hook enables
+the clock, but when power management is disabled, all those pm_*
+functions are noops and the clock is never enabled resulting in a
+dysfunctional gpio controller.
+
+Put the clock initialization back to support CONFIG_PM=n.
+
+Signed-off-by: Helmut Grohne <h.grohne@intenta.de>
+Fixes: 3773c195d387 ("gpio: zynq: Do PM initialization earlier to support gpio hogs")
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpio/gpio-zynq.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/gpio/gpio-zynq.c
++++ b/drivers/gpio/gpio-zynq.c
+@@ -709,7 +709,13 @@ static int zynq_gpio_probe(struct platfo
+ dev_err(&pdev->dev, "input clock not found.\n");
+ return PTR_ERR(gpio->clk);
+ }
++ ret = clk_prepare_enable(gpio->clk);
++ if (ret) {
++ dev_err(&pdev->dev, "Unable to enable clock.\n");
++ return ret;
++ }
+
++ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ ret = pm_runtime_get_sync(&pdev->dev);
+ if (ret < 0)
+@@ -747,6 +753,7 @@ err_pm_put:
+ pm_runtime_put(&pdev->dev);
+ err_pm_dis:
+ pm_runtime_disable(&pdev->dev);
++ clk_disable_unprepare(gpio->clk);
+
+ return ret;
+ }