--- /dev/null
+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);
--- /dev/null
+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);
--- /dev/null
+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 */
--- /dev/null
+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");
--- /dev/null
+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");
--- /dev/null
+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;
+ }
--- /dev/null
+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;
--- /dev/null
+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;
--- /dev/null
+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;
+
--- /dev/null
+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)
--- /dev/null
+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,
--- /dev/null
+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 {
--- /dev/null
+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,
--- /dev/null
+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
--- /dev/null
+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");
--- /dev/null
+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;
--- /dev/null
+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)) {
--- /dev/null
+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},
--- /dev/null
+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;
--- /dev/null
+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;
--- /dev/null
+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;
--- /dev/null
+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;
--- /dev/null
+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;
+ }
+
--- /dev/null
+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)
--- /dev/null
+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;
+ }
+
+ /*
--- /dev/null
+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) {
--- /dev/null
+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;
--- /dev/null
+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);
+ }
+
--- /dev/null
+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;
--- /dev/null
+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
--- /dev/null
+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);
+
--- /dev/null
+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);
+ }
+
--- /dev/null
+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
--- /dev/null
+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;
+
--- /dev/null
+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);
--- /dev/null
+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");
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
--- /dev/null
+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) {
+ /*
--- /dev/null
+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;
+ }
+
--- /dev/null
+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 = {