]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 1 Mar 2016 19:49:51 +0000 (11:49 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 1 Mar 2016 19:49:51 +0000 (11:49 -0800)
added patches:
drm-add-drm_fixp_from_fraction-and-drm_fixp2int_ceil.patch
drm-amdgpu-call-hpd_irq_event-on-resume.patch
drm-amdgpu-don-t-hang-in-amdgpu_flip_work_func-on-disabled-crtc.patch
drm-amdgpu-don-t-load-mec2-on-topaz.patch
drm-amdgpu-drop-topaz-support-from-gmc8-module.patch
drm-amdgpu-fix-amdgpu_bo_pin_restricted-vram-placing-v2.patch
drm-amdgpu-fix-issue-with-overlapping-userptrs.patch
drm-amdgpu-fix-lost-sync_to-if-scheduler-is-enabled.patch
drm-amdgpu-fix-off-by-one-errors-in-amdgpu_vm_bo_map.patch
drm-amdgpu-fix-s4-resume.patch
drm-amdgpu-fix-tonga-smu-resume.patch
drm-amdgpu-hold-reference-to-fences-in-amdgpu_sa_bo_new-v2.patch
drm-amdgpu-iceland-use-ci-based-mc-ip.patch
drm-amdgpu-move-gmc7-support-out-of-cik-dependency.patch
drm-amdgpu-no-need-to-load-mc-firmware-on-fiji.patch
drm-amdgpu-pm-adjust-display-configuration-after-powerstate.patch
drm-amdgpu-pull-topaz-gmc-bits-into-gmc_v7.patch
drm-amdgpu-remove-exp-hardware-support-from-iceland.patch
drm-amdgpu-remove-unnecessary-forward-declaration.patch
drm-amdgpu-the-vi-specific-exe-bit-should-only-apply-to-gmc-v8.0-above.patch
drm-amdgpu-use-post-decrement-in-error-handling.patch
drm-dp-mst-always-send-reply-for-up-request.patch
drm-dp-mst-calculate-mst-pbn-with-31.32-fixed-point.patch
drm-dp-mst-deallocate-payload-on-port-destruction.patch
drm-dp-mst-fix-in-mstb-rad-initialization.patch
drm-dp-mst-fix-in-rad-element-access.patch
drm-dp-mst-move-guid-storage-from-mgr-port-to-only-mst-branch.patch
drm-dp-mst-process-broadcast-messages-correctly.patch
drm-dp-mst-reverse-order-of-mst-enable-and-clearing-vc-payload-table.patch
drm-nouveau-disp-dp-ensure-sink-is-powered-up-before-attempting-link-training.patch
drm-nouveau-display-enable-vblank-irqs-after-display-engine-is-on-again.patch
drm-nouveau-kms-take-mode_config-mutex-in-connector-hotplug-path.patch
drm-nouveau-platform-fix-deferred-probe.patch
drm-vmwgfx-fix-a-width-pitch-mismatch-on-framebuffer-updates.patch
drm-vmwgfx-fix-an-incorrect-lock-check.patch
drm-vmwgfx-respect-nomodeset.patch
virtio_balloon-fix-race-between-migration-and-ballooning.patch
virtio_balloon-fix-race-by-fill-and-leak.patch
virtio_pci-fix-use-after-free-on-release.patch

40 files changed:
queue-4.4/drm-add-drm_fixp_from_fraction-and-drm_fixp2int_ceil.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-call-hpd_irq_event-on-resume.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-don-t-hang-in-amdgpu_flip_work_func-on-disabled-crtc.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-don-t-load-mec2-on-topaz.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-drop-topaz-support-from-gmc8-module.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-fix-amdgpu_bo_pin_restricted-vram-placing-v2.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-fix-issue-with-overlapping-userptrs.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-fix-lost-sync_to-if-scheduler-is-enabled.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-fix-off-by-one-errors-in-amdgpu_vm_bo_map.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-fix-s4-resume.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-fix-tonga-smu-resume.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-hold-reference-to-fences-in-amdgpu_sa_bo_new-v2.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-iceland-use-ci-based-mc-ip.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-move-gmc7-support-out-of-cik-dependency.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-no-need-to-load-mc-firmware-on-fiji.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-pm-adjust-display-configuration-after-powerstate.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-pull-topaz-gmc-bits-into-gmc_v7.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-remove-exp-hardware-support-from-iceland.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-remove-unnecessary-forward-declaration.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-the-vi-specific-exe-bit-should-only-apply-to-gmc-v8.0-above.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-use-post-decrement-in-error-handling.patch [new file with mode: 0644]
queue-4.4/drm-dp-mst-always-send-reply-for-up-request.patch [new file with mode: 0644]
queue-4.4/drm-dp-mst-calculate-mst-pbn-with-31.32-fixed-point.patch [new file with mode: 0644]
queue-4.4/drm-dp-mst-deallocate-payload-on-port-destruction.patch [new file with mode: 0644]
queue-4.4/drm-dp-mst-fix-in-mstb-rad-initialization.patch [new file with mode: 0644]
queue-4.4/drm-dp-mst-fix-in-rad-element-access.patch [new file with mode: 0644]
queue-4.4/drm-dp-mst-move-guid-storage-from-mgr-port-to-only-mst-branch.patch [new file with mode: 0644]
queue-4.4/drm-dp-mst-process-broadcast-messages-correctly.patch [new file with mode: 0644]
queue-4.4/drm-dp-mst-reverse-order-of-mst-enable-and-clearing-vc-payload-table.patch [new file with mode: 0644]
queue-4.4/drm-nouveau-disp-dp-ensure-sink-is-powered-up-before-attempting-link-training.patch [new file with mode: 0644]
queue-4.4/drm-nouveau-display-enable-vblank-irqs-after-display-engine-is-on-again.patch [new file with mode: 0644]
queue-4.4/drm-nouveau-kms-take-mode_config-mutex-in-connector-hotplug-path.patch [new file with mode: 0644]
queue-4.4/drm-nouveau-platform-fix-deferred-probe.patch [new file with mode: 0644]
queue-4.4/drm-vmwgfx-fix-a-width-pitch-mismatch-on-framebuffer-updates.patch [new file with mode: 0644]
queue-4.4/drm-vmwgfx-fix-an-incorrect-lock-check.patch [new file with mode: 0644]
queue-4.4/drm-vmwgfx-respect-nomodeset.patch [new file with mode: 0644]
queue-4.4/series
queue-4.4/virtio_balloon-fix-race-between-migration-and-ballooning.patch [new file with mode: 0644]
queue-4.4/virtio_balloon-fix-race-by-fill-and-leak.patch [new file with mode: 0644]
queue-4.4/virtio_pci-fix-use-after-free-on-release.patch [new file with mode: 0644]

diff --git a/queue-4.4/drm-add-drm_fixp_from_fraction-and-drm_fixp2int_ceil.patch b/queue-4.4/drm-add-drm_fixp_from_fraction-and-drm_fixp2int_ceil.patch
new file mode 100644 (file)
index 0000000..6607851
--- /dev/null
@@ -0,0 +1,106 @@
+From 64566b5e767f9bc3161055ca1b443a51afb52aad Mon Sep 17 00:00:00 2001
+From: Harry Wentland <harry.wentland@amd.com>
+Date: Fri, 22 Jan 2016 17:07:25 -0500
+Subject: drm: Add drm_fixp_from_fraction and drm_fixp2int_ceil
+
+From: Harry Wentland <harry.wentland@amd.com>
+
+commit 64566b5e767f9bc3161055ca1b443a51afb52aad upstream.
+
+drm_fixp_from_fraction allows us to create a fixed point directly
+from a fraction, rather than creating fixed point values and dividing
+later. This avoids overflow of our 64 bit value for large numbers.
+
+drm_fixp2int_ceil allows us to return the ceiling of our fixed point
+value.
+
+[airlied: squash Jordan's fix]
+32-bit-build-fix: Jordan Lazare <Jordan.Lazare@amd.com>
+Signed-off-by: Harry Wentland <harry.wentland@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/drm/drm_fixed.h |   53 ++++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 51 insertions(+), 2 deletions(-)
+
+--- a/include/drm/drm_fixed.h
++++ b/include/drm/drm_fixed.h
+@@ -73,18 +73,28 @@ static inline u32 dfixed_div(fixed20_12
+ #define DRM_FIXED_ONE         (1ULL << DRM_FIXED_POINT)
+ #define DRM_FIXED_DECIMAL_MASK        (DRM_FIXED_ONE - 1)
+ #define DRM_FIXED_DIGITS_MASK (~DRM_FIXED_DECIMAL_MASK)
++#define DRM_FIXED_EPSILON     1LL
++#define DRM_FIXED_ALMOST_ONE  (DRM_FIXED_ONE - DRM_FIXED_EPSILON)
+ static inline s64 drm_int2fixp(int a)
+ {
+       return ((s64)a) << DRM_FIXED_POINT;
+ }
+-static inline int drm_fixp2int(int64_t a)
++static inline int drm_fixp2int(s64 a)
+ {
+       return ((s64)a) >> DRM_FIXED_POINT;
+ }
+-static inline unsigned drm_fixp_msbset(int64_t a)
++static inline int drm_fixp2int_ceil(s64 a)
++{
++      if (a > 0)
++              return drm_fixp2int(a + DRM_FIXED_ALMOST_ONE);
++      else
++              return drm_fixp2int(a - DRM_FIXED_ALMOST_ONE);
++}
++
++static inline unsigned drm_fixp_msbset(s64 a)
+ {
+       unsigned shift, sign = (a >> 63) & 1;
+@@ -136,6 +146,45 @@ static inline s64 drm_fixp_div(s64 a, s6
+       return result;
+ }
++static inline s64 drm_fixp_from_fraction(s64 a, s64 b)
++{
++      s64 res;
++      bool a_neg = a < 0;
++      bool b_neg = b < 0;
++      u64 a_abs = a_neg ? -a : a;
++      u64 b_abs = b_neg ? -b : b;
++      u64 rem;
++
++      /* determine integer part */
++      u64 res_abs  = div64_u64_rem(a_abs, b_abs, &rem);
++
++      /* determine fractional part */
++      {
++              u32 i = DRM_FIXED_POINT;
++
++              do {
++                      rem <<= 1;
++                      res_abs <<= 1;
++                      if (rem >= b_abs) {
++                              res_abs |= 1;
++                              rem -= b_abs;
++                      }
++              } while (--i != 0);
++      }
++
++      /* round up LSB */
++      {
++              u64 summand = (rem << 1) >= b_abs;
++
++              res_abs += summand;
++      }
++
++      res = (s64) res_abs;
++      if (a_neg ^ b_neg)
++              res = -res;
++      return res;
++}
++
+ static inline s64 drm_fixp_exp(s64 x)
+ {
+       s64 tolerance = div64_s64(DRM_FIXED_ONE, 1000000);
diff --git a/queue-4.4/drm-amdgpu-call-hpd_irq_event-on-resume.patch b/queue-4.4/drm-amdgpu-call-hpd_irq_event-on-resume.patch
new file mode 100644 (file)
index 0000000..5fcc9c4
--- /dev/null
@@ -0,0 +1,29 @@
+From 54fb2a5cd0baf8e97d743de411e2f832d1afa68d Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Tue, 24 Nov 2015 14:30:56 -0500
+Subject: drm/amdgpu: call hpd_irq_event on resume
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit 54fb2a5cd0baf8e97d743de411e2f832d1afa68d upstream.
+
+Need to call this on resume if displays changes during
+suspend in order to properly be notified of changes.
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -1788,6 +1788,7 @@ int amdgpu_resume_kms(struct drm_device
+       }
+       drm_kms_helper_poll_enable(dev);
++      drm_helper_hpd_irq_event(dev);
+       if (fbcon) {
+               amdgpu_fbdev_set_suspend(adev, 0);
diff --git a/queue-4.4/drm-amdgpu-don-t-hang-in-amdgpu_flip_work_func-on-disabled-crtc.patch b/queue-4.4/drm-amdgpu-don-t-hang-in-amdgpu_flip_work_func-on-disabled-crtc.patch
new file mode 100644 (file)
index 0000000..33da403
--- /dev/null
@@ -0,0 +1,111 @@
+From e1d09dc0ccc6c91e3916476f636edb76da1f65bb Mon Sep 17 00:00:00 2001
+From: Mario Kleiner <mario.kleiner.de@gmail.com>
+Date: Fri, 19 Feb 2016 02:06:39 +0100
+Subject: drm/amdgpu: Don't hang in amdgpu_flip_work_func on disabled crtc.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mario Kleiner <mario.kleiner.de@gmail.com>
+
+commit e1d09dc0ccc6c91e3916476f636edb76da1f65bb upstream.
+
+This fixes a regression introduced in Linux 4.4.
+
+This is a port of the same fix for radeon-kms in the
+patch "drm/radeon: Don't hang in radeon_flip_work_func
+on disabled crtc. (v2)"
+
+Limit the amount of time amdgpu_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 amdgpu_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. amdgpu_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 8e36f9d33c13 ("drm/amdgpu: 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>
+
+Reported-by: Bernd Steinhauser <linux@bernd-steinhauser.de>
+Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+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>
+
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_display.c |   18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+@@ -72,8 +72,8 @@ static void amdgpu_flip_work_func(struct
+       struct drm_crtc *crtc = &amdgpuCrtc->base;
+       unsigned long flags;
+-      unsigned i;
+-      int vpos, hpos, stat, min_udelay;
++      unsigned i, repcnt = 4;
++      int vpos, hpos, stat, min_udelay = 0;
+       struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];
+       amdgpu_flip_wait_fence(adev, &work->excl);
+@@ -96,7 +96,7 @@ static void amdgpu_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 (amdgpuCrtc->enabled && repcnt--) {
+               /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
+                * start in hpos, and to the "fudged earlier" vblank start in
+                * vpos.
+@@ -114,10 +114,22 @@ static void amdgpu_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) */
+       adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base);
+       /* set the flip status */
diff --git a/queue-4.4/drm-amdgpu-don-t-load-mec2-on-topaz.patch b/queue-4.4/drm-amdgpu-don-t-load-mec2-on-topaz.patch
new file mode 100644 (file)
index 0000000..c4a117c
--- /dev/null
@@ -0,0 +1,79 @@
+From 97dde76a30c2e67fa5fb9cb6a4072c0178c9df26 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Tue, 2 Feb 2016 11:15:41 -0500
+Subject: drm/amdgpu: don't load MEC2 on topaz
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit 97dde76a30c2e67fa5fb9cb6a4072c0178c9df26 upstream.
+
+Not validated.
+
+Reviewed-by: Ken Wang <Qingqing.Wang@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c    |    4 ++--
+ drivers/gpu/drm/amd/amdgpu/iceland_smc.c |   12 +++---------
+ 2 files changed, 5 insertions(+), 11 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+@@ -90,7 +90,6 @@ MODULE_FIRMWARE("amdgpu/topaz_ce.bin");
+ MODULE_FIRMWARE("amdgpu/topaz_pfp.bin");
+ MODULE_FIRMWARE("amdgpu/topaz_me.bin");
+ MODULE_FIRMWARE("amdgpu/topaz_mec.bin");
+-MODULE_FIRMWARE("amdgpu/topaz_mec2.bin");
+ MODULE_FIRMWARE("amdgpu/topaz_rlc.bin");
+ MODULE_FIRMWARE("amdgpu/fiji_ce.bin");
+@@ -807,7 +806,8 @@ static int gfx_v8_0_init_microcode(struc
+       adev->gfx.mec_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
+       adev->gfx.mec_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
+-      if (adev->asic_type != CHIP_STONEY) {
++      if ((adev->asic_type != CHIP_STONEY) &&
++          (adev->asic_type != CHIP_TOPAZ)) {
+               snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name);
+               err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev);
+               if (!err) {
+--- a/drivers/gpu/drm/amd/amdgpu/iceland_smc.c
++++ b/drivers/gpu/drm/amd/amdgpu/iceland_smc.c
+@@ -432,7 +432,7 @@ static uint32_t iceland_smu_get_mask_for
+               case AMDGPU_UCODE_ID_CP_ME:
+                       return UCODE_ID_CP_ME_MASK;
+               case AMDGPU_UCODE_ID_CP_MEC1:
+-                      return UCODE_ID_CP_MEC_MASK | UCODE_ID_CP_MEC_JT1_MASK | UCODE_ID_CP_MEC_JT2_MASK;
++                      return UCODE_ID_CP_MEC_MASK | UCODE_ID_CP_MEC_JT1_MASK;
+               case AMDGPU_UCODE_ID_CP_MEC2:
+                       return UCODE_ID_CP_MEC_MASK;
+               case AMDGPU_UCODE_ID_RLC_G:
+@@ -522,12 +522,6 @@ static int iceland_smu_request_load_fw(s
+               return -EINVAL;
+       }
+-      if (iceland_smu_populate_single_firmware_entry(adev, UCODE_ID_CP_MEC_JT2,
+-                      &toc->entry[toc->num_entries++])) {
+-              DRM_ERROR("Failed to get firmware entry for MEC_JT2\n");
+-              return -EINVAL;
+-      }
+-
+       if (iceland_smu_populate_single_firmware_entry(adev, UCODE_ID_SDMA0,
+                       &toc->entry[toc->num_entries++])) {
+               DRM_ERROR("Failed to get firmware entry for SDMA0\n");
+@@ -550,8 +544,8 @@ static int iceland_smu_request_load_fw(s
+                       UCODE_ID_CP_ME_MASK |
+                       UCODE_ID_CP_PFP_MASK |
+                       UCODE_ID_CP_MEC_MASK |
+-                      UCODE_ID_CP_MEC_JT1_MASK |
+-                      UCODE_ID_CP_MEC_JT2_MASK;
++                      UCODE_ID_CP_MEC_JT1_MASK;
++
+       if (iceland_send_msg_to_smc_with_parameter_without_waiting(adev, PPSMC_MSG_LoadUcodes, fw_to_load)) {
+               DRM_ERROR("Fail to request SMU load ucode\n");
diff --git a/queue-4.4/drm-amdgpu-drop-topaz-support-from-gmc8-module.patch b/queue-4.4/drm-amdgpu-drop-topaz-support-from-gmc8-module.patch
new file mode 100644 (file)
index 0000000..81f5587
--- /dev/null
@@ -0,0 +1,88 @@
+From 8878d8548ac7fae43cd6d82579f966eb8825e282 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Tue, 2 Feb 2016 10:57:30 -0500
+Subject: drm/amdgpu: drop topaz support from gmc8 module
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit 8878d8548ac7fae43cd6d82579f966eb8825e282 upstream.
+
+topaz is actually gmc7.
+
+Reviewed-by: Ken Wang <Qingqing.Wang@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c |   28 +---------------------------
+ 1 file changed, 1 insertion(+), 27 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+@@ -42,7 +42,6 @@
+ static void gmc_v8_0_set_gart_funcs(struct amdgpu_device *adev);
+ static void gmc_v8_0_set_irq_funcs(struct amdgpu_device *adev);
+-MODULE_FIRMWARE("amdgpu/topaz_mc.bin");
+ MODULE_FIRMWARE("amdgpu/tonga_mc.bin");
+ static const u32 golden_settings_tonga_a11[] =
+@@ -74,19 +73,6 @@ static const u32 fiji_mgcg_cgcg_init[] =
+       mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104
+ };
+-static const u32 golden_settings_iceland_a11[] =
+-{
+-      mmVM_PRT_APERTURE0_LOW_ADDR, 0x0fffffff, 0x0fffffff,
+-      mmVM_PRT_APERTURE1_LOW_ADDR, 0x0fffffff, 0x0fffffff,
+-      mmVM_PRT_APERTURE2_LOW_ADDR, 0x0fffffff, 0x0fffffff,
+-      mmVM_PRT_APERTURE3_LOW_ADDR, 0x0fffffff, 0x0fffffff
+-};
+-
+-static const u32 iceland_mgcg_cgcg_init[] =
+-{
+-      mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104
+-};
+-
+ static const u32 cz_mgcg_cgcg_init[] =
+ {
+       mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104
+@@ -101,14 +87,6 @@ static const u32 stoney_mgcg_cgcg_init[]
+ static void gmc_v8_0_init_golden_registers(struct amdgpu_device *adev)
+ {
+       switch (adev->asic_type) {
+-      case CHIP_TOPAZ:
+-              amdgpu_program_register_sequence(adev,
+-                                               iceland_mgcg_cgcg_init,
+-                                               (const u32)ARRAY_SIZE(iceland_mgcg_cgcg_init));
+-              amdgpu_program_register_sequence(adev,
+-                                               golden_settings_iceland_a11,
+-                                               (const u32)ARRAY_SIZE(golden_settings_iceland_a11));
+-              break;
+       case CHIP_FIJI:
+               amdgpu_program_register_sequence(adev,
+                                                fiji_mgcg_cgcg_init,
+@@ -228,9 +206,6 @@ static int gmc_v8_0_init_microcode(struc
+       DRM_DEBUG("\n");
+       switch (adev->asic_type) {
+-      case CHIP_TOPAZ:
+-              chip_name = "topaz";
+-              break;
+       case CHIP_TONGA:
+               chip_name = "tonga";
+               break;
+@@ -1000,8 +975,7 @@ static int gmc_v8_0_hw_init(void *handle
+       gmc_v8_0_mc_program(adev);
+-      if ((adev->asic_type == CHIP_TOPAZ) ||
+-          (adev->asic_type == CHIP_TONGA)) {
++      if (adev->asic_type == CHIP_TONGA) {
+               r = gmc_v8_0_mc_load_microcode(adev);
+               if (r) {
+                       DRM_ERROR("Failed to load MC firmware!\n");
diff --git a/queue-4.4/drm-amdgpu-fix-amdgpu_bo_pin_restricted-vram-placing-v2.patch b/queue-4.4/drm-amdgpu-fix-amdgpu_bo_pin_restricted-vram-placing-v2.patch
new file mode 100644 (file)
index 0000000..e4b4d87
--- /dev/null
@@ -0,0 +1,38 @@
+From 78d0e182b6c1f5336f6e8cbb197f403276dabc7f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Tue, 19 Jan 2016 12:48:14 +0100
+Subject: drm/amdgpu: fix amdgpu_bo_pin_restricted VRAM placing v2
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Christian König <christian.koenig@amd.com>
+
+commit 78d0e182b6c1f5336f6e8cbb197f403276dabc7f upstream.
+
+We could pin BOs into invisible VRAM otherwise.
+
+v2: make logic more readable as suggested by Michel
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com> (v1)
+Reviewed-by: Rex Zhu <Rex.Zhu@amd.com> (v1)
+Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_object.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+@@ -399,7 +399,8 @@ int amdgpu_bo_pin_restricted(struct amdg
+               }
+               if (fpfn > bo->placements[i].fpfn)
+                       bo->placements[i].fpfn = fpfn;
+-              if (lpfn && lpfn < bo->placements[i].lpfn)
++              if (!bo->placements[i].lpfn ||
++                  (lpfn && lpfn < bo->placements[i].lpfn))
+                       bo->placements[i].lpfn = lpfn;
+               bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
+       }
diff --git a/queue-4.4/drm-amdgpu-fix-issue-with-overlapping-userptrs.patch b/queue-4.4/drm-amdgpu-fix-issue-with-overlapping-userptrs.patch
new file mode 100644 (file)
index 0000000..3b398bc
--- /dev/null
@@ -0,0 +1,76 @@
+From cc1de6e800c253172334f8774c419dc64401cd2e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Mon, 8 Feb 2016 10:57:22 +0100
+Subject: drm/amdgpu: fix issue with overlapping userptrs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Christian König <christian.koenig@amd.com>
+
+commit cc1de6e800c253172334f8774c419dc64401cd2e upstream.
+
+Otherwise we could try to evict overlapping userptr BOs in get_user_pages(),
+leading to a possible circular locking dependency.
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu.h     |    2 ++
+ drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c  |    3 ++-
+ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c |   19 +++++++++++++++++++
+ 3 files changed, 23 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+@@ -2312,6 +2312,8 @@ bool amdgpu_ttm_bo_is_amdgpu_bo(struct t
+ int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr,
+                                    uint32_t flags);
+ bool amdgpu_ttm_tt_has_userptr(struct ttm_tt *ttm);
++bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start,
++                                unsigned long end);
+ bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm);
+ uint32_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm,
+                                struct ttm_mem_reg *mem);
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
+@@ -142,7 +142,8 @@ static void amdgpu_mn_invalidate_range_s
+               list_for_each_entry(bo, &node->bos, mn_list) {
+-                      if (!bo->tbo.ttm || bo->tbo.ttm->state != tt_bound)
++                      if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start,
++                                                        end))
+                               continue;
+                       r = amdgpu_bo_reserve(bo, true);
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+@@ -783,6 +783,25 @@ bool amdgpu_ttm_tt_has_userptr(struct tt
+       return !!gtt->userptr;
+ }
++bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start,
++                                unsigned long end)
++{
++      struct amdgpu_ttm_tt *gtt = (void *)ttm;
++      unsigned long size;
++
++      if (gtt == NULL)
++              return false;
++
++      if (gtt->ttm.ttm.state != tt_bound || !gtt->userptr)
++              return false;
++
++      size = (unsigned long)gtt->ttm.ttm.num_pages * PAGE_SIZE;
++      if (gtt->userptr > end || gtt->userptr + size <= start)
++              return false;
++
++      return true;
++}
++
+ bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm)
+ {
+       struct amdgpu_ttm_tt *gtt = (void *)ttm;
diff --git a/queue-4.4/drm-amdgpu-fix-lost-sync_to-if-scheduler-is-enabled.patch b/queue-4.4/drm-amdgpu-fix-lost-sync_to-if-scheduler-is-enabled.patch
new file mode 100644 (file)
index 0000000..6153d91
--- /dev/null
@@ -0,0 +1,43 @@
+From 888c9e33e4c5a503285921046c621f7c73199d2f Mon Sep 17 00:00:00 2001
+From: Chunming Zhou <David1.Zhou@amd.com>
+Date: Wed, 13 Jan 2016 12:55:18 +0800
+Subject: drm/amdgpu: fix lost sync_to if scheduler is enabled.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Chunming Zhou <David1.Zhou@amd.com>
+
+commit 888c9e33e4c5a503285921046c621f7c73199d2f upstream.
+
+when scheduler is enabled, the semaphore isn't used at all.
+
+Signed-off-by: Chunming Zhou <David1.Zhou@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
+@@ -293,7 +293,8 @@ int amdgpu_sync_rings(struct amdgpu_sync
+               fence = to_amdgpu_fence(sync->sync_to[i]);
+               /* check if we really need to sync */
+-              if (!amdgpu_fence_need_sync(fence, ring))
++              if (!amdgpu_enable_scheduler &&
++                  !amdgpu_fence_need_sync(fence, ring))
+                       continue;
+               /* prevent GPU deadlocks */
+@@ -303,7 +304,7 @@ int amdgpu_sync_rings(struct amdgpu_sync
+               }
+               if (amdgpu_enable_scheduler || !amdgpu_enable_semaphores) {
+-                      r = fence_wait(&fence->base, true);
++                      r = fence_wait(sync->sync_to[i], true);
+                       if (r)
+                               return r;
+                       continue;
diff --git a/queue-4.4/drm-amdgpu-fix-off-by-one-errors-in-amdgpu_vm_bo_map.patch b/queue-4.4/drm-amdgpu-fix-off-by-one-errors-in-amdgpu_vm_bo_map.patch
new file mode 100644 (file)
index 0000000..e81b370
--- /dev/null
@@ -0,0 +1,63 @@
+From 005ae95e6ec119c64e2d16eb65a94c49e1dcf9f0 Mon Sep 17 00:00:00 2001
+From: Felix Kuehling <Felix.Kuehling@amd.com>
+Date: Mon, 23 Nov 2015 17:43:48 -0500
+Subject: drm/amdgpu: Fix off-by-one errors in amdgpu_vm_bo_map
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Felix Kuehling <Felix.Kuehling@amd.com>
+
+commit 005ae95e6ec119c64e2d16eb65a94c49e1dcf9f0 upstream.
+
+eaddr is sometimes treated as the last address inside the address
+range, and sometimes as the first address outside the range. This
+was resulting in errors when a test filled up the entire address
+space. Make it consistent to always be the last address within the
+range.
+
+Signed-off-by: Felix.Kuehling <Felix.Kuehling@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c |   10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+@@ -1010,13 +1010,13 @@ int amdgpu_vm_bo_map(struct amdgpu_devic
+               return -EINVAL;
+       /* make sure object fit at this offset */
+-      eaddr = saddr + size;
++      eaddr = saddr + size - 1;
+       if ((saddr >= eaddr) || (offset + size > amdgpu_bo_size(bo_va->bo)))
+               return -EINVAL;
+       last_pfn = eaddr / AMDGPU_GPU_PAGE_SIZE;
+-      if (last_pfn > adev->vm_manager.max_pfn) {
+-              dev_err(adev->dev, "va above limit (0x%08X > 0x%08X)\n",
++      if (last_pfn >= adev->vm_manager.max_pfn) {
++              dev_err(adev->dev, "va above limit (0x%08X >= 0x%08X)\n",
+                       last_pfn, adev->vm_manager.max_pfn);
+               return -EINVAL;
+       }
+@@ -1025,7 +1025,7 @@ int amdgpu_vm_bo_map(struct amdgpu_devic
+       eaddr /= AMDGPU_GPU_PAGE_SIZE;
+       spin_lock(&vm->it_lock);
+-      it = interval_tree_iter_first(&vm->va, saddr, eaddr - 1);
++      it = interval_tree_iter_first(&vm->va, saddr, eaddr);
+       spin_unlock(&vm->it_lock);
+       if (it) {
+               struct amdgpu_bo_va_mapping *tmp;
+@@ -1046,7 +1046,7 @@ int amdgpu_vm_bo_map(struct amdgpu_devic
+       INIT_LIST_HEAD(&mapping->list);
+       mapping->it.start = saddr;
+-      mapping->it.last = eaddr - 1;
++      mapping->it.last = eaddr;
+       mapping->offset = offset;
+       mapping->flags = flags;
diff --git a/queue-4.4/drm-amdgpu-fix-s4-resume.patch b/queue-4.4/drm-amdgpu-fix-s4-resume.patch
new file mode 100644 (file)
index 0000000..88e9c7a
--- /dev/null
@@ -0,0 +1,47 @@
+From ca19852884c8937eed89560f924f5a34cfcc22af Mon Sep 17 00:00:00 2001
+From: Flora Cui <Flora.Cui@amd.com>
+Date: Thu, 4 Feb 2016 15:10:08 +0800
+Subject: drm/amdgpu: fix s4 resume
+
+From: Flora Cui <Flora.Cui@amd.com>
+
+commit ca19852884c8937eed89560f924f5a34cfcc22af upstream.
+
+No need to re-init asic if it's already been initialized.
+Skip IB tests since kernel processes are frozen in thaw.
+
+Signed-off-by: Flora Cui <Flora.Cui@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c |   13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -1744,15 +1744,20 @@ int amdgpu_resume_kms(struct drm_device
+       }
+       /* post card */
+-      amdgpu_atom_asic_init(adev->mode_info.atom_context);
++      if (!amdgpu_card_posted(adev))
++              amdgpu_atom_asic_init(adev->mode_info.atom_context);
+       r = amdgpu_resume(adev);
++      if (r)
++              DRM_ERROR("amdgpu_resume failed (%d).\n", r);
+       amdgpu_fence_driver_resume(adev);
+-      r = amdgpu_ib_ring_tests(adev);
+-      if (r)
+-              DRM_ERROR("ib ring test failed (%d).\n", r);
++      if (resume) {
++              r = amdgpu_ib_ring_tests(adev);
++              if (r)
++                      DRM_ERROR("ib ring test failed (%d).\n", r);
++      }
+       r = amdgpu_late_init(adev);
+       if (r)
diff --git a/queue-4.4/drm-amdgpu-fix-tonga-smu-resume.patch b/queue-4.4/drm-amdgpu-fix-tonga-smu-resume.patch
new file mode 100644 (file)
index 0000000..b23d6dd
--- /dev/null
@@ -0,0 +1,55 @@
+From e160e4db833c7e8587ec3c88efaed0d84f1bcf42 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Thu, 14 Jan 2016 13:48:24 -0500
+Subject: drm/amdgpu: fix tonga smu resume
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit e160e4db833c7e8587ec3c88efaed0d84f1bcf42 upstream.
+
+Need to make sure smu buffers are pinned on resume.  This
+matches what Fiji does.
+
+Reviewed-by: Junwei Zhang <Jerry.Zhang@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Reviewed-by: Ken Wang <Qingqing.Wang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/tonga_dpm.c |   17 ++---------------
+ 1 file changed, 2 insertions(+), 15 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c
++++ b/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c
+@@ -122,25 +122,12 @@ static int tonga_dpm_hw_fini(void *handl
+ static int tonga_dpm_suspend(void *handle)
+ {
+-      return 0;
++      return tonga_dpm_hw_fini(handle);
+ }
+ static int tonga_dpm_resume(void *handle)
+ {
+-      int ret;
+-      struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+-
+-      mutex_lock(&adev->pm.mutex);
+-
+-      ret = tonga_smu_start(adev);
+-      if (ret) {
+-              DRM_ERROR("SMU start failed\n");
+-              goto fail;
+-      }
+-
+-fail:
+-      mutex_unlock(&adev->pm.mutex);
+-      return ret;
++      return tonga_dpm_hw_init(handle);
+ }
+ static int tonga_dpm_set_clockgating_state(void *handle,
diff --git a/queue-4.4/drm-amdgpu-hold-reference-to-fences-in-amdgpu_sa_bo_new-v2.patch b/queue-4.4/drm-amdgpu-hold-reference-to-fences-in-amdgpu_sa_bo_new-v2.patch
new file mode 100644 (file)
index 0000000..a1e1c90
--- /dev/null
@@ -0,0 +1,51 @@
+From a8d81b36267366603771431747438d18f32ae2d5 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Nicolai=20H=C3=A4hnle?= <nicolai.haehnle@amd.com>
+Date: Fri, 5 Feb 2016 10:59:43 -0500
+Subject: drm/amdgpu: hold reference to fences in amdgpu_sa_bo_new (v2)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Nicolai Hähnle <nicolai.haehnle@amd.com>
+
+commit a8d81b36267366603771431747438d18f32ae2d5 upstream.
+
+An arbitrary amount of time can pass between spin_unlock and
+fence_wait_any_timeout, so we need to ensure that nobody frees the
+fences from under us.
+
+A stress test (rapidly starting and killing hundreds of glxgears
+instances) ran into a deadlock in fence_wait_any_timeout after
+about an hour, and this race condition appears to be a plausible
+cause.
+
+v2: agd: rebase on upstream
+
+Signed-off-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
+@@ -354,12 +354,15 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_ma
+               for (i = 0, count = 0; i < AMDGPU_MAX_RINGS; ++i)
+                       if (fences[i])
+-                              fences[count++] = fences[i];
++                              fences[count++] = fence_get(fences[i]);
+               if (count) {
+                       spin_unlock(&sa_manager->wq.lock);
+                       t = fence_wait_any_timeout(fences, count, false,
+                                                  MAX_SCHEDULE_TIMEOUT);
++                      for (i = 0; i < count; ++i)
++                              fence_put(fences[i]);
++
+                       r = (t > 0) ? 0 : t;
+                       spin_lock(&sa_manager->wq.lock);
+               } else {
diff --git a/queue-4.4/drm-amdgpu-iceland-use-ci-based-mc-ip.patch b/queue-4.4/drm-amdgpu-iceland-use-ci-based-mc-ip.patch
new file mode 100644 (file)
index 0000000..2718432
--- /dev/null
@@ -0,0 +1,78 @@
+From 429c45deae6e57f1bb91bfb05b671063fb0cef60 Mon Sep 17 00:00:00 2001
+From: Ken Wang <Qingqing.Wang@amd.com>
+Date: Wed, 3 Feb 2016 19:16:54 +0800
+Subject: drm/amdgpu: iceland use CI based MC IP
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ken Wang <Qingqing.Wang@amd.com>
+
+commit 429c45deae6e57f1bb91bfb05b671063fb0cef60 upstream.
+
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Ken Wang <Qingqing.Wang@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c |   10 +++++++++-
+ drivers/gpu/drm/amd/amdgpu/vi.c       |    7 ++++---
+ 2 files changed, 13 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+@@ -42,6 +42,7 @@ static void gmc_v7_0_set_irq_funcs(struc
+ MODULE_FIRMWARE("radeon/bonaire_mc.bin");
+ MODULE_FIRMWARE("radeon/hawaii_mc.bin");
++MODULE_FIRMWARE("amdgpu/topaz_mc.bin");
+ /**
+  * gmc8_mc_wait_for_idle - wait for MC idle callback.
+@@ -132,13 +133,20 @@ static int gmc_v7_0_init_microcode(struc
+       case CHIP_HAWAII:
+               chip_name = "hawaii";
+               break;
++      case CHIP_TOPAZ:
++              chip_name = "topaz";
++              break;
+       case CHIP_KAVERI:
+       case CHIP_KABINI:
+               return 0;
+       default: BUG();
+       }
+-      snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
++      if(adev->asic_type == CHIP_TOPAZ)
++              snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mc.bin", chip_name);
++      else
++              snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
++
+       err = request_firmware(&adev->mc.fw, fw_name, adev->dev);
+       if (err)
+               goto out;
+--- a/drivers/gpu/drm/amd/amdgpu/vi.c
++++ b/drivers/gpu/drm/amd/amdgpu/vi.c
+@@ -60,6 +60,7 @@
+ #include "vi.h"
+ #include "vi_dpm.h"
+ #include "gmc_v8_0.h"
++#include "gmc_v7_0.h"
+ #include "gfx_v8_0.h"
+ #include "sdma_v2_4.h"
+ #include "sdma_v3_0.h"
+@@ -1128,10 +1129,10 @@ static const struct amdgpu_ip_block_vers
+       },
+       {
+               .type = AMD_IP_BLOCK_TYPE_GMC,
+-              .major = 8,
+-              .minor = 0,
++              .major = 7,
++              .minor = 4,
+               .rev = 0,
+-              .funcs = &gmc_v8_0_ip_funcs,
++              .funcs = &gmc_v7_0_ip_funcs,
+       },
+       {
+               .type = AMD_IP_BLOCK_TYPE_IH,
diff --git a/queue-4.4/drm-amdgpu-move-gmc7-support-out-of-cik-dependency.patch b/queue-4.4/drm-amdgpu-move-gmc7-support-out-of-cik-dependency.patch
new file mode 100644 (file)
index 0000000..d4340d9
--- /dev/null
@@ -0,0 +1,42 @@
+From e42d85261680edfc350a6c2a86b7fbb44a85014b Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Tue, 2 Feb 2016 10:59:53 -0500
+Subject: drm/amdgpu: move gmc7 support out of CIK dependency
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit e42d85261680edfc350a6c2a86b7fbb44a85014b upstream.
+
+It's used by iceland which is VI.
+
+Reviewed-by: Ken Wang <Qingqing.Wang@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/Makefile |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/Makefile
++++ b/drivers/gpu/drm/amd/amdgpu/Makefile
+@@ -22,7 +22,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o
+       amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o
+ # add asic specific block
+-amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o gmc_v7_0.o cik_ih.o kv_smc.o kv_dpm.o \
++amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \
+       ci_smc.o ci_dpm.o dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o \
+       amdgpu_amdkfd_gfx_v7.o
+@@ -31,6 +31,7 @@ amdgpu-y += \
+ # add GMC block
+ amdgpu-y += \
++      gmc_v7_0.o \
+       gmc_v8_0.o
+ # add IH block
diff --git a/queue-4.4/drm-amdgpu-no-need-to-load-mc-firmware-on-fiji.patch b/queue-4.4/drm-amdgpu-no-need-to-load-mc-firmware-on-fiji.patch
new file mode 100644 (file)
index 0000000..4e69c97
--- /dev/null
@@ -0,0 +1,48 @@
+From ad32152eb26043d165eed9406cb9e2f7011f6b10 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Thu, 28 Jan 2016 16:27:41 -0500
+Subject: drm/amdgpu: no need to load MC firmware on fiji
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit ad32152eb26043d165eed9406cb9e2f7011f6b10 upstream.
+
+Vbios does this for us on asic_init.
+
+Reviewed-by: Ken Wang >Qingqing.Wang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c |    6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+@@ -44,7 +44,6 @@ static void gmc_v8_0_set_irq_funcs(struc
+ MODULE_FIRMWARE("amdgpu/topaz_mc.bin");
+ MODULE_FIRMWARE("amdgpu/tonga_mc.bin");
+-MODULE_FIRMWARE("amdgpu/fiji_mc.bin");
+ static const u32 golden_settings_tonga_a11[] =
+ {
+@@ -236,8 +235,6 @@ static int gmc_v8_0_init_microcode(struc
+               chip_name = "tonga";
+               break;
+       case CHIP_FIJI:
+-              chip_name = "fiji";
+-              break;
+       case CHIP_CARRIZO:
+       case CHIP_STONEY:
+               return 0;
+@@ -1003,7 +1000,8 @@ static int gmc_v8_0_hw_init(void *handle
+       gmc_v8_0_mc_program(adev);
+-      if (!(adev->flags & AMD_IS_APU)) {
++      if ((adev->asic_type == CHIP_TOPAZ) ||
++          (adev->asic_type == CHIP_TONGA)) {
+               r = gmc_v8_0_mc_load_microcode(adev);
+               if (r) {
+                       DRM_ERROR("Failed to load MC firmware!\n");
diff --git a/queue-4.4/drm-amdgpu-pm-adjust-display-configuration-after-powerstate.patch b/queue-4.4/drm-amdgpu-pm-adjust-display-configuration-after-powerstate.patch
new file mode 100644 (file)
index 0000000..16d1e75
--- /dev/null
@@ -0,0 +1,49 @@
+From 8e7cedc6f7fe762ffe6e348502be34b11fa79298 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Fri, 19 Feb 2016 17:55:31 -0500
+Subject: drm/amdgpu/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 8e7cedc6f7fe762ffe6e348502be34b11fa79298 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/amd/amdgpu/amdgpu_pm.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+@@ -595,8 +595,6 @@ force:
+       /* update display watermarks based on new power state */
+       amdgpu_display_bandwidth_update(adev);
+-      /* update displays */
+-      amdgpu_dpm_display_configuration_changed(adev);
+       adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
+       adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
+@@ -616,6 +614,9 @@ force:
+       amdgpu_dpm_post_set_power_state(adev);
++      /* update displays */
++      amdgpu_dpm_display_configuration_changed(adev);
++
+       if (adev->pm.funcs->force_performance_level) {
+               if (adev->pm.dpm.thermal_active) {
+                       enum amdgpu_dpm_forced_level level = adev->pm.dpm.forced_level;
diff --git a/queue-4.4/drm-amdgpu-pull-topaz-gmc-bits-into-gmc_v7.patch b/queue-4.4/drm-amdgpu-pull-topaz-gmc-bits-into-gmc_v7.patch
new file mode 100644 (file)
index 0000000..54b32d5
--- /dev/null
@@ -0,0 +1,82 @@
+From 72b459c8f716ef03a8a0c78078547ce64d8d29a2 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Tue, 2 Feb 2016 10:56:15 -0500
+Subject: drm/amdgpu: pull topaz gmc bits into gmc_v7
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit 72b459c8f716ef03a8a0c78078547ce64d8d29a2 upstream.
+
+Add the topaz golden settings into the gmc7 module.
+
+Reviewed-by: Ken Wang <Qingqing.Wang@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c |   35 ++++++++++++++++++++++++++++++++--
+ 1 file changed, 33 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+@@ -44,8 +44,37 @@ MODULE_FIRMWARE("radeon/bonaire_mc.bin")
+ MODULE_FIRMWARE("radeon/hawaii_mc.bin");
+ MODULE_FIRMWARE("amdgpu/topaz_mc.bin");
++static const u32 golden_settings_iceland_a11[] =
++{
++      mmVM_PRT_APERTURE0_LOW_ADDR, 0x0fffffff, 0x0fffffff,
++      mmVM_PRT_APERTURE1_LOW_ADDR, 0x0fffffff, 0x0fffffff,
++      mmVM_PRT_APERTURE2_LOW_ADDR, 0x0fffffff, 0x0fffffff,
++      mmVM_PRT_APERTURE3_LOW_ADDR, 0x0fffffff, 0x0fffffff
++};
++
++static const u32 iceland_mgcg_cgcg_init[] =
++{
++      mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104
++};
++
++static void gmc_v7_0_init_golden_registers(struct amdgpu_device *adev)
++{
++      switch (adev->asic_type) {
++      case CHIP_TOPAZ:
++              amdgpu_program_register_sequence(adev,
++                                               iceland_mgcg_cgcg_init,
++                                               (const u32)ARRAY_SIZE(iceland_mgcg_cgcg_init));
++              amdgpu_program_register_sequence(adev,
++                                               golden_settings_iceland_a11,
++                                               (const u32)ARRAY_SIZE(golden_settings_iceland_a11));
++              break;
++      default:
++              break;
++      }
++}
++
+ /**
+- * gmc8_mc_wait_for_idle - wait for MC idle callback.
++ * gmc7_mc_wait_for_idle - wait for MC idle callback.
+  *
+  * @adev: amdgpu_device pointer
+  *
+@@ -142,7 +171,7 @@ static int gmc_v7_0_init_microcode(struc
+       default: BUG();
+       }
+-      if(adev->asic_type == CHIP_TOPAZ)
++      if (adev->asic_type == CHIP_TOPAZ)
+               snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mc.bin", chip_name);
+       else
+               snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
+@@ -988,6 +1017,8 @@ static int gmc_v7_0_hw_init(void *handle
+       int r;
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
++      gmc_v7_0_init_golden_registers(adev);
++
+       gmc_v7_0_mc_program(adev);
+       if (!(adev->flags & AMD_IS_APU)) {
diff --git a/queue-4.4/drm-amdgpu-remove-exp-hardware-support-from-iceland.patch b/queue-4.4/drm-amdgpu-remove-exp-hardware-support-from-iceland.patch
new file mode 100644 (file)
index 0000000..167dfcc
--- /dev/null
@@ -0,0 +1,45 @@
+From dba280b20bfd1c2bed8a07ce3f75a6da8ba7d247 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Tue, 2 Feb 2016 16:24:20 -0500
+Subject: drm/amdgpu: remove exp hardware support from iceland
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit dba280b20bfd1c2bed8a07ce3f75a6da8ba7d247 upstream.
+
+It's working now.
+
+bug:
+https://bugs.freedesktop.org/show_bug.cgi?id=92270
+
+Reviewed-by: Ken Wang <Qingqing.Wang@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c |   10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+@@ -250,11 +250,11 @@ static struct pci_device_id pciidlist[]
+       {0x1002, 0x985F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
+ #endif
+       /* topaz */
+-      {0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
+-      {0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
+-      {0x1002, 0x6902, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
+-      {0x1002, 0x6903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
+-      {0x1002, 0x6907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
++      {0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
++      {0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
++      {0x1002, 0x6902, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
++      {0x1002, 0x6903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
++      {0x1002, 0x6907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
+       /* tonga */
+       {0x1002, 0x6920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
+       {0x1002, 0x6921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
diff --git a/queue-4.4/drm-amdgpu-remove-unnecessary-forward-declaration.patch b/queue-4.4/drm-amdgpu-remove-unnecessary-forward-declaration.patch
new file mode 100644 (file)
index 0000000..b775970
--- /dev/null
@@ -0,0 +1,32 @@
+From b19763d0d867eb863953500a5c87f2fd663863b8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Nicolai=20H=C3=A4hnle?= <nicolai.haehnle@amd.com>
+Date: Fri, 5 Feb 2016 10:49:50 -0500
+Subject: drm/amdgpu: remove unnecessary forward declaration
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Nicolai Hähnle <nicolai.haehnle@amd.com>
+
+commit b19763d0d867eb863953500a5c87f2fd663863b8 upstream.
+
+Signed-off-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu.h |    2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+@@ -604,8 +604,6 @@ struct amdgpu_sa_manager {
+       uint32_t                align;
+ };
+-struct amdgpu_sa_bo;
+-
+ /* sub-allocation buffer */
+ struct amdgpu_sa_bo {
+       struct list_head                olist;
diff --git a/queue-4.4/drm-amdgpu-the-vi-specific-exe-bit-should-only-apply-to-gmc-v8.0-above.patch b/queue-4.4/drm-amdgpu-the-vi-specific-exe-bit-should-only-apply-to-gmc-v8.0-above.patch
new file mode 100644 (file)
index 0000000..552f1bc
--- /dev/null
@@ -0,0 +1,32 @@
+From 8f3c162961fc2d92ec73a66496aab69eb2e19c36 Mon Sep 17 00:00:00 2001
+From: Ken Wang <Qingqing.Wang@amd.com>
+Date: Wed, 3 Feb 2016 19:17:53 +0800
+Subject: drm/amdgpu: The VI specific EXE bit should only apply to GMC v8.0 above
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ken Wang <Qingqing.Wang@amd.com>
+
+commit 8f3c162961fc2d92ec73a66496aab69eb2e19c36 upstream.
+
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Ken Wang <Qingqing.Wang@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+@@ -808,7 +808,7 @@ uint32_t amdgpu_ttm_tt_pte_flags(struct
+                       flags |= AMDGPU_PTE_SNOOPED;
+       }
+-      if (adev->asic_type >= CHIP_TOPAZ)
++      if (adev->asic_type >= CHIP_TONGA)
+               flags |= AMDGPU_PTE_EXECUTABLE;
+       flags |= AMDGPU_PTE_READABLE;
diff --git a/queue-4.4/drm-amdgpu-use-post-decrement-in-error-handling.patch b/queue-4.4/drm-amdgpu-use-post-decrement-in-error-handling.patch
new file mode 100644 (file)
index 0000000..eed8725
--- /dev/null
@@ -0,0 +1,36 @@
+From 09ccbb74b6718ad4d1290de3f5669212c0ac7d4b Mon Sep 17 00:00:00 2001
+From: Rasmus Villemoes <linux@rasmusvillemoes.dk>
+Date: Mon, 15 Feb 2016 19:41:45 +0100
+Subject: drm/amdgpu: 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 09ccbb74b6718ad4d1290de3f5669212c0ac7d4b 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/amd/amdgpu/amdgpu_ttm.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+@@ -712,7 +712,7 @@ static int amdgpu_ttm_tt_populate(struct
+                                                      0, PAGE_SIZE,
+                                                      PCI_DMA_BIDIRECTIONAL);
+               if (pci_dma_mapping_error(adev->pdev, gtt->ttm.dma_address[i])) {
+-                      while (--i) {
++                      while (i--) {
+                               pci_unmap_page(adev->pdev, gtt->ttm.dma_address[i],
+                                              PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+                               gtt->ttm.dma_address[i] = 0;
diff --git a/queue-4.4/drm-dp-mst-always-send-reply-for-up-request.patch b/queue-4.4/drm-dp-mst-always-send-reply-for-up-request.patch
new file mode 100644 (file)
index 0000000..da65a77
--- /dev/null
@@ -0,0 +1,96 @@
+From 1f16ee7fa13649f4e55aa48ad31c3eb0722a62d3 Mon Sep 17 00:00:00 2001
+From: Mykola Lysenko <Mykola.Lysenko@amd.com>
+Date: Fri, 18 Dec 2015 17:14:43 -0500
+Subject: drm/dp/mst: always send reply for UP request
+
+From: Mykola Lysenko <Mykola.Lysenko@amd.com>
+
+commit 1f16ee7fa13649f4e55aa48ad31c3eb0722a62d3 upstream.
+
+We should always send reply for UP request in order
+to make downstream device clean-up resources appropriately.
+
+Issue was that reply for UP request was sent only once.
+
+Acked-by: Dave Airlie <airlied@gmail.com>
+Signed-off-by: Mykola Lysenko <Mykola.Lysenko@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_dp_mst_topology.c |   30 +++++++++++-------------------
+ include/drm/drm_dp_mst_helper.h       |    2 --
+ 2 files changed, 11 insertions(+), 21 deletions(-)
+
+--- a/drivers/gpu/drm/drm_dp_mst_topology.c
++++ b/drivers/gpu/drm/drm_dp_mst_topology.c
+@@ -1489,26 +1489,18 @@ static void process_single_down_tx_qlock
+ }
+ /* called holding qlock */
+-static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr)
++static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr,
++                                     struct drm_dp_sideband_msg_tx *txmsg)
+ {
+-      struct drm_dp_sideband_msg_tx *txmsg;
+       int ret;
+       /* construct a chunk from the first msg in the tx_msg queue */
+-      if (list_empty(&mgr->tx_msg_upq)) {
+-              mgr->tx_up_in_progress = false;
+-              return;
+-      }
+-
+-      txmsg = list_first_entry(&mgr->tx_msg_upq, struct drm_dp_sideband_msg_tx, next);
+       ret = process_single_tx_qlock(mgr, txmsg, true);
+-      if (ret == 1) {
+-              /* up txmsgs aren't put in slots - so free after we send it */
+-              list_del(&txmsg->next);
+-              kfree(txmsg);
+-      } else if (ret)
++
++      if (ret != 1)
+               DRM_DEBUG_KMS("failed to send msg in q %d\n", ret);
+-      mgr->tx_up_in_progress = true;
++
++      txmsg->dst->tx_slots[txmsg->seqno] = NULL;
+ }
+ static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr,
+@@ -1895,11 +1887,12 @@ static int drm_dp_send_up_ack_reply(stru
+       drm_dp_encode_up_ack_reply(txmsg, req_type);
+       mutex_lock(&mgr->qlock);
+-      list_add_tail(&txmsg->next, &mgr->tx_msg_upq);
+-      if (!mgr->tx_up_in_progress) {
+-              process_single_up_tx_qlock(mgr);
+-      }
++
++      process_single_up_tx_qlock(mgr, txmsg);
++
+       mutex_unlock(&mgr->qlock);
++
++      kfree(txmsg);
+       return 0;
+ }
+@@ -2809,7 +2802,6 @@ int drm_dp_mst_topology_mgr_init(struct
+       mutex_init(&mgr->qlock);
+       mutex_init(&mgr->payload_lock);
+       mutex_init(&mgr->destroy_connector_lock);
+-      INIT_LIST_HEAD(&mgr->tx_msg_upq);
+       INIT_LIST_HEAD(&mgr->tx_msg_downq);
+       INIT_LIST_HEAD(&mgr->destroy_connector_list);
+       INIT_WORK(&mgr->work, drm_dp_mst_link_probe_work);
+--- a/include/drm/drm_dp_mst_helper.h
++++ b/include/drm/drm_dp_mst_helper.h
+@@ -450,9 +450,7 @@ struct drm_dp_mst_topology_mgr {
+          the mstb tx_slots and txmsg->state once they are queued */
+       struct mutex qlock;
+       struct list_head tx_msg_downq;
+-      struct list_head tx_msg_upq;
+       bool tx_down_in_progress;
+-      bool tx_up_in_progress;
+       /* payload info + lock for it */
+       struct mutex payload_lock;
diff --git a/queue-4.4/drm-dp-mst-calculate-mst-pbn-with-31.32-fixed-point.patch b/queue-4.4/drm-dp-mst-calculate-mst-pbn-with-31.32-fixed-point.patch
new file mode 100644 (file)
index 0000000..a3fb1ba
--- /dev/null
@@ -0,0 +1,110 @@
+From a9ebb3e46c7ef6112c0da466ef0954673ad36832 Mon Sep 17 00:00:00 2001
+From: Harry Wentland <harry.wentland@amd.com>
+Date: Fri, 22 Jan 2016 17:07:26 -0500
+Subject: drm/dp/mst: Calculate MST PBN with 31.32 fixed point
+
+From: Harry Wentland <harry.wentland@amd.com>
+
+commit a9ebb3e46c7ef6112c0da466ef0954673ad36832 upstream.
+
+Our PBN value overflows the 20 bits integer part of the 20.12
+fixed point. We need to use 31.32 fixed point to avoid this.
+
+This happens with display clocks larger than 293122 (at 24 bpp),
+which we see with the Sharp (and similar) 4k tiled displays.
+
+Signed-off-by: Harry Wentland <harry.wentland@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_dp_mst_topology.c |   67 +++++++++++++++++++---------------
+ 1 file changed, 39 insertions(+), 28 deletions(-)
+
+--- a/drivers/gpu/drm/drm_dp_mst_topology.c
++++ b/drivers/gpu/drm/drm_dp_mst_topology.c
+@@ -2571,32 +2571,31 @@ EXPORT_SYMBOL(drm_dp_check_act_status);
+  */
+ int drm_dp_calc_pbn_mode(int clock, int bpp)
+ {
+-      fixed20_12 pix_bw;
+-      fixed20_12 fbpp;
+-      fixed20_12 result;
+-      fixed20_12 margin, tmp;
+-      u32 res;
+-
+-      pix_bw.full = dfixed_const(clock);
+-      fbpp.full = dfixed_const(bpp);
+-      tmp.full = dfixed_const(8);
+-      fbpp.full = dfixed_div(fbpp, tmp);
+-
+-      result.full = dfixed_mul(pix_bw, fbpp);
+-      margin.full = dfixed_const(54);
+-      tmp.full = dfixed_const(64);
+-      margin.full = dfixed_div(margin, tmp);
+-      result.full = dfixed_div(result, margin);
+-
+-      margin.full = dfixed_const(1006);
+-      tmp.full = dfixed_const(1000);
+-      margin.full = dfixed_div(margin, tmp);
+-      result.full = dfixed_mul(result, margin);
+-
+-      result.full = dfixed_div(result, tmp);
+-      result.full = dfixed_ceil(result);
+-      res = dfixed_trunc(result);
+-      return res;
++      u64 kbps;
++      s64 peak_kbps;
++      u32 numerator;
++      u32 denominator;
++
++      kbps = clock * bpp;
++
++      /*
++       * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
++       * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on
++       * common multiplier to render an integer PBN for all link rate/lane
++       * counts combinations
++       * calculate
++       * peak_kbps *= (1006/1000)
++       * peak_kbps *= (64/54)
++       * peak_kbps *= 8    convert to bytes
++       */
++
++      numerator = 64 * 1006;
++      denominator = 54 * 8 * 1000 * 1000;
++
++      kbps *= numerator;
++      peak_kbps = drm_fixp_from_fraction(kbps, denominator);
++
++      return drm_fixp2int_ceil(peak_kbps);
+ }
+ EXPORT_SYMBOL(drm_dp_calc_pbn_mode);
+@@ -2604,11 +2603,23 @@ static int test_calc_pbn_mode(void)
+ {
+       int ret;
+       ret = drm_dp_calc_pbn_mode(154000, 30);
+-      if (ret != 689)
++      if (ret != 689) {
++              DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n",
++                              154000, 30, 689, ret);
+               return -EINVAL;
++      }
+       ret = drm_dp_calc_pbn_mode(234000, 30);
+-      if (ret != 1047)
++      if (ret != 1047) {
++              DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n",
++                              234000, 30, 1047, ret);
++              return -EINVAL;
++      }
++      ret = drm_dp_calc_pbn_mode(297000, 24);
++      if (ret != 1063) {
++              DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n",
++                              297000, 24, 1063, ret);
+               return -EINVAL;
++      }
+       return 0;
+ }
diff --git a/queue-4.4/drm-dp-mst-deallocate-payload-on-port-destruction.patch b/queue-4.4/drm-dp-mst-deallocate-payload-on-port-destruction.patch
new file mode 100644 (file)
index 0000000..4555438
--- /dev/null
@@ -0,0 +1,195 @@
+From 91a25e463130c8e19bdb42f2d827836c7937992e Mon Sep 17 00:00:00 2001
+From: Mykola Lysenko <Mykola.Lysenko@amd.com>
+Date: Wed, 27 Jan 2016 09:39:36 -0500
+Subject: drm/dp/mst: deallocate payload on port destruction
+
+From: Mykola Lysenko <Mykola.Lysenko@amd.com>
+
+commit 91a25e463130c8e19bdb42f2d827836c7937992e upstream.
+
+This is needed to properly deallocate port payload
+after downstream branch get unplugged.
+
+In order to do this unplugged MST topology should
+be preserved, to find first alive port on path to
+unplugged MST topology, and send payload deallocation
+request to branch device of found port.
+
+For this mstb and port kref's are used in reversed
+order to track when port and branch memory could be
+freed.
+
+Added additional functions to find appropriate mstb
+as described above.
+
+Signed-off-by: Mykola Lysenko <Mykola.Lysenko@amd.com>
+Reviewed-by: Harry Wentland <Harry.Wentland@amd.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_dp_mst_topology.c |   91 +++++++++++++++++++++++++++++++---
+ 1 file changed, 83 insertions(+), 8 deletions(-)
+
+--- a/drivers/gpu/drm/drm_dp_mst_topology.c
++++ b/drivers/gpu/drm/drm_dp_mst_topology.c
+@@ -798,6 +798,18 @@ static struct drm_dp_mst_branch *drm_dp_
+       return mstb;
+ }
++static void drm_dp_free_mst_port(struct kref *kref);
++
++static void drm_dp_free_mst_branch_device(struct kref *kref)
++{
++      struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref);
++      if (mstb->port_parent) {
++              if (list_empty(&mstb->port_parent->next))
++                      kref_put(&mstb->port_parent->kref, drm_dp_free_mst_port);
++      }
++      kfree(mstb);
++}
++
+ static void drm_dp_destroy_mst_branch_device(struct kref *kref)
+ {
+       struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref);
+@@ -805,6 +817,15 @@ static void drm_dp_destroy_mst_branch_de
+       bool wake_tx = false;
+       /*
++       * init kref again to be used by ports to remove mst branch when it is
++       * not needed anymore
++       */
++      kref_init(kref);
++
++      if (mstb->port_parent && list_empty(&mstb->port_parent->next))
++              kref_get(&mstb->port_parent->kref);
++
++      /*
+        * destroy all ports - don't need lock
+        * as there are no more references to the mst branch
+        * device at this point.
+@@ -830,7 +851,8 @@ static void drm_dp_destroy_mst_branch_de
+       if (wake_tx)
+               wake_up(&mstb->mgr->tx_waitq);
+-      kfree(mstb);
++
++      kref_put(kref, drm_dp_free_mst_branch_device);
+ }
+ static void drm_dp_put_mst_branch_device(struct drm_dp_mst_branch *mstb)
+@@ -878,6 +900,7 @@ static void drm_dp_destroy_port(struct k
+                        * from an EDID retrieval */
+                       mutex_lock(&mgr->destroy_connector_lock);
++                      kref_get(&port->parent->kref);
+                       list_add(&port->next, &mgr->destroy_connector_list);
+                       mutex_unlock(&mgr->destroy_connector_lock);
+                       schedule_work(&mgr->destroy_connector_work);
+@@ -1602,6 +1625,37 @@ static int drm_dp_send_enum_path_resourc
+       return 0;
+ }
++static struct drm_dp_mst_port *drm_dp_get_last_connected_port_to_mstb(struct drm_dp_mst_branch *mstb)
++{
++      if (!mstb->port_parent)
++              return NULL;
++
++      if (mstb->port_parent->mstb != mstb)
++              return mstb->port_parent;
++
++      return drm_dp_get_last_connected_port_to_mstb(mstb->port_parent->parent);
++}
++
++static struct drm_dp_mst_branch *drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr,
++                                                                       struct drm_dp_mst_branch *mstb,
++                                                                       int *port_num)
++{
++      struct drm_dp_mst_branch *rmstb = NULL;
++      struct drm_dp_mst_port *found_port;
++      mutex_lock(&mgr->lock);
++      if (mgr->mst_primary) {
++              found_port = drm_dp_get_last_connected_port_to_mstb(mstb);
++
++              if (found_port) {
++                      rmstb = found_port->parent;
++                      kref_get(&rmstb->kref);
++                      *port_num = found_port->port_num;
++              }
++      }
++      mutex_unlock(&mgr->lock);
++      return rmstb;
++}
++
+ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
+                                  struct drm_dp_mst_port *port,
+                                  int id,
+@@ -1609,11 +1663,16 @@ static int drm_dp_payload_send_msg(struc
+ {
+       struct drm_dp_sideband_msg_tx *txmsg;
+       struct drm_dp_mst_branch *mstb;
+-      int len, ret;
++      int len, ret, port_num;
++      port_num = port->port_num;
+       mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent);
+-      if (!mstb)
+-              return -EINVAL;
++      if (!mstb) {
++              mstb = drm_dp_get_last_connected_port_and_mstb(mgr, port->parent, &port_num);
++
++              if (!mstb)
++                      return -EINVAL;
++      }
+       txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+       if (!txmsg) {
+@@ -1622,7 +1681,7 @@ static int drm_dp_payload_send_msg(struc
+       }
+       txmsg->dst = mstb;
+-      len = build_allocate_payload(txmsg, port->port_num,
++      len = build_allocate_payload(txmsg, port_num,
+                                    id,
+                                    pbn);
+@@ -2752,6 +2811,13 @@ static void drm_dp_tx_work(struct work_s
+       mutex_unlock(&mgr->qlock);
+ }
++static void drm_dp_free_mst_port(struct kref *kref)
++{
++      struct drm_dp_mst_port *port = container_of(kref, struct drm_dp_mst_port, kref);
++      kref_put(&port->parent->kref, drm_dp_free_mst_branch_device);
++      kfree(port);
++}
++
+ static void drm_dp_destroy_connector_work(struct work_struct *work)
+ {
+       struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work);
+@@ -2772,13 +2838,22 @@ static void drm_dp_destroy_connector_wor
+               list_del(&port->next);
+               mutex_unlock(&mgr->destroy_connector_lock);
++              kref_init(&port->kref);
++              INIT_LIST_HEAD(&port->next);
++
+               mgr->cbs->destroy_connector(mgr, port->connector);
+               drm_dp_port_teardown_pdt(port, port->pdt);
+-              if (!port->input && port->vcpi.vcpi > 0)
+-                      drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
+-              kfree(port);
++              if (!port->input && port->vcpi.vcpi > 0) {
++                      if (mgr->mst_state) {
++                              drm_dp_mst_reset_vcpi_slots(mgr, port);
++                              drm_dp_update_payload_part1(mgr);
++                              drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
++                      }
++              }
++
++              kref_put(&port->kref, drm_dp_free_mst_port);
+               send_hotplug = true;
+       }
+       if (send_hotplug)
diff --git a/queue-4.4/drm-dp-mst-fix-in-mstb-rad-initialization.patch b/queue-4.4/drm-dp-mst-fix-in-mstb-rad-initialization.patch
new file mode 100644 (file)
index 0000000..3fb3509
--- /dev/null
@@ -0,0 +1,48 @@
+From 75af4c8c4c0f60d7ad135419805798f144e9baf9 Mon Sep 17 00:00:00 2001
+From: Mykola Lysenko <Mykola.Lysenko@amd.com>
+Date: Fri, 25 Dec 2015 16:14:47 +0800
+Subject: drm/dp/mst: fix in MSTB RAD initialization
+
+From: Mykola Lysenko <Mykola.Lysenko@amd.com>
+
+commit 75af4c8c4c0f60d7ad135419805798f144e9baf9 upstream.
+
+This fix is needed to support more then two
+branch displays, so RAD address consist at
+least of 2 elements
+
+Acked-by: Dave Airlie <airlied@gmail.com>
+Signed-off-by: Mykola Lysenko <Mykola.Lysenko@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_dp_mst_topology.c |   12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/gpu/drm/drm_dp_mst_topology.c
++++ b/drivers/gpu/drm/drm_dp_mst_topology.c
+@@ -973,17 +973,17 @@ static struct drm_dp_mst_port *drm_dp_ge
+ static u8 drm_dp_calculate_rad(struct drm_dp_mst_port *port,
+                                u8 *rad)
+ {
+-      int lct = port->parent->lct;
++      int parent_lct = port->parent->lct;
+       int shift = 4;
+-      int idx = lct / 2;
+-      if (lct > 1) {
+-              memcpy(rad, port->parent->rad, idx);
+-              shift = (lct % 2) ? 4 : 0;
++      int idx = (parent_lct - 1) / 2;
++      if (parent_lct > 1) {
++              memcpy(rad, port->parent->rad, idx + 1);
++              shift = (parent_lct % 2) ? 4 : 0;
+       } else
+               rad[0] = 0;
+       rad[idx] |= port->port_num << shift;
+-      return lct + 1;
++      return parent_lct + 1;
+ }
+ /*
diff --git a/queue-4.4/drm-dp-mst-fix-in-rad-element-access.patch b/queue-4.4/drm-dp-mst-fix-in-rad-element-access.patch
new file mode 100644 (file)
index 0000000..60975b9
--- /dev/null
@@ -0,0 +1,41 @@
+From 7a11a334aa6af4c65c6a0d81b60c97fc18673532 Mon Sep 17 00:00:00 2001
+From: Mykola Lysenko <Mykola.Lysenko@amd.com>
+Date: Fri, 25 Dec 2015 16:14:48 +0800
+Subject: drm/dp/mst: fix in RAD element access
+
+From: Mykola Lysenko <Mykola.Lysenko@amd.com>
+
+commit 7a11a334aa6af4c65c6a0d81b60c97fc18673532 upstream.
+
+This is needed to receive correct port
+number from RAD, so MSTB could be found
+
+Acked-by: Dave Airlie <airlied@gmail.com>
+Signed-off-by: Mykola Lysenko <Mykola.Lysenko@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_dp_mst_topology.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/drm_dp_mst_topology.c
++++ b/drivers/gpu/drm/drm_dp_mst_topology.c
+@@ -1039,7 +1039,7 @@ static void build_mst_prop_path(const st
+       snprintf(proppath, proppath_size, "mst:%d", mstb->mgr->conn_base_id);
+       for (i = 0; i < (mstb->lct - 1); i++) {
+               int shift = (i % 2) ? 0 : 4;
+-              int port_num = mstb->rad[i / 2] >> shift;
++              int port_num = (mstb->rad[i / 2] >> shift) & 0xf;
+               snprintf(temp, sizeof(temp), "-%d", port_num);
+               strlcat(proppath, temp, proppath_size);
+       }
+@@ -1190,7 +1190,7 @@ static struct drm_dp_mst_branch *drm_dp_
+       for (i = 0; i < lct - 1; i++) {
+               int shift = (i % 2) ? 0 : 4;
+-              int port_num = rad[i / 2] >> shift;
++              int port_num = (rad[i / 2] >> shift) & 0xf;
+               list_for_each_entry(port, &mstb->ports, next) {
+                       if (port->port_num == port_num) {
diff --git a/queue-4.4/drm-dp-mst-move-guid-storage-from-mgr-port-to-only-mst-branch.patch b/queue-4.4/drm-dp-mst-move-guid-storage-from-mgr-port-to-only-mst-branch.patch
new file mode 100644 (file)
index 0000000..4cb69b1
--- /dev/null
@@ -0,0 +1,244 @@
+From 5e93b8208d3c419b515fb75e2601931c027e12ab Mon Sep 17 00:00:00 2001
+From: Hersen Wu <hersenxs.wu@amd.com>
+Date: Fri, 22 Jan 2016 17:07:28 -0500
+Subject: drm/dp/mst: move GUID storage from mgr, port to only mst branch
+
+From: Hersen Wu <hersenxs.wu@amd.com>
+
+commit 5e93b8208d3c419b515fb75e2601931c027e12ab upstream.
+
+Previous implementation does not handle case below: boot up one MST branch
+to DP connector of ASIC. After boot up, hot plug 2nd MST branch to DP output
+of 1st MST, GUID is not created for 2nd MST branch. When downstream port of
+2nd MST branch send upstream request, it fails because 2nd MST branch GUID
+is not available.
+
+New Implementation: only create GUID for MST branch and save it within Branch.
+
+Signed-off-by: Hersen Wu <hersenxs.wu@amd.com>
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_dp_mst_topology.c |   64 ++++++++++++++--------------------
+ include/drm/drm_dp_mst_helper.h       |   25 +++++--------
+ 2 files changed, 38 insertions(+), 51 deletions(-)
+
+--- a/drivers/gpu/drm/drm_dp_mst_topology.c
++++ b/drivers/gpu/drm/drm_dp_mst_topology.c
+@@ -1013,18 +1013,27 @@ static bool drm_dp_port_setup_pdt(struct
+       return send_link;
+ }
+-static void drm_dp_check_port_guid(struct drm_dp_mst_branch *mstb,
+-                                 struct drm_dp_mst_port *port)
++static void drm_dp_check_mstb_guid(struct drm_dp_mst_branch *mstb, u8 *guid)
+ {
+       int ret;
+-      if (port->dpcd_rev >= 0x12) {
+-              port->guid_valid = drm_dp_validate_guid(mstb->mgr, port->guid);
+-              if (!port->guid_valid) {
+-                      ret = drm_dp_send_dpcd_write(mstb->mgr,
+-                                                   port,
+-                                                   DP_GUID,
+-                                                   16, port->guid);
+-                      port->guid_valid = true;
++
++      memcpy(mstb->guid, guid, 16);
++
++      if (!drm_dp_validate_guid(mstb->mgr, mstb->guid)) {
++              if (mstb->port_parent) {
++                      ret = drm_dp_send_dpcd_write(
++                                      mstb->mgr,
++                                      mstb->port_parent,
++                                      DP_GUID,
++                                      16,
++                                      mstb->guid);
++              } else {
++
++                      ret = drm_dp_dpcd_write(
++                                      mstb->mgr->aux,
++                                      DP_GUID,
++                                      mstb->guid,
++                                      16);
+               }
+       }
+ }
+@@ -1081,7 +1090,6 @@ static void drm_dp_add_port(struct drm_d
+       port->dpcd_rev = port_msg->dpcd_revision;
+       port->num_sdp_streams = port_msg->num_sdp_streams;
+       port->num_sdp_stream_sinks = port_msg->num_sdp_stream_sinks;
+-      memcpy(port->guid, port_msg->peer_guid, 16);
+       /* manage mstb port lists with mgr lock - take a reference
+          for this list */
+@@ -1094,11 +1102,9 @@ static void drm_dp_add_port(struct drm_d
+       if (old_ddps != port->ddps) {
+               if (port->ddps) {
+-                      drm_dp_check_port_guid(mstb, port);
+                       if (!port->input)
+                               drm_dp_send_enum_path_resources(mstb->mgr, mstb, port);
+               } else {
+-                      port->guid_valid = false;
+                       port->available_pbn = 0;
+                       }
+       }
+@@ -1157,10 +1163,8 @@ static void drm_dp_update_port(struct dr
+       if (old_ddps != port->ddps) {
+               if (port->ddps) {
+-                      drm_dp_check_port_guid(mstb, port);
+                       dowork = true;
+               } else {
+-                      port->guid_valid = false;
+                       port->available_pbn = 0;
+               }
+       }
+@@ -1217,13 +1221,14 @@ static struct drm_dp_mst_branch *get_mst
+       struct drm_dp_mst_branch *found_mstb;
+       struct drm_dp_mst_port *port;
++      if (memcmp(mstb->guid, guid, 16) == 0)
++              return mstb;
++
++
+       list_for_each_entry(port, &mstb->ports, next) {
+               if (!port->mstb)
+                       continue;
+-              if (port->guid_valid && memcmp(port->guid, guid, 16) == 0)
+-                      return port->mstb;
+-
+               found_mstb = get_mst_branch_device_by_guid_helper(port->mstb, guid);
+               if (found_mstb)
+@@ -1242,10 +1247,7 @@ static struct drm_dp_mst_branch *drm_dp_
+       /* find the port by iterating down */
+       mutex_lock(&mgr->lock);
+-      if (mgr->guid_valid && memcmp(mgr->guid, guid, 16) == 0)
+-              mstb = mgr->mst_primary;
+-      else
+-              mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid);
++      mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid);
+       if (mstb)
+               kref_get(&mstb->kref);
+@@ -1550,6 +1552,9 @@ static void drm_dp_send_link_address(str
+                                      txmsg->reply.u.link_addr.ports[i].num_sdp_streams,
+                                      txmsg->reply.u.link_addr.ports[i].num_sdp_stream_sinks);
+                       }
++
++                      drm_dp_check_mstb_guid(mstb, txmsg->reply.u.link_addr.guid);
++
+                       for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) {
+                               drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]);
+                       }
+@@ -1984,20 +1989,6 @@ int drm_dp_mst_topology_mgr_set_mst(stru
+                       goto out_unlock;
+               }
+-
+-              /* sort out guid */
+-              ret = drm_dp_dpcd_read(mgr->aux, DP_GUID, mgr->guid, 16);
+-              if (ret != 16) {
+-                      DRM_DEBUG_KMS("failed to read DP GUID %d\n", ret);
+-                      goto out_unlock;
+-              }
+-
+-              mgr->guid_valid = drm_dp_validate_guid(mgr, mgr->guid);
+-              if (!mgr->guid_valid) {
+-                      ret = drm_dp_dpcd_write(mgr->aux, DP_GUID, mgr->guid, 16);
+-                      mgr->guid_valid = true;
+-              }
+-
+               queue_work(system_long_wq, &mgr->work);
+               ret = 0;
+@@ -2219,6 +2210,7 @@ static int drm_dp_mst_handle_up_req(stru
+                       }
+                       drm_dp_update_port(mstb, &msg.u.conn_stat);
++
+                       DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type);
+                       (*mgr->cbs->hotplug)(mgr);
+--- a/include/drm/drm_dp_mst_helper.h
++++ b/include/drm/drm_dp_mst_helper.h
+@@ -44,8 +44,6 @@ struct drm_dp_vcpi {
+ /**
+  * struct drm_dp_mst_port - MST port
+  * @kref: reference count for this port.
+- * @guid_valid: for DP 1.2 devices if we have validated the GUID.
+- * @guid: guid for DP 1.2 device on this port.
+  * @port_num: port number
+  * @input: if this port is an input port.
+  * @mcs: message capability status - DP 1.2 spec.
+@@ -70,10 +68,6 @@ struct drm_dp_vcpi {
+ struct drm_dp_mst_port {
+       struct kref kref;
+-      /* if dpcd 1.2 device is on this port - its GUID info */
+-      bool guid_valid;
+-      u8 guid[16];
+-
+       u8 port_num;
+       bool input;
+       bool mcs;
+@@ -109,10 +103,12 @@ struct drm_dp_mst_port {
+  * @tx_slots: transmission slots for this device.
+  * @last_seqno: last sequence number used to talk to this.
+  * @link_address_sent: if a link address message has been sent to this device yet.
++ * @guid: guid for DP 1.2 branch device. port under this branch can be
++ * identified by port #.
+  *
+  * This structure represents an MST branch device, there is one
+- * primary branch device at the root, along with any others connected
+- * to downstream ports
++ * primary branch device at the root, along with any other branches connected
++ * to downstream port of parent branches.
+  */
+ struct drm_dp_mst_branch {
+       struct kref kref;
+@@ -131,6 +127,9 @@ struct drm_dp_mst_branch {
+       struct drm_dp_sideband_msg_tx *tx_slots[2];
+       int last_seqno;
+       bool link_address_sent;
++
++      /* global unique identifier to identify branch devices */
++      u8 guid[16];
+ };
+@@ -405,11 +404,9 @@ struct drm_dp_payload {
+  * @conn_base_id: DRM connector ID this mgr is connected to.
+  * @down_rep_recv: msg receiver state for down replies.
+  * @up_req_recv: msg receiver state for up requests.
+- * @lock: protects mst state, primary, guid, dpcd.
++ * @lock: protects mst state, primary, dpcd.
+  * @mst_state: if this manager is enabled for an MST capable port.
+  * @mst_primary: pointer to the primary branch device.
+- * @guid_valid: GUID valid for the primary branch device.
+- * @guid: GUID for primary port.
+  * @dpcd: cache of DPCD for primary port.
+  * @pbn_div: PBN to slots divisor.
+  *
+@@ -431,13 +428,11 @@ struct drm_dp_mst_topology_mgr {
+       struct drm_dp_sideband_msg_rx up_req_recv;
+       /* pointer to info about the initial MST device */
+-      struct mutex lock; /* protects mst_state + primary + guid + dpcd */
++      struct mutex lock; /* protects mst_state + primary + dpcd */
+       bool mst_state;
+       struct drm_dp_mst_branch *mst_primary;
+-      /* primary MST device GUID */
+-      bool guid_valid;
+-      u8 guid[16];
++
+       u8 dpcd[DP_RECEIVER_CAP_SIZE];
+       u8 sink_count;
+       int pbn_div;
diff --git a/queue-4.4/drm-dp-mst-process-broadcast-messages-correctly.patch b/queue-4.4/drm-dp-mst-process-broadcast-messages-correctly.patch
new file mode 100644 (file)
index 0000000..2ae08e3
--- /dev/null
@@ -0,0 +1,163 @@
+From bd9343208704fcc70a5b919f228a7d26ae472727 Mon Sep 17 00:00:00 2001
+From: Mykola Lysenko <Mykola.Lysenko@amd.com>
+Date: Fri, 18 Dec 2015 17:14:42 -0500
+Subject: drm/dp/mst: process broadcast messages correctly
+
+From: Mykola Lysenko <Mykola.Lysenko@amd.com>
+
+commit bd9343208704fcc70a5b919f228a7d26ae472727 upstream.
+
+In case broadcast message received in UP request,
+RAD cannot be used to identify message originator.
+Message should be parsed, originator should be found
+by GUID from parsed message.
+
+Also reply with broadcast in case broadcast message
+received (for now it is always broadcast)
+
+Acked-by: Dave Airlie <airlied@gmail.com>
+Signed-off-by: Mykola Lysenko <Mykola.Lysenko@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_dp_mst_topology.c |   95 ++++++++++++++++++++++++++++++----
+ 1 file changed, 84 insertions(+), 11 deletions(-)
+
+--- a/drivers/gpu/drm/drm_dp_mst_topology.c
++++ b/drivers/gpu/drm/drm_dp_mst_topology.c
+@@ -1210,6 +1210,50 @@ out:
+       return mstb;
+ }
++static struct drm_dp_mst_branch *get_mst_branch_device_by_guid_helper(
++      struct drm_dp_mst_branch *mstb,
++      uint8_t *guid)
++{
++      struct drm_dp_mst_branch *found_mstb;
++      struct drm_dp_mst_port *port;
++
++      list_for_each_entry(port, &mstb->ports, next) {
++              if (!port->mstb)
++                      continue;
++
++              if (port->guid_valid && memcmp(port->guid, guid, 16) == 0)
++                      return port->mstb;
++
++              found_mstb = get_mst_branch_device_by_guid_helper(port->mstb, guid);
++
++              if (found_mstb)
++                      return found_mstb;
++      }
++
++      return NULL;
++}
++
++static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device_by_guid(
++      struct drm_dp_mst_topology_mgr *mgr,
++      uint8_t *guid)
++{
++      struct drm_dp_mst_branch *mstb;
++
++      /* find the port by iterating down */
++      mutex_lock(&mgr->lock);
++
++      if (mgr->guid_valid && memcmp(mgr->guid, guid, 16) == 0)
++              mstb = mgr->mst_primary;
++      else
++              mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid);
++
++      if (mstb)
++              kref_get(&mstb->kref);
++
++      mutex_unlock(&mgr->lock);
++      return mstb;
++}
++
+ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
+                                              struct drm_dp_mst_branch *mstb)
+ {
+@@ -1320,6 +1364,7 @@ static int set_hdr_from_dst_qlock(struct
+                                 struct drm_dp_sideband_msg_tx *txmsg)
+ {
+       struct drm_dp_mst_branch *mstb = txmsg->dst;
++      u8 req_type;
+       /* both msg slots are full */
+       if (txmsg->seqno == -1) {
+@@ -1336,7 +1381,13 @@ static int set_hdr_from_dst_qlock(struct
+                       txmsg->seqno = 1;
+               mstb->tx_slots[txmsg->seqno] = txmsg;
+       }
+-      hdr->broadcast = 0;
++
++      req_type = txmsg->msg[0] & 0x7f;
++      if (req_type == DP_CONNECTION_STATUS_NOTIFY ||
++              req_type == DP_RESOURCE_STATUS_NOTIFY)
++              hdr->broadcast = 1;
++      else
++              hdr->broadcast = 0;
+       hdr->path_msg = txmsg->path_msg;
+       hdr->lct = mstb->lct;
+       hdr->lcr = mstb->lct - 1;
+@@ -2145,28 +2196,50 @@ static int drm_dp_mst_handle_up_req(stru
+       if (mgr->up_req_recv.have_eomt) {
+               struct drm_dp_sideband_msg_req_body msg;
+-              struct drm_dp_mst_branch *mstb;
++              struct drm_dp_mst_branch *mstb = NULL;
+               bool seqno;
+-              mstb = drm_dp_get_mst_branch_device(mgr,
+-                                                  mgr->up_req_recv.initial_hdr.lct,
+-                                                  mgr->up_req_recv.initial_hdr.rad);
+-              if (!mstb) {
+-                      DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
+-                      memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+-                      return 0;
++
++              if (!mgr->up_req_recv.initial_hdr.broadcast) {
++                      mstb = drm_dp_get_mst_branch_device(mgr,
++                                                          mgr->up_req_recv.initial_hdr.lct,
++                                                          mgr->up_req_recv.initial_hdr.rad);
++                      if (!mstb) {
++                              DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
++                              memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
++                              return 0;
++                      }
+               }
+               seqno = mgr->up_req_recv.initial_hdr.seqno;
+               drm_dp_sideband_parse_req(&mgr->up_req_recv, &msg);
+               if (msg.req_type == DP_CONNECTION_STATUS_NOTIFY) {
+-                      drm_dp_send_up_ack_reply(mgr, mstb, msg.req_type, seqno, false);
++                      drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
++
++                      if (!mstb)
++                              mstb = drm_dp_get_mst_branch_device_by_guid(mgr, msg.u.conn_stat.guid);
++
++                      if (!mstb) {
++                              DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
++                              memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
++                              return 0;
++                      }
++
+                       drm_dp_update_port(mstb, &msg.u.conn_stat);
+                       DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type);
+                       (*mgr->cbs->hotplug)(mgr);
+               } else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
+-                      drm_dp_send_up_ack_reply(mgr, mstb, msg.req_type, seqno, false);
++                      drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
++                      if (!mstb)
++                              mstb = drm_dp_get_mst_branch_device_by_guid(mgr, msg.u.resource_stat.guid);
++
++                      if (!mstb) {
++                              DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
++                              memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
++                              return 0;
++                      }
++
+                       DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n", msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn);
+               }
diff --git a/queue-4.4/drm-dp-mst-reverse-order-of-mst-enable-and-clearing-vc-payload-table.patch b/queue-4.4/drm-dp-mst-reverse-order-of-mst-enable-and-clearing-vc-payload-table.patch
new file mode 100644 (file)
index 0000000..a47960a
--- /dev/null
@@ -0,0 +1,50 @@
+From c175cd16df272119534058f28cbd5eeac6ff2d24 Mon Sep 17 00:00:00 2001
+From: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
+Date: Fri, 22 Jan 2016 17:07:29 -0500
+Subject: drm/dp/mst: Reverse order of MST enable and clearing VC payload table.
+
+From: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
+
+commit c175cd16df272119534058f28cbd5eeac6ff2d24 upstream.
+
+On DELL U3014 if you clear the table before enabling MST it sometimes
+hangs the receiver.
+
+Signed-off-by: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_dp_mst_topology.c |   12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/gpu/drm/drm_dp_mst_topology.c
++++ b/drivers/gpu/drm/drm_dp_mst_topology.c
+@@ -1976,6 +1976,12 @@ int drm_dp_mst_topology_mgr_set_mst(stru
+               mgr->mst_primary = mstb;
+               kref_get(&mgr->mst_primary->kref);
++              ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
++                                                       DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC);
++              if (ret < 0) {
++                      goto out_unlock;
++              }
++
+               {
+                       struct drm_dp_payload reset_pay;
+                       reset_pay.start_slot = 0;
+@@ -1983,12 +1989,6 @@ int drm_dp_mst_topology_mgr_set_mst(stru
+                       drm_dp_dpcd_write_payload(mgr, 0, &reset_pay);
+               }
+-              ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
+-                                       DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC);
+-              if (ret < 0) {
+-                      goto out_unlock;
+-              }
+-
+               queue_work(system_long_wq, &mgr->work);
+               ret = 0;
diff --git a/queue-4.4/drm-nouveau-disp-dp-ensure-sink-is-powered-up-before-attempting-link-training.patch b/queue-4.4/drm-nouveau-disp-dp-ensure-sink-is-powered-up-before-attempting-link-training.patch
new file mode 100644 (file)
index 0000000..130b73c
--- /dev/null
@@ -0,0 +1,62 @@
+From 95664e66fad964c3dd7945d6edfb1d0931844664 Mon Sep 17 00:00:00 2001
+From: Ben Skeggs <bskeggs@redhat.com>
+Date: Thu, 18 Feb 2016 08:14:19 +1000
+Subject: drm/nouveau/disp/dp: ensure sink is powered up before attempting link training
+
+From: Ben Skeggs <bskeggs@redhat.com>
+
+commit 95664e66fad964c3dd7945d6edfb1d0931844664 upstream.
+
+This can happen under some annoying circumstances, and is a quick fix
+until more substantial changes can be made.
+
+Fixed eDP mode changes on (at least) the Lenovo P50.
+
+Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c |   10 ++++++++++
+ drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h |    6 ++++++
+ 2 files changed, 16 insertions(+)
+
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c
+@@ -328,6 +328,7 @@ nvkm_dp_train(struct work_struct *w)
+               .outp = outp,
+       }, *dp = &_dp;
+       u32 datarate = 0;
++      u8  pwr;
+       int ret;
+       if (!outp->base.info.location && disp->func->sor.magic)
+@@ -355,6 +356,15 @@ nvkm_dp_train(struct work_struct *w)
+       /* disable link interrupt handling during link training */
+       nvkm_notify_put(&outp->irq);
++      /* ensure sink is not in a low-power state */
++      if (!nvkm_rdaux(outp->aux, DPCD_SC00, &pwr, 1)) {
++              if ((pwr & DPCD_SC00_SET_POWER) != DPCD_SC00_SET_POWER_D0) {
++                      pwr &= ~DPCD_SC00_SET_POWER;
++                      pwr |=  DPCD_SC00_SET_POWER_D0;
++                      nvkm_wraux(outp->aux, DPCD_SC00, &pwr, 1);
++              }
++      }
++
+       /* enable down-spreading and execute pre-train script from vbios */
+       dp_link_train_init(dp, outp->dpcd[3] & 0x01);
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h
+@@ -71,5 +71,11 @@
+ #define DPCD_LS0C_LANE1_POST_CURSOR2                                       0x0c
+ #define DPCD_LS0C_LANE0_POST_CURSOR2                                       0x03
++/* DPCD Sink Control */
++#define DPCD_SC00                                                       0x00600
++#define DPCD_SC00_SET_POWER                                                0x03
++#define DPCD_SC00_SET_POWER_D0                                             0x01
++#define DPCD_SC00_SET_POWER_D3                                             0x03
++
+ void nvkm_dp_train(struct work_struct *);
+ #endif
diff --git a/queue-4.4/drm-nouveau-display-enable-vblank-irqs-after-display-engine-is-on-again.patch b/queue-4.4/drm-nouveau-display-enable-vblank-irqs-after-display-engine-is-on-again.patch
new file mode 100644 (file)
index 0000000..fe71adb
--- /dev/null
@@ -0,0 +1,60 @@
+From ff683df7bf34f90766a50c7e7454e219aef2710e Mon Sep 17 00:00:00 2001
+From: Mario Kleiner <mario.kleiner.de@gmail.com>
+Date: Fri, 12 Feb 2016 20:30:32 +0100
+Subject: drm/nouveau/display: Enable vblank irqs after display engine is on again.
+
+From: Mario Kleiner <mario.kleiner.de@gmail.com>
+
+commit ff683df7bf34f90766a50c7e7454e219aef2710e upstream.
+
+In the display resume path, move the calls to drm_vblank_on()
+after the point when the display engine is running again.
+
+Since changes were made to drm_update_vblank_count() in Linux 4.4+
+to emulate hw vblank counters via vblank timestamping, the function
+drm_vblank_on() now needs working high precision vblank timestamping
+and therefore working scanout position queries at time of call.
+These don't work before the display engine gets restarted, causing
+miscalculation of vblank counter increments and thereby large forward
+jumps in vblank count at display resume. These jumps can cause client
+hangs on resume, or desktop hangs in the case of composited desktops.
+
+Fix this Linux 4.4 regression by reordering calls accordingly.
+
+Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
+Cc: Ben Skeggs <bskeggs@redhat.com>
+Cc: ville.syrjala@linux.intel.com
+Cc: daniel.vetter@ffwll.ch
+Cc: dri-devel@lists.freedesktop.org
+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/nouveau/nouveau_display.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/nouveau/nouveau_display.c
++++ b/drivers/gpu/drm/nouveau/nouveau_display.c
+@@ -634,10 +634,6 @@ nouveau_display_resume(struct drm_device
+               nv_crtc->lut.depth = 0;
+       }
+-      /* Make sure that drm and hw vblank irqs get resumed if needed. */
+-      for (head = 0; head < dev->mode_config.num_crtc; head++)
+-              drm_vblank_on(dev, head);
+-
+       /* This should ensure we don't hit a locking problem when someone
+        * wakes us up via a connector.  We should never go into suspend
+        * while the display is on anyways.
+@@ -647,6 +643,10 @@ nouveau_display_resume(struct drm_device
+       drm_helper_resume_force_mode(dev);
++      /* Make sure that drm and hw vblank irqs get resumed if needed. */
++      for (head = 0; head < dev->mode_config.num_crtc; head++)
++              drm_vblank_on(dev, head);
++
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
diff --git a/queue-4.4/drm-nouveau-kms-take-mode_config-mutex-in-connector-hotplug-path.patch b/queue-4.4/drm-nouveau-kms-take-mode_config-mutex-in-connector-hotplug-path.patch
new file mode 100644 (file)
index 0000000..e10319e
--- /dev/null
@@ -0,0 +1,34 @@
+From 0a882cadbc63fd2da3994af7115b4ada2fcbd638 Mon Sep 17 00:00:00 2001
+From: Ben Skeggs <bskeggs@redhat.com>
+Date: Fri, 8 Jan 2016 08:56:51 +1000
+Subject: drm/nouveau/kms: take mode_config mutex in connector hotplug path
+
+From: Ben Skeggs <bskeggs@redhat.com>
+
+commit 0a882cadbc63fd2da3994af7115b4ada2fcbd638 upstream.
+
+fdo#93634
+
+Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/nouveau/nouveau_connector.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
+@@ -969,10 +969,13 @@ nouveau_connector_hotplug(struct nvif_no
+               NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name);
++              mutex_lock(&drm->dev->mode_config.mutex);
+               if (plugged)
+                       drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+               else
+                       drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
++              mutex_unlock(&drm->dev->mode_config.mutex);
++
+               drm_helper_hpd_irq_event(connector->dev);
+       }
diff --git a/queue-4.4/drm-nouveau-platform-fix-deferred-probe.patch b/queue-4.4/drm-nouveau-platform-fix-deferred-probe.patch
new file mode 100644 (file)
index 0000000..15f2d13
--- /dev/null
@@ -0,0 +1,108 @@
+From 870571a5698b2e9d0f4d2e5c6245967b582aab45 Mon Sep 17 00:00:00 2001
+From: Thierry Reding <treding@nvidia.com>
+Date: Wed, 24 Feb 2016 18:34:43 +0100
+Subject: drm/nouveau: platform: Fix deferred probe
+
+From: Thierry Reding <treding@nvidia.com>
+
+commit 870571a5698b2e9d0f4d2e5c6245967b582aab45 upstream.
+
+The error cleanup paths aren't quite correct and will crash upon
+deferred probe.
+
+Reviewed-by: Ben Skeggs <bskeggs@redhat.com>
+Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
+Signed-off-by: Thierry Reding <treding@nvidia.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/nouveau/nouveau_platform.c         |    2 -
+ drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c |   40 +++++++++++++++------
+ 2 files changed, 30 insertions(+), 12 deletions(-)
+
+--- a/drivers/gpu/drm/nouveau/nouveau_platform.c
++++ b/drivers/gpu/drm/nouveau/nouveau_platform.c
+@@ -24,7 +24,7 @@
+ static int nouveau_platform_probe(struct platform_device *pdev)
+ {
+       const struct nvkm_device_tegra_func *func;
+-      struct nvkm_device *device;
++      struct nvkm_device *device = NULL;
+       struct drm_device *drm;
+       int ret;
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
+@@ -252,32 +252,40 @@ nvkm_device_tegra_new(const struct nvkm_
+       if (!(tdev = kzalloc(sizeof(*tdev), GFP_KERNEL)))
+               return -ENOMEM;
+-      *pdevice = &tdev->device;
++
+       tdev->func = func;
+       tdev->pdev = pdev;
+       tdev->irq = -1;
+       tdev->vdd = devm_regulator_get(&pdev->dev, "vdd");
+-      if (IS_ERR(tdev->vdd))
+-              return PTR_ERR(tdev->vdd);
++      if (IS_ERR(tdev->vdd)) {
++              ret = PTR_ERR(tdev->vdd);
++              goto free;
++      }
+       tdev->rst = devm_reset_control_get(&pdev->dev, "gpu");
+-      if (IS_ERR(tdev->rst))
+-              return PTR_ERR(tdev->rst);
++      if (IS_ERR(tdev->rst)) {
++              ret = PTR_ERR(tdev->rst);
++              goto free;
++      }
+       tdev->clk = devm_clk_get(&pdev->dev, "gpu");
+-      if (IS_ERR(tdev->clk))
+-              return PTR_ERR(tdev->clk);
++      if (IS_ERR(tdev->clk)) {
++              ret = PTR_ERR(tdev->clk);
++              goto free;
++      }
+       tdev->clk_pwr = devm_clk_get(&pdev->dev, "pwr");
+-      if (IS_ERR(tdev->clk_pwr))
+-              return PTR_ERR(tdev->clk_pwr);
++      if (IS_ERR(tdev->clk_pwr)) {
++              ret = PTR_ERR(tdev->clk_pwr);
++              goto free;
++      }
+       nvkm_device_tegra_probe_iommu(tdev);
+       ret = nvkm_device_tegra_power_up(tdev);
+       if (ret)
+-              return ret;
++              goto remove;
+       tdev->gpu_speedo = tegra_sku_info.gpu_speedo_value;
+       ret = nvkm_device_ctor(&nvkm_device_tegra_func, NULL, &pdev->dev,
+@@ -285,9 +293,19 @@ nvkm_device_tegra_new(const struct nvkm_
+                              cfg, dbg, detect, mmio, subdev_mask,
+                              &tdev->device);
+       if (ret)
+-              return ret;
++              goto powerdown;
++
++      *pdevice = &tdev->device;
+       return 0;
++
++powerdown:
++      nvkm_device_tegra_power_down(tdev);
++remove:
++      nvkm_device_tegra_remove_iommu(tdev);
++free:
++      kfree(tdev);
++      return ret;
+ }
+ #else
+ int
diff --git a/queue-4.4/drm-vmwgfx-fix-a-width-pitch-mismatch-on-framebuffer-updates.patch b/queue-4.4/drm-vmwgfx-fix-a-width-pitch-mismatch-on-framebuffer-updates.patch
new file mode 100644 (file)
index 0000000..b8452fc
--- /dev/null
@@ -0,0 +1,65 @@
+From a50e2bf5a0f674d62b69f51f6935a30e82bd015c Mon Sep 17 00:00:00 2001
+From: Thomas Hellstrom <thellstrom@vmware.com>
+Date: Fri, 8 Jan 2016 20:29:40 +0100
+Subject: drm/vmwgfx: Fix a width / pitch mismatch on framebuffer updates
+
+From: Thomas Hellstrom <thellstrom@vmware.com>
+
+commit a50e2bf5a0f674d62b69f51f6935a30e82bd015c upstream.
+
+When the framebuffer is a vmwgfx dma buffer and a proxy surface is
+created, the vmw_kms_update_proxy() function requires that the proxy
+surface width and the framebuffer pitch are compatible, otherwise
+display corruption occurs as seen in gnome-shell/native with software
+3D. Since the framebuffer pitch is determined by user-space, allocate
+a proxy surface the width of which is based on the framebuffer pitch
+rather than on the framebuffer width.
+
+Reported-by: Raphael Hertzog <buxy@kali.org>
+Tested-by:  Mati Aharoni <muts@kali.org>
+Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
+Reviewed-by: Brian Paul <brianp@vmware.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/vmwgfx/vmwgfx_kms.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+@@ -763,21 +763,25 @@ static int vmw_create_dmabuf_proxy(struc
+       uint32_t format;
+       struct drm_vmw_size content_base_size;
+       struct vmw_resource *res;
++      unsigned int bytes_pp;
+       int ret;
+       switch (mode_cmd->depth) {
+       case 32:
+       case 24:
+               format = SVGA3D_X8R8G8B8;
++              bytes_pp = 4;
+               break;
+       case 16:
+       case 15:
+               format = SVGA3D_R5G6B5;
++              bytes_pp = 2;
+               break;
+       case 8:
+               format = SVGA3D_P8;
++              bytes_pp = 1;
+               break;
+       default:
+@@ -785,7 +789,7 @@ static int vmw_create_dmabuf_proxy(struc
+               return -EINVAL;
+       }
+-      content_base_size.width  = mode_cmd->width;
++      content_base_size.width  = mode_cmd->pitch / bytes_pp;
+       content_base_size.height = mode_cmd->height;
+       content_base_size.depth  = 1;
diff --git a/queue-4.4/drm-vmwgfx-fix-an-incorrect-lock-check.patch b/queue-4.4/drm-vmwgfx-fix-an-incorrect-lock-check.patch
new file mode 100644 (file)
index 0000000..294963e
--- /dev/null
@@ -0,0 +1,34 @@
+From fb89ac5102ae2875d685c847e6b5dbc141622d43 Mon Sep 17 00:00:00 2001
+From: Thomas Hellstrom <thellstrom@vmware.com>
+Date: Fri, 8 Jan 2016 20:29:39 +0100
+Subject: drm/vmwgfx: Fix an incorrect lock check
+
+From: Thomas Hellstrom <thellstrom@vmware.com>
+
+commit fb89ac5102ae2875d685c847e6b5dbc141622d43 upstream.
+
+With CONFIG_SMP=n and CONFIG_DEBUG_SPINLOCK=y the vmwgfx kernel module
+would unconditionally throw a bug when checking for a held spinlock
+in the command buffer code. Fix this by using a lockdep check.
+
+Reported-and-tested-by: Tetsuo Handa <penguin-kernel@i-love-sakura.ne.jp>
+Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
+Reviewed-by: Sinclair Yeh <syeh@vmware.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
+@@ -247,7 +247,7 @@ static void __vmw_cmdbuf_header_free(str
+ {
+       struct vmw_cmdbuf_man *man = header->man;
+-      BUG_ON(!spin_is_locked(&man->lock));
++      lockdep_assert_held_once(&man->lock);
+       if (header->inline_space) {
+               vmw_cmdbuf_header_inline_free(header);
diff --git a/queue-4.4/drm-vmwgfx-respect-nomodeset.patch b/queue-4.4/drm-vmwgfx-respect-nomodeset.patch
new file mode 100644 (file)
index 0000000..15356d5
--- /dev/null
@@ -0,0 +1,41 @@
+From 96c5d076f0a5e2023ecdb44d8261f87641ee71e0 Mon Sep 17 00:00:00 2001
+From: Rob Clark <robdclark@gmail.com>
+Date: Wed, 15 Oct 2014 15:00:47 -0400
+Subject: drm/vmwgfx: respect 'nomodeset'
+
+From: Rob Clark <robdclark@gmail.com>
+
+commit 96c5d076f0a5e2023ecdb44d8261f87641ee71e0 upstream.
+
+Signed-off-by: Rob Clark <robdclark@gmail.com>
+Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>.
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/vmwgfx/vmwgfx_drv.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+@@ -25,6 +25,7 @@
+  *
+  **************************************************************************/
+ #include <linux/module.h>
++#include <linux/console.h>
+ #include <drm/drmP.h>
+ #include "vmwgfx_drv.h"
+@@ -1538,6 +1539,12 @@ static int vmw_probe(struct pci_dev *pde
+ static int __init vmwgfx_init(void)
+ {
+       int ret;
++
++#ifdef CONFIG_VGA_CONSOLE
++      if (vgacon_text_force())
++              return -EINVAL;
++#endif
++
+       ret = drm_pci_init(&driver, &vmw_pci_driver);
+       if (ret)
+               DRM_ERROR("Failed initializing DRM.\n");
index bd231e03884be269592414548e97e0897ef6ff4b..95bf492c5c55a2ef8db9730d9b5e040a4cf6421c 100644 (file)
@@ -163,3 +163,42 @@ cxl-use-correct-operator-when-writing-pcie-config-space-values.patch
 clk-exynos-use-irqsave-version-of-spin_lock-to-avoid-deadlock-with-irqs.patch
 regulator-axp20x-fix-gpio-ldo-enable-value-for-axp22x.patch
 regulator-mt6311-mt6311_regulator-needs-to-select-regmap_i2c.patch
+virtio_balloon-fix-race-by-fill-and-leak.patch
+virtio_balloon-fix-race-between-migration-and-ballooning.patch
+virtio_pci-fix-use-after-free-on-release.patch
+drm-vmwgfx-fix-an-incorrect-lock-check.patch
+drm-vmwgfx-fix-a-width-pitch-mismatch-on-framebuffer-updates.patch
+drm-vmwgfx-respect-nomodeset.patch
+drm-amdgpu-fix-off-by-one-errors-in-amdgpu_vm_bo_map.patch
+drm-amdgpu-call-hpd_irq_event-on-resume.patch
+drm-amdgpu-fix-lost-sync_to-if-scheduler-is-enabled.patch
+drm-amdgpu-fix-tonga-smu-resume.patch
+drm-amdgpu-fix-amdgpu_bo_pin_restricted-vram-placing-v2.patch
+drm-amdgpu-no-need-to-load-mc-firmware-on-fiji.patch
+drm-amdgpu-move-gmc7-support-out-of-cik-dependency.patch
+drm-amdgpu-iceland-use-ci-based-mc-ip.patch
+drm-amdgpu-the-vi-specific-exe-bit-should-only-apply-to-gmc-v8.0-above.patch
+drm-amdgpu-pull-topaz-gmc-bits-into-gmc_v7.patch
+drm-amdgpu-drop-topaz-support-from-gmc8-module.patch
+drm-amdgpu-don-t-load-mec2-on-topaz.patch
+drm-amdgpu-remove-exp-hardware-support-from-iceland.patch
+drm-amdgpu-fix-s4-resume.patch
+drm-amdgpu-remove-unnecessary-forward-declaration.patch
+drm-amdgpu-hold-reference-to-fences-in-amdgpu_sa_bo_new-v2.patch
+drm-amdgpu-fix-issue-with-overlapping-userptrs.patch
+drm-amdgpu-use-post-decrement-in-error-handling.patch
+drm-amdgpu-don-t-hang-in-amdgpu_flip_work_func-on-disabled-crtc.patch
+drm-amdgpu-pm-adjust-display-configuration-after-powerstate.patch
+drm-nouveau-kms-take-mode_config-mutex-in-connector-hotplug-path.patch
+drm-nouveau-display-enable-vblank-irqs-after-display-engine-is-on-again.patch
+drm-nouveau-disp-dp-ensure-sink-is-powered-up-before-attempting-link-training.patch
+drm-nouveau-platform-fix-deferred-probe.patch
+drm-dp-mst-process-broadcast-messages-correctly.patch
+drm-dp-mst-always-send-reply-for-up-request.patch
+drm-dp-mst-fix-in-mstb-rad-initialization.patch
+drm-dp-mst-fix-in-rad-element-access.patch
+drm-add-drm_fixp_from_fraction-and-drm_fixp2int_ceil.patch
+drm-dp-mst-calculate-mst-pbn-with-31.32-fixed-point.patch
+drm-dp-mst-move-guid-storage-from-mgr-port-to-only-mst-branch.patch
+drm-dp-mst-reverse-order-of-mst-enable-and-clearing-vc-payload-table.patch
+drm-dp-mst-deallocate-payload-on-port-destruction.patch
diff --git a/queue-4.4/virtio_balloon-fix-race-between-migration-and-ballooning.patch b/queue-4.4/virtio_balloon-fix-race-between-migration-and-ballooning.patch
new file mode 100644 (file)
index 0000000..3460d0a
--- /dev/null
@@ -0,0 +1,91 @@
+From 21ea9fb69e7c4b1b1559c3e410943d3ff248ffcb Mon Sep 17 00:00:00 2001
+From: Minchan Kim <minchan@kernel.org>
+Date: Mon, 28 Dec 2015 08:35:13 +0900
+Subject: virtio_balloon: fix race between migration and ballooning
+
+From: Minchan Kim <minchan@kernel.org>
+
+commit 21ea9fb69e7c4b1b1559c3e410943d3ff248ffcb upstream.
+
+In balloon_page_dequeue, pages_lock should cover the loop
+(ie, list_for_each_entry_safe). Otherwise, the cursor page could
+be isolated by compaction and then list_del by isolation could
+poison the page->lru.{prev,next} so the loop finally could
+access wrong address like this. This patch fixes the bug.
+
+general protection fault: 0000 [#1] SMP
+Dumping ftrace buffer:
+   (ftrace buffer empty)
+Modules linked in:
+CPU: 2 PID: 82 Comm: vballoon Not tainted 4.4.0-rc5-mm1-access_bit+ #1906
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
+task: ffff8800a7ff0000 ti: ffff8800a7fec000 task.ti: ffff8800a7fec000
+RIP: 0010:[<ffffffff8115e754>]  [<ffffffff8115e754>] balloon_page_dequeue+0x54/0x130
+RSP: 0018:ffff8800a7fefdc0  EFLAGS: 00010246
+RAX: ffff88013fff9a70 RBX: ffffea000056fe00 RCX: 0000000000002b7d
+RDX: ffff88013fff9a70 RSI: ffffea000056fe00 RDI: ffff88013fff9a68
+RBP: ffff8800a7fefde8 R08: ffffea000056fda0 R09: 0000000000000000
+R10: ffff8800a7fefd90 R11: 0000000000000001 R12: dead0000000000e0
+R13: ffffea000056fe20 R14: ffff880138809070 R15: ffff880138809060
+FS:  0000000000000000(0000) GS:ffff88013fc40000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
+CR2: 00007f229c10e000 CR3: 00000000b8b53000 CR4: 00000000000006a0
+Stack:
+ 0000000000000100 ffff880138809088 ffff880138809000 ffff880138809060
+ 0000000000000046 ffff8800a7fefe28 ffffffff812c86d3 ffff880138809020
+ ffff880138809000 fffffffffff91900 0000000000000100 ffff880138809060
+Call Trace:
+ [<ffffffff812c86d3>] leak_balloon+0x93/0x1a0
+ [<ffffffff812c8bc7>] balloon+0x217/0x2a0
+ [<ffffffff8143739e>] ? __schedule+0x31e/0x8b0
+ [<ffffffff81078160>] ? abort_exclusive_wait+0xb0/0xb0
+ [<ffffffff812c89b0>] ? update_balloon_stats+0xf0/0xf0
+ [<ffffffff8105b6e9>] kthread+0xc9/0xe0
+ [<ffffffff8105b620>] ? kthread_park+0x60/0x60
+ [<ffffffff8143b4af>] ret_from_fork+0x3f/0x70
+ [<ffffffff8105b620>] ? kthread_park+0x60/0x60
+Code: 8d 60 e0 0f 84 af 00 00 00 48 8b 43 20 a8 01 75 3b 48 89 d8 f0 0f ba 28 00 72 10 48 8b 03 f6 c4 08 75 2f 48 89 df e8 8c 83 f9 ff <49> 8b 44 24 20 4d 8d 6c 24 20 48 83 e8 20 4d 39 f5 74 7a 4c 89
+RIP  [<ffffffff8115e754>] balloon_page_dequeue+0x54/0x130
+ RSP <ffff8800a7fefdc0>
+---[ end trace 43cf28060d708d5f ]---
+Kernel panic - not syncing: Fatal exception
+Dumping ftrace buffer:
+   (ftrace buffer empty)
+Kernel Offset: disabled
+
+Signed-off-by: Minchan Kim <minchan@kernel.org>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Acked-by: Rafael Aquini <aquini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ mm/balloon_compaction.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/mm/balloon_compaction.c
++++ b/mm/balloon_compaction.c
+@@ -61,6 +61,7 @@ struct page *balloon_page_dequeue(struct
+       bool dequeued_page;
+       dequeued_page = false;
++      spin_lock_irqsave(&b_dev_info->pages_lock, flags);
+       list_for_each_entry_safe(page, tmp, &b_dev_info->pages, lru) {
+               /*
+                * Block others from accessing the 'page' while we get around
+@@ -75,15 +76,14 @@ struct page *balloon_page_dequeue(struct
+                               continue;
+                       }
+ #endif
+-                      spin_lock_irqsave(&b_dev_info->pages_lock, flags);
+                       balloon_page_delete(page);
+                       __count_vm_event(BALLOON_DEFLATE);
+-                      spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
+                       unlock_page(page);
+                       dequeued_page = true;
+                       break;
+               }
+       }
++      spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
+       if (!dequeued_page) {
+               /*
diff --git a/queue-4.4/virtio_balloon-fix-race-by-fill-and-leak.patch b/queue-4.4/virtio_balloon-fix-race-by-fill-and-leak.patch
new file mode 100644 (file)
index 0000000..ea2d028
--- /dev/null
@@ -0,0 +1,42 @@
+From f68b992bbb474641881932c61c92dcfa6f5b3689 Mon Sep 17 00:00:00 2001
+From: Minchan Kim <minchan@kernel.org>
+Date: Mon, 28 Dec 2015 08:35:12 +0900
+Subject: virtio_balloon: fix race by fill and leak
+
+From: Minchan Kim <minchan@kernel.org>
+
+commit f68b992bbb474641881932c61c92dcfa6f5b3689 upstream.
+
+During my compaction-related stuff, I encountered a bug
+with ballooning.
+
+With repeated inflating and deflating cycle, guest memory(
+ie, cat /proc/meminfo | grep MemTotal) is decreased and
+couldn't be recovered.
+
+The reason is balloon_lock doesn't cover release_pages_balloon
+so struct virtio_balloon fields could be overwritten by race
+of fill_balloon(e,g, vb->*pfns could be critical).
+
+This patch fixes it in my test.
+
+Signed-off-by: Minchan Kim <minchan@kernel.org>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/virtio/virtio_balloon.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/virtio/virtio_balloon.c
++++ b/drivers/virtio/virtio_balloon.c
+@@ -209,8 +209,8 @@ static unsigned leak_balloon(struct virt
+        */
+       if (vb->num_pfns != 0)
+               tell_host(vb, vb->deflate_vq);
+-      mutex_unlock(&vb->balloon_lock);
+       release_pages_balloon(vb);
++      mutex_unlock(&vb->balloon_lock);
+       return num_freed_pages;
+ }
diff --git a/queue-4.4/virtio_pci-fix-use-after-free-on-release.patch b/queue-4.4/virtio_pci-fix-use-after-free-on-release.patch
new file mode 100644 (file)
index 0000000..581ea2b
--- /dev/null
@@ -0,0 +1,45 @@
+From 2989be09a8a9d62a785137586ad941f916e08f83 Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst@redhat.com>
+Date: Thu, 14 Jan 2016 16:00:41 +0200
+Subject: virtio_pci: fix use after free on release
+
+From: Michael S. Tsirkin <mst@redhat.com>
+
+commit 2989be09a8a9d62a785137586ad941f916e08f83 upstream.
+
+KASan detected a use-after-free error in virtio-pci remove code. In
+virtio_pci_remove(), vp_dev is still used after being freed in
+unregister_virtio_device() (in virtio_pci_release_dev() more
+precisely).
+
+To fix, keep a reference until cleanup is done.
+
+Fixes: 63bd62a08ca4 ("virtio_pci: defer kfree until release callback")
+Reported-by: Jerome Marchand <jmarchan@redhat.com>
+Cc: Sasha Levin <sasha.levin@oracle.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Tested-by: Jerome Marchand <jmarchan@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/virtio/virtio_pci_common.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/virtio/virtio_pci_common.c
++++ b/drivers/virtio/virtio_pci_common.c
+@@ -545,6 +545,7 @@ err_enable_device:
+ static void virtio_pci_remove(struct pci_dev *pci_dev)
+ {
+       struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
++      struct device *dev = get_device(&vp_dev->vdev.dev);
+       unregister_virtio_device(&vp_dev->vdev);
+@@ -554,6 +555,7 @@ static void virtio_pci_remove(struct pci
+               virtio_pci_modern_remove(vp_dev);
+       pci_disable_device(pci_dev);
++      put_device(dev);
+ }
+ static struct pci_driver virtio_pci_driver = {