]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 1 Mar 2016 21:24:39 +0000 (13:24 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 1 Mar 2016 21:24:39 +0000 (13:24 -0800)
added patches:
drm-fix-drm_vblank_pre-post_modeset-regression-from-linux-4.4.patch
drm-fix-treatment-of-drm_vblank_offdelay-in-drm_vblank_on-v2.patch
drm-no-op-redundant-calls-to-drm_vblank_off-v2.patch
drm-prevent-vblank-counter-bumps-1-with-active-vblank-clients.-v2.patch
drm-qxl-use-kmalloc_array-to-alloc-reloc_info-in-qxl_process_single_command.patch
drm-radeon-don-t-hang-in-radeon_flip_work_func-on-disabled-crtc.-v2.patch
drm-radeon-pm-adjust-display-configuration-after-powerstate.patch
drm-radeon-use-post-decrement-in-error-handling.patch
make-sure-that-freeing-shmem-fast-symlinks-is-rcu-delayed.patch

queue-4.4/drm-fix-drm_vblank_pre-post_modeset-regression-from-linux-4.4.patch [new file with mode: 0644]
queue-4.4/drm-fix-treatment-of-drm_vblank_offdelay-in-drm_vblank_on-v2.patch [new file with mode: 0644]
queue-4.4/drm-no-op-redundant-calls-to-drm_vblank_off-v2.patch [new file with mode: 0644]
queue-4.4/drm-prevent-vblank-counter-bumps-1-with-active-vblank-clients.-v2.patch [new file with mode: 0644]
queue-4.4/drm-qxl-use-kmalloc_array-to-alloc-reloc_info-in-qxl_process_single_command.patch [new file with mode: 0644]
queue-4.4/drm-radeon-don-t-hang-in-radeon_flip_work_func-on-disabled-crtc.-v2.patch [new file with mode: 0644]
queue-4.4/drm-radeon-pm-adjust-display-configuration-after-powerstate.patch [new file with mode: 0644]
queue-4.4/drm-radeon-use-post-decrement-in-error-handling.patch [new file with mode: 0644]
queue-4.4/make-sure-that-freeing-shmem-fast-symlinks-is-rcu-delayed.patch [new file with mode: 0644]
queue-4.4/series

diff --git a/queue-4.4/drm-fix-drm_vblank_pre-post_modeset-regression-from-linux-4.4.patch b/queue-4.4/drm-fix-drm_vblank_pre-post_modeset-regression-from-linux-4.4.patch
new file mode 100644 (file)
index 0000000..69f9ff2
--- /dev/null
@@ -0,0 +1,83 @@
+From c61934ed9a0e3911a9935df26858726a7ec35ec0 Mon Sep 17 00:00:00 2001
+From: Mario Kleiner <mario.kleiner.de@gmail.com>
+Date: Fri, 12 Feb 2016 20:30:29 +0100
+Subject: drm: Fix drm_vblank_pre/post_modeset regression from Linux 4.4
+
+From: Mario Kleiner <mario.kleiner.de@gmail.com>
+
+commit c61934ed9a0e3911a9935df26858726a7ec35ec0 upstream.
+
+Changes to drm_update_vblank_count() in Linux 4.4 broke the
+behaviour of the pre/post modeset functions as the new update
+code doesn't deal with hw vblank counter resets inbetween calls
+to drm_vblank_pre_modeset an drm_vblank_post_modeset, as it
+should.
+
+This causes mistreatment of such hw counter resets as counter
+wraparound, and thereby large forward jumps of the software
+vblank counter which in turn cause vblank event dispatching
+and vblank waits to fail/hang --> userspace clients hang.
+
+This symptom was reported on radeon-kms to cause a infinite
+hang of KDE Plasma 5 shell's login procedure, preventing users
+from logging in.
+
+Fix this by detecting when drm_update_vblank_count() is called
+inside a pre->post modeset interval. If so, clamp valid vblank
+increments to the safe values 0 and 1, pretty much restoring
+the update behavior of the old update code of Linux 4.3 and
+earlier. Also reset the last recorded hw vblank count at call
+to drm_vblank_post_modeset() to be safe against hw that after
+modesetting, dpms on etc. only fires its first vblank irq after
+drm_vblank_post_modeset() was already called.
+
+Reported-by: Vlastimil Babka <vbabka@suse.cz>
+Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Tested-by: Vlastimil Babka <vbabka@suse.cz>
+Cc: michel@daenzer.net
+Cc: vbabka@suse.cz
+Cc: ville.syrjala@linux.intel.com
+Cc: daniel.vetter@ffwll.ch
+Cc: dri-devel@lists.freedesktop.org
+Cc: alexander.deucher@amd.com
+Cc: christian.koenig@amd.com
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_irq.c |   16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/drivers/gpu/drm/drm_irq.c
++++ b/drivers/gpu/drm/drm_irq.c
+@@ -222,6 +222,21 @@ static void drm_update_vblank_count(stru
+       }
+       /*
++       * Within a drm_vblank_pre_modeset - drm_vblank_post_modeset
++       * interval? If so then vblank irqs keep running and it will likely
++       * happen that the hardware vblank counter is not trustworthy as it
++       * might reset at some point in that interval and vblank timestamps
++       * are not trustworthy either in that interval. Iow. this can result
++       * in a bogus diff >> 1 which must be avoided as it would cause
++       * random large forward jumps of the software vblank counter.
++       */
++      if (diff > 1 && (vblank->inmodeset & 0x2)) {
++              DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u"
++                            " due to pre-modeset.\n", pipe, diff);
++              diff = 1;
++      }
++
++      /*
+        * FIMXE: Need to replace this hack with proper seqlocks.
+        *
+        * Restrict the bump of the software vblank counter to a safe maximum
+@@ -1575,6 +1590,7 @@ void drm_vblank_post_modeset(struct drm_
+       if (vblank->inmodeset) {
+               spin_lock_irqsave(&dev->vbl_lock, irqflags);
+               dev->vblank_disable_allowed = true;
++              drm_reset_vblank_timestamp(dev, pipe);
+               spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+               if (vblank->inmodeset & 0x2)
diff --git a/queue-4.4/drm-fix-treatment-of-drm_vblank_offdelay-in-drm_vblank_on-v2.patch b/queue-4.4/drm-fix-treatment-of-drm_vblank_offdelay-in-drm_vblank_on-v2.patch
new file mode 100644 (file)
index 0000000..ddac3fc
--- /dev/null
@@ -0,0 +1,65 @@
+From bb74fc1bf3072bd3ab4ed5f43afd287a63baf2d7 Mon Sep 17 00:00:00 2001
+From: Mario Kleiner <mario.kleiner.de@gmail.com>
+Date: Fri, 12 Feb 2016 20:30:30 +0100
+Subject: drm: Fix treatment of drm_vblank_offdelay in drm_vblank_on() (v2)
+
+From: Mario Kleiner <mario.kleiner.de@gmail.com>
+
+commit bb74fc1bf3072bd3ab4ed5f43afd287a63baf2d7 upstream.
+
+drm_vblank_offdelay can have three different types of values:
+
+< 0 is to be always treated the same as dev->vblank_disable_immediate
+= 0 is to be treated as "never disable vblanks"
+> 0 is to be treated as disable immediate if kms driver wants it
+    that way via dev->vblank_disable_immediate. Otherwise it is
+    a disable timeout in msecs.
+
+This got broken in Linux 3.18+ for the implementation of
+drm_vblank_on. If the user specified a value of zero which should
+always reenable vblank irqs in this function, a kms driver could
+override the users choice by setting vblank_disable_immediate
+to true. This patch fixes the regression and keeps the user in
+control.
+
+v2: Only reenable vblank if there are clients left or the user
+    requested to "never disable vblanks" via offdelay 0. Enabling
+    vblanks even in the "delayed disable" case (offdelay > 0) was
+    specifically added by Ville in commit cd19e52aee922
+    ("drm: Kick start vblank interrupts at drm_vblank_on()"),
+    but after discussion it turns out that this was done by accident.
+
+    Citing Ville: "I think it just ended up as a mess due to changing
+    some of the semantics of offdelay<0 vs. offdelay==0 vs.
+    disable_immediate during the review of the series. So yeah, given
+    how drm_vblank_put() works now, I'd just make this check for
+    offdelay==0."
+
+Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Cc: michel@daenzer.net
+Cc: vbabka@suse.cz
+Cc: ville.syrjala@linux.intel.com
+Cc: daniel.vetter@ffwll.ch
+Cc: dri-devel@lists.freedesktop.org
+Cc: alexander.deucher@amd.com
+Cc: christian.koenig@amd.com
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_irq.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/drm_irq.c
++++ b/drivers/gpu/drm/drm_irq.c
+@@ -1494,8 +1494,7 @@ void drm_vblank_on(struct drm_device *de
+        * re-enable interrupts if there are users left, or the
+        * user wishes vblank interrupts to be enabled all the time.
+        */
+-      if (atomic_read(&vblank->refcount) != 0 ||
+-          (!dev->vblank_disable_immediate && drm_vblank_offdelay == 0))
++      if (atomic_read(&vblank->refcount) != 0 || drm_vblank_offdelay == 0)
+               WARN_ON(drm_vblank_enable(dev, pipe));
+       spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+ }
diff --git a/queue-4.4/drm-no-op-redundant-calls-to-drm_vblank_off-v2.patch b/queue-4.4/drm-no-op-redundant-calls-to-drm_vblank_off-v2.patch
new file mode 100644 (file)
index 0000000..2a8fd11
--- /dev/null
@@ -0,0 +1,75 @@
+From e8235891b33799d597ff4ab5e45afe173a65da30 Mon Sep 17 00:00:00 2001
+From: Mario Kleiner <mario.kleiner.de@gmail.com>
+Date: Fri, 12 Feb 2016 20:30:27 +0100
+Subject: drm: No-Op redundant calls to drm_vblank_off() (v2)
+
+From: Mario Kleiner <mario.kleiner.de@gmail.com>
+
+commit e8235891b33799d597ff4ab5e45afe173a65da30 upstream.
+
+Otherwise if a kms driver calls into drm_vblank_off() more than once
+before calling drm_vblank_on() again, the redundant calls to
+vblank_disable_and_save() will call drm_update_vblank_count()
+while hw vblank counters and vblank timestamping are in a undefined
+state during modesets, dpms off etc.
+
+At least with the legacy drm helpers it is not unusual to
+get multiple calls to drm_vblank_off and drm_vblank_on, e.g.,
+half a dozen calls to drm_vblank_off and two calls to drm_vblank_on
+were observed on radeon-kms during dpms-off -> dpms-on transition.
+
+We don't no-op calls from atomic modesetting drivers, as they
+should do a proper job of tracking hw state.
+
+Fixes large jumps of the software maintained vblank counter due to
+the hardware vblank counter resetting to zero during dpms off or
+modeset, e.g., if radeon-kms is modified to use drm_vblank_off/on
+instead of drm_vblank_pre/post_modeset().
+
+This fixes a regression caused by the changes made to
+drm_update_vblank_count() in Linux 4.4.
+
+v2: Don't no-op on atomic modesetting drivers, per suggestion
+    of Daniel Vetter.
+
+Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Cc: michel@daenzer.net
+Cc: vbabka@suse.cz
+Cc: ville.syrjala@linux.intel.com
+Cc: alexander.deucher@amd.com
+Cc: christian.koenig@amd.com
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_irq.c |   11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/drm_irq.c
++++ b/drivers/gpu/drm/drm_irq.c
+@@ -1313,7 +1313,13 @@ void drm_vblank_off(struct drm_device *d
+       spin_lock_irqsave(&dev->event_lock, irqflags);
+       spin_lock(&dev->vbl_lock);
+-      vblank_disable_and_save(dev, pipe);
++      DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n",
++                    pipe, vblank->enabled, vblank->inmodeset);
++
++      /* Avoid redundant vblank disables without previous drm_vblank_on(). */
++      if (drm_core_check_feature(dev, DRIVER_ATOMIC) || !vblank->inmodeset)
++              vblank_disable_and_save(dev, pipe);
++
+       wake_up(&vblank->queue);
+       /*
+@@ -1415,6 +1421,9 @@ void drm_vblank_on(struct drm_device *de
+               return;
+       spin_lock_irqsave(&dev->vbl_lock, irqflags);
++      DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n",
++                    pipe, vblank->enabled, vblank->inmodeset);
++
+       /* Drop our private "prevent drm_vblank_get" refcount */
+       if (vblank->inmodeset) {
+               atomic_dec(&vblank->refcount);
diff --git a/queue-4.4/drm-prevent-vblank-counter-bumps-1-with-active-vblank-clients.-v2.patch b/queue-4.4/drm-prevent-vblank-counter-bumps-1-with-active-vblank-clients.-v2.patch
new file mode 100644 (file)
index 0000000..82bb0e6
--- /dev/null
@@ -0,0 +1,122 @@
+From 99b8e71597fadd6b2ac85e6e10f221f79dd9c1c1 Mon Sep 17 00:00:00 2001
+From: Mario Kleiner <mario.kleiner.de@gmail.com>
+Date: Fri, 12 Feb 2016 20:30:28 +0100
+Subject: drm: Prevent vblank counter bumps > 1 with active vblank clients. (v2)
+
+From: Mario Kleiner <mario.kleiner.de@gmail.com>
+
+commit 99b8e71597fadd6b2ac85e6e10f221f79dd9c1c1 upstream.
+
+This fixes a regression introduced by the new drm_update_vblank_count()
+implementation in Linux 4.4:
+
+Restrict the bump of the software vblank counter in drm_update_vblank_count()
+to a safe maximum value of +1 whenever there is the possibility that
+concurrent readers of vblank timestamps could be active at the moment,
+as the current implementation of the timestamp caching and updating is
+not safe against concurrent readers for calls to store_vblank() with a
+bump of anything but +1. A bump != 1 would very likely return corrupted
+timestamps to userspace, because the same slot in the cache could
+be concurrently written by store_vblank() and read by one of those
+readers in a non-atomic fashion and without the read-retry logic
+detecting this collision.
+
+Concurrent readers can exist while drm_update_vblank_count() is called
+from the drm_vblank_off() or drm_vblank_on() functions or other non-vblank-
+irq callers. However, all those calls are happening with the vbl_lock
+locked thereby preventing a drm_vblank_get(), so the vblank refcount
+can't increase while drm_update_vblank_count() is executing. Therefore
+a zero vblank refcount during execution of that function signals that
+is safe for arbitrary counter bumps if called from outside vblank irq,
+whereas a non-zero count is not safe.
+
+Whenever the function is called from vblank irq, we have to assume concurrent
+readers could show up any time during its execution, even if the refcount
+is currently zero, as vblank irqs are usually only enabled due to the
+presence of readers, and because when it is called from vblank irq it
+can't hold the vbl_lock to protect it from sudden bumps in vblank refcount.
+Therefore also restrict bumps to +1 when the function is called from vblank
+irq.
+
+Such bumps of more than +1 can happen at other times than reenabling
+vblank irqs, e.g., when regular vblank interrupts get delayed by more
+than 1 frame due to long held locks, long irq off periods, realtime
+preemption on RT kernels, or system management interrupts.
+
+A better solution would be to rewrite the timestamp caching to use
+full seqlocks to allow concurrent writes and reads for arbitrary
+vblank counter increments.
+
+v2: Add code comment that this is essentially a hack and should
+    be replaced by a full seqlock implementation for caching of
+    timestamps.
+
+Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+Cc: michel@daenzer.net
+Cc: vbabka@suse.cz
+Cc: ville.syrjala@linux.intel.com
+Cc: daniel.vetter@ffwll.ch
+Cc: dri-devel@lists.freedesktop.org
+Cc: alexander.deucher@amd.com
+Cc: christian.koenig@amd.com
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+
+---
+ drivers/gpu/drm/drm_irq.c |   43 +++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 43 insertions(+)
+
+--- a/drivers/gpu/drm/drm_irq.c
++++ b/drivers/gpu/drm/drm_irq.c
+@@ -221,6 +221,49 @@ static void drm_update_vblank_count(stru
+               diff = (flags & DRM_CALLED_FROM_VBLIRQ) != 0;
+       }
++      /*
++       * FIMXE: Need to replace this hack with proper seqlocks.
++       *
++       * Restrict the bump of the software vblank counter to a safe maximum
++       * value of +1 whenever there is the possibility that concurrent readers
++       * of vblank timestamps could be active at the moment, as the current
++       * implementation of the timestamp caching and updating is not safe
++       * against concurrent readers for calls to store_vblank() with a bump
++       * of anything but +1. A bump != 1 would very likely return corrupted
++       * timestamps to userspace, because the same slot in the cache could
++       * be concurrently written by store_vblank() and read by one of those
++       * readers without the read-retry logic detecting the collision.
++       *
++       * Concurrent readers can exist when we are called from the
++       * drm_vblank_off() or drm_vblank_on() functions and other non-vblank-
++       * irq callers. However, all those calls to us are happening with the
++       * vbl_lock locked to prevent drm_vblank_get(), so the vblank refcount
++       * can't increase while we are executing. Therefore a zero refcount at
++       * this point is safe for arbitrary counter bumps if we are called
++       * outside vblank irq, a non-zero count is not 100% safe. Unfortunately
++       * we must also accept a refcount of 1, as whenever we are called from
++       * drm_vblank_get() -> drm_vblank_enable() the refcount will be 1 and
++       * we must let that one pass through in order to not lose vblank counts
++       * during vblank irq off - which would completely defeat the whole
++       * point of this routine.
++       *
++       * Whenever we are called from vblank irq, we have to assume concurrent
++       * readers exist or can show up any time during our execution, even if
++       * the refcount is currently zero, as vblank irqs are usually only
++       * enabled due to the presence of readers, and because when we are called
++       * from vblank irq we can't hold the vbl_lock to protect us from sudden
++       * bumps in vblank refcount. Therefore also restrict bumps to +1 when
++       * called from vblank irq.
++       */
++      if ((diff > 1) && (atomic_read(&vblank->refcount) > 1 ||
++          (flags & DRM_CALLED_FROM_VBLIRQ))) {
++              DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u "
++                            "refcount %u, vblirq %u\n", pipe, diff,
++                            atomic_read(&vblank->refcount),
++                            (flags & DRM_CALLED_FROM_VBLIRQ) != 0);
++              diff = 1;
++      }
++
+       DRM_DEBUG_VBL("updating vblank count on crtc %u:"
+                     " current=%u, diff=%u, hw=%u hw_last=%u\n",
+                     pipe, vblank->count, diff, cur_vblank, vblank->last);
diff --git a/queue-4.4/drm-qxl-use-kmalloc_array-to-alloc-reloc_info-in-qxl_process_single_command.patch b/queue-4.4/drm-qxl-use-kmalloc_array-to-alloc-reloc_info-in-qxl_process_single_command.patch
new file mode 100644 (file)
index 0000000..2c56d14
--- /dev/null
@@ -0,0 +1,34 @@
+From 34855706c30d52b0a744da44348b5d1cc39fbe51 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Tue, 16 Feb 2016 14:25:00 +0100
+Subject: drm/qxl: use kmalloc_array to alloc reloc_info in qxl_process_single_command
+
+From: Gerd Hoffmann <kraxel@redhat.com>
+
+commit 34855706c30d52b0a744da44348b5d1cc39fbe51 upstream.
+
+This avoids integer overflows on 32bit machines when calculating
+reloc_info size, as reported by Alan Cox.
+
+Cc: gnomes@lxorguk.ukuu.org.uk
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/qxl/qxl_ioctl.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/qxl/qxl_ioctl.c
++++ b/drivers/gpu/drm/qxl/qxl_ioctl.c
+@@ -168,7 +168,8 @@ static int qxl_process_single_command(st
+                      cmd->command_size))
+               return -EFAULT;
+-      reloc_info = kmalloc(sizeof(struct qxl_reloc_info) * cmd->relocs_num, GFP_KERNEL);
++      reloc_info = kmalloc_array(cmd->relocs_num,
++                                 sizeof(struct qxl_reloc_info), GFP_KERNEL);
+       if (!reloc_info)
+               return -ENOMEM;
diff --git a/queue-4.4/drm-radeon-don-t-hang-in-radeon_flip_work_func-on-disabled-crtc.-v2.patch b/queue-4.4/drm-radeon-don-t-hang-in-radeon_flip_work_func-on-disabled-crtc.-v2.patch
new file mode 100644 (file)
index 0000000..3a5729e
--- /dev/null
@@ -0,0 +1,109 @@
+From 2b8341b3f917c108b47f6a8a771a40d226c57883 Mon Sep 17 00:00:00 2001
+From: Mario Kleiner <mario.kleiner.de@gmail.com>
+Date: Fri, 19 Feb 2016 02:06:38 +0100
+Subject: drm/radeon: Don't hang in radeon_flip_work_func on disabled crtc. (v2)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mario Kleiner <mario.kleiner.de@gmail.com>
+
+commit 2b8341b3f917c108b47f6a8a771a40d226c57883 upstream.
+
+This fixes a regression introduced in Linux 4.4.
+
+Limit the amount of time radeon_flip_work_func can
+delay programming a page flip, by both limiting the
+maximum amount of time per wait cycle and the maximum
+number of wait cycles. Continue the flip if the limit
+is exceeded, even if that may result in a visual or
+timing glitch.
+
+This is to prevent a hang of page flips, as reported
+in fdo bug #93746: Disconnecting a DisplayPort display
+in parallel to a kms pageflip getting queued can cause
+the following hang of page flips and thereby an unusable
+desktop:
+
+1. kms pageflip ioctl() queues pageflip -> queues execution
+   of radeon_flip_work_func.
+
+2. Hotunplug of display causes the driver to DPMS OFF
+   the unplugged display. Display engine shuts down,
+   scanout no longer moves, but stays at its resting
+   position at start line of vblank.
+
+3. radeon_flip_work_func executes while crtc is off, and
+   due to the non-moving scanout position, the new flip
+   delay code introduced into Linux 4.4 by
+   commit 5b5561b3660d ("drm/radeon: Fixup hw vblank counter/ts..")
+   enters an infinite wait loop.
+
+4. After reconnecting the display, the pageflip continues
+   to hang in 3. and the display doesn't update its view
+   of the desktop.
+
+This patch fixes the Linux 4.4 regression from fdo bug #93746
+
+<https://bugs.freedesktop.org/show_bug.cgi?id=93746>
+
+v2: Skip wait immediately if !radeon_crtc->enabled, as
+    suggested by Michel.
+
+Reported-by: Bernd Steinhauser <linux@bernd-steinhauser.de>
+Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
+Tested-by: Bernd Steinhauser <linux@bernd-steinhauser.de>
+Cc: Michel Dänzer <michel.daenzer@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/radeon/radeon_display.c |   17 +++++++++++++++--
+ 1 file changed, 15 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/radeon_display.c
++++ b/drivers/gpu/drm/radeon/radeon_display.c
+@@ -403,7 +403,8 @@ static void radeon_flip_work_func(struct
+       struct drm_crtc *crtc = &radeon_crtc->base;
+       unsigned long flags;
+       int r;
+-      int vpos, hpos, stat, min_udelay;
++      int vpos, hpos, stat, min_udelay = 0;
++      unsigned repcnt = 4;
+       struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];
+         down_read(&rdev->exclusive_lock);
+@@ -454,7 +455,7 @@ static void radeon_flip_work_func(struct
+        * In practice this won't execute very often unless on very fast
+        * machines because the time window for this to happen is very small.
+        */
+-      for (;;) {
++      while (radeon_crtc->enabled && repcnt--) {
+               /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
+                * start in hpos, and to the "fudged earlier" vblank start in
+                * vpos.
+@@ -472,10 +473,22 @@ static void radeon_flip_work_func(struct
+               /* Sleep at least until estimated real start of hw vblank */
+               spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+               min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5);
++              if (min_udelay > vblank->framedur_ns / 2000) {
++                      /* Don't wait ridiculously long - something is wrong */
++                      repcnt = 0;
++                      break;
++              }
+               usleep_range(min_udelay, 2 * min_udelay);
+               spin_lock_irqsave(&crtc->dev->event_lock, flags);
+       };
++      if (!repcnt)
++              DRM_DEBUG_DRIVER("Delay problem on crtc %d: min_udelay %d, "
++                               "framedur %d, linedur %d, stat %d, vpos %d, "
++                               "hpos %d\n", work->crtc_id, min_udelay,
++                               vblank->framedur_ns / 1000,
++                               vblank->linedur_ns / 1000, stat, vpos, hpos);
++
+       /* do the flip (mmio) */
+       radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base);
diff --git a/queue-4.4/drm-radeon-pm-adjust-display-configuration-after-powerstate.patch b/queue-4.4/drm-radeon-pm-adjust-display-configuration-after-powerstate.patch
new file mode 100644 (file)
index 0000000..db96a25
--- /dev/null
@@ -0,0 +1,49 @@
+From 39d4275058baf53e89203407bf3841ff2c74fa32 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Fri, 19 Feb 2016 18:05:10 -0500
+Subject: drm/radeon/pm: adjust display configuration after powerstate
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit 39d4275058baf53e89203407bf3841ff2c74fa32 upstream.
+
+set_power_state defaults to no displays, so we need to update
+the display configuration after setting up the powerstate on the
+first call. In most cases this is not an issue since ends up
+getting called multiple times at any given modeset and the proper
+order is achieved in the display changed handling at the top of
+the function.
+
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Acked-by: Jordan Lazare <Jordan.Lazare@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/radeon/radeon_pm.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/radeon_pm.c
++++ b/drivers/gpu/drm/radeon/radeon_pm.c
+@@ -1075,8 +1075,6 @@ force:
+       /* update display watermarks based on new power state */
+       radeon_bandwidth_update(rdev);
+-      /* update displays */
+-      radeon_dpm_display_configuration_changed(rdev);
+       rdev->pm.dpm.current_active_crtcs = rdev->pm.dpm.new_active_crtcs;
+       rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count;
+@@ -1097,6 +1095,9 @@ force:
+       radeon_dpm_post_set_power_state(rdev);
++      /* update displays */
++      radeon_dpm_display_configuration_changed(rdev);
++
+       if (rdev->asic->dpm.force_performance_level) {
+               if (rdev->pm.dpm.thermal_active) {
+                       enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level;
diff --git a/queue-4.4/drm-radeon-use-post-decrement-in-error-handling.patch b/queue-4.4/drm-radeon-use-post-decrement-in-error-handling.patch
new file mode 100644 (file)
index 0000000..835fda6
--- /dev/null
@@ -0,0 +1,36 @@
+From bc3f5d8c4ca01555820617eb3b6c0857e4df710d Mon Sep 17 00:00:00 2001
+From: Rasmus Villemoes <linux@rasmusvillemoes.dk>
+Date: Mon, 15 Feb 2016 19:41:47 +0100
+Subject: drm/radeon: use post-decrement in error handling
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Rasmus Villemoes <linux@rasmusvillemoes.dk>
+
+commit bc3f5d8c4ca01555820617eb3b6c0857e4df710d upstream.
+
+We need to use post-decrement to get the pci_map_page undone also for
+i==0, and to avoid some very unpleasant behaviour if pci_map_page
+failed already at i==0.
+
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/radeon/radeon_ttm.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/radeon/radeon_ttm.c
++++ b/drivers/gpu/drm/radeon/radeon_ttm.c
+@@ -758,7 +758,7 @@ static int radeon_ttm_tt_populate(struct
+                                                      0, PAGE_SIZE,
+                                                      PCI_DMA_BIDIRECTIONAL);
+               if (pci_dma_mapping_error(rdev->pdev, gtt->ttm.dma_address[i])) {
+-                      while (--i) {
++                      while (i--) {
+                               pci_unmap_page(rdev->pdev, gtt->ttm.dma_address[i],
+                                              PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+                               gtt->ttm.dma_address[i] = 0;
diff --git a/queue-4.4/make-sure-that-freeing-shmem-fast-symlinks-is-rcu-delayed.patch b/queue-4.4/make-sure-that-freeing-shmem-fast-symlinks-is-rcu-delayed.patch
new file mode 100644 (file)
index 0000000..bc3e749
--- /dev/null
@@ -0,0 +1,67 @@
+From 3ed47db34f480df7caf44436e3e63e555351ae9a Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Fri, 22 Jan 2016 18:08:52 -0500
+Subject: make sure that freeing shmem fast symlinks is RCU-delayed
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 3ed47db34f480df7caf44436e3e63e555351ae9a upstream.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/shmem_fs.h |    5 +----
+ mm/shmem.c               |    9 ++++-----
+ 2 files changed, 5 insertions(+), 9 deletions(-)
+
+--- a/include/linux/shmem_fs.h
++++ b/include/linux/shmem_fs.h
+@@ -15,10 +15,7 @@ struct shmem_inode_info {
+       unsigned int            seals;          /* shmem seals */
+       unsigned long           flags;
+       unsigned long           alloced;        /* data pages alloced to file */
+-      union {
+-              unsigned long   swapped;        /* subtotal assigned to swap */
+-              char            *symlink;       /* unswappable short symlink */
+-      };
++      unsigned long           swapped;        /* subtotal assigned to swap */
+       struct shared_policy    policy;         /* NUMA memory alloc policy */
+       struct list_head        swaplist;       /* chain of maybes on swap */
+       struct simple_xattrs    xattrs;         /* list of xattrs */
+--- a/mm/shmem.c
++++ b/mm/shmem.c
+@@ -620,8 +620,7 @@ static void shmem_evict_inode(struct ino
+                       list_del_init(&info->swaplist);
+                       mutex_unlock(&shmem_swaplist_mutex);
+               }
+-      } else
+-              kfree(info->symlink);
++      }
+       simple_xattrs_free(&info->xattrs);
+       WARN_ON(inode->i_blocks);
+@@ -2462,13 +2461,12 @@ static int shmem_symlink(struct inode *d
+       info = SHMEM_I(inode);
+       inode->i_size = len-1;
+       if (len <= SHORT_SYMLINK_LEN) {
+-              info->symlink = kmemdup(symname, len, GFP_KERNEL);
+-              if (!info->symlink) {
++              inode->i_link = kmemdup(symname, len, GFP_KERNEL);
++              if (!inode->i_link) {
+                       iput(inode);
+                       return -ENOMEM;
+               }
+               inode->i_op = &shmem_short_symlink_operations;
+-              inode->i_link = info->symlink;
+       } else {
+               error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL);
+               if (error) {
+@@ -3083,6 +3081,7 @@ static struct inode *shmem_alloc_inode(s
+ static void shmem_destroy_callback(struct rcu_head *head)
+ {
+       struct inode *inode = container_of(head, struct inode, i_rcu);
++      kfree(inode->i_link);
+       kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));
+ }
index 86eca8ea7e949f302a3dc25bf1e47e8cdb53eae0..e2db8553ac6730c38f90a841a2ed8f1575a3b770 100644 (file)
@@ -224,3 +224,12 @@ drm-i915-skl-don-t-skip-mst-encoders-in-skl_ddi_pll_select.patch
 drm-i915-dsi-defend-gpio-table-against-out-of-bounds-access.patch
 drm-i915-dsi-don-t-pass-arbitrary-data-to-sideband.patch
 drm-i915-fix-error-path-in-intel_setup_gmbus.patch
+drm-qxl-use-kmalloc_array-to-alloc-reloc_info-in-qxl_process_single_command.patch
+drm-radeon-use-post-decrement-in-error-handling.patch
+drm-no-op-redundant-calls-to-drm_vblank_off-v2.patch
+drm-prevent-vblank-counter-bumps-1-with-active-vblank-clients.-v2.patch
+drm-fix-drm_vblank_pre-post_modeset-regression-from-linux-4.4.patch
+drm-fix-treatment-of-drm_vblank_offdelay-in-drm_vblank_on-v2.patch
+drm-radeon-don-t-hang-in-radeon_flip_work_func-on-disabled-crtc.-v2.patch
+drm-radeon-pm-adjust-display-configuration-after-powerstate.patch
+make-sure-that-freeing-shmem-fast-symlinks-is-rcu-delayed.patch