From 0017b83cdafc3837cd13ad14472ebcb03d0aeabe Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 1 Mar 2016 11:49:51 -0800 Subject: [PATCH] 4.4-stable patches added patches: drm-add-drm_fixp_from_fraction-and-drm_fixp2int_ceil.patch drm-amdgpu-call-hpd_irq_event-on-resume.patch drm-amdgpu-don-t-hang-in-amdgpu_flip_work_func-on-disabled-crtc.patch drm-amdgpu-don-t-load-mec2-on-topaz.patch drm-amdgpu-drop-topaz-support-from-gmc8-module.patch drm-amdgpu-fix-amdgpu_bo_pin_restricted-vram-placing-v2.patch drm-amdgpu-fix-issue-with-overlapping-userptrs.patch drm-amdgpu-fix-lost-sync_to-if-scheduler-is-enabled.patch drm-amdgpu-fix-off-by-one-errors-in-amdgpu_vm_bo_map.patch drm-amdgpu-fix-s4-resume.patch drm-amdgpu-fix-tonga-smu-resume.patch drm-amdgpu-hold-reference-to-fences-in-amdgpu_sa_bo_new-v2.patch drm-amdgpu-iceland-use-ci-based-mc-ip.patch drm-amdgpu-move-gmc7-support-out-of-cik-dependency.patch drm-amdgpu-no-need-to-load-mc-firmware-on-fiji.patch drm-amdgpu-pm-adjust-display-configuration-after-powerstate.patch drm-amdgpu-pull-topaz-gmc-bits-into-gmc_v7.patch drm-amdgpu-remove-exp-hardware-support-from-iceland.patch drm-amdgpu-remove-unnecessary-forward-declaration.patch drm-amdgpu-the-vi-specific-exe-bit-should-only-apply-to-gmc-v8.0-above.patch drm-amdgpu-use-post-decrement-in-error-handling.patch drm-dp-mst-always-send-reply-for-up-request.patch drm-dp-mst-calculate-mst-pbn-with-31.32-fixed-point.patch drm-dp-mst-deallocate-payload-on-port-destruction.patch drm-dp-mst-fix-in-mstb-rad-initialization.patch drm-dp-mst-fix-in-rad-element-access.patch drm-dp-mst-move-guid-storage-from-mgr-port-to-only-mst-branch.patch drm-dp-mst-process-broadcast-messages-correctly.patch drm-dp-mst-reverse-order-of-mst-enable-and-clearing-vc-payload-table.patch drm-nouveau-disp-dp-ensure-sink-is-powered-up-before-attempting-link-training.patch drm-nouveau-display-enable-vblank-irqs-after-display-engine-is-on-again.patch drm-nouveau-kms-take-mode_config-mutex-in-connector-hotplug-path.patch drm-nouveau-platform-fix-deferred-probe.patch drm-vmwgfx-fix-a-width-pitch-mismatch-on-framebuffer-updates.patch drm-vmwgfx-fix-an-incorrect-lock-check.patch drm-vmwgfx-respect-nomodeset.patch virtio_balloon-fix-race-between-migration-and-ballooning.patch virtio_balloon-fix-race-by-fill-and-leak.patch virtio_pci-fix-use-after-free-on-release.patch --- ..._from_fraction-and-drm_fixp2int_ceil.patch | 106 ++++++++ ...-amdgpu-call-hpd_irq_event-on-resume.patch | 29 +++ ...dgpu_flip_work_func-on-disabled-crtc.patch | 111 ++++++++ .../drm-amdgpu-don-t-load-mec2-on-topaz.patch | 79 ++++++ ...-drop-topaz-support-from-gmc8-module.patch | 88 +++++++ ...pu_bo_pin_restricted-vram-placing-v2.patch | 38 +++ ...-fix-issue-with-overlapping-userptrs.patch | 76 ++++++ ...lost-sync_to-if-scheduler-is-enabled.patch | 43 +++ ...ff-by-one-errors-in-amdgpu_vm_bo_map.patch | 63 +++++ queue-4.4/drm-amdgpu-fix-s4-resume.patch | 47 ++++ .../drm-amdgpu-fix-tonga-smu-resume.patch | 55 ++++ ...nce-to-fences-in-amdgpu_sa_bo_new-v2.patch | 51 ++++ ...rm-amdgpu-iceland-use-ci-based-mc-ip.patch | 78 ++++++ ...e-gmc7-support-out-of-cik-dependency.patch | 42 +++ ...-no-need-to-load-mc-firmware-on-fiji.patch | 48 ++++ ...splay-configuration-after-powerstate.patch | 49 ++++ ...dgpu-pull-topaz-gmc-bits-into-gmc_v7.patch | 82 ++++++ ...ve-exp-hardware-support-from-iceland.patch | 45 ++++ ...move-unnecessary-forward-declaration.patch | 32 +++ ...-should-only-apply-to-gmc-v8.0-above.patch | 32 +++ ...use-post-decrement-in-error-handling.patch | 36 +++ ...mst-always-send-reply-for-up-request.patch | 96 +++++++ ...ulate-mst-pbn-with-31.32-fixed-point.patch | 110 ++++++++ ...allocate-payload-on-port-destruction.patch | 195 ++++++++++++++ ...p-mst-fix-in-mstb-rad-initialization.patch | 48 ++++ ...drm-dp-mst-fix-in-rad-element-access.patch | 41 +++ ...age-from-mgr-port-to-only-mst-branch.patch | 244 ++++++++++++++++++ ...process-broadcast-messages-correctly.patch | 163 ++++++++++++ ...enable-and-clearing-vc-payload-table.patch | 50 ++++ ...d-up-before-attempting-link-training.patch | 62 +++++ ...rqs-after-display-engine-is-on-again.patch | 60 +++++ ...nfig-mutex-in-connector-hotplug-path.patch | 34 +++ ...-nouveau-platform-fix-deferred-probe.patch | 108 ++++++++ ...itch-mismatch-on-framebuffer-updates.patch | 65 +++++ ...m-vmwgfx-fix-an-incorrect-lock-check.patch | 34 +++ queue-4.4/drm-vmwgfx-respect-nomodeset.patch | 41 +++ queue-4.4/series | 39 +++ ...ace-between-migration-and-ballooning.patch | 91 +++++++ ...io_balloon-fix-race-by-fill-and-leak.patch | 42 +++ ...io_pci-fix-use-after-free-on-release.patch | 45 ++++ 40 files changed, 2798 insertions(+) create mode 100644 queue-4.4/drm-add-drm_fixp_from_fraction-and-drm_fixp2int_ceil.patch create mode 100644 queue-4.4/drm-amdgpu-call-hpd_irq_event-on-resume.patch create mode 100644 queue-4.4/drm-amdgpu-don-t-hang-in-amdgpu_flip_work_func-on-disabled-crtc.patch create mode 100644 queue-4.4/drm-amdgpu-don-t-load-mec2-on-topaz.patch create mode 100644 queue-4.4/drm-amdgpu-drop-topaz-support-from-gmc8-module.patch create mode 100644 queue-4.4/drm-amdgpu-fix-amdgpu_bo_pin_restricted-vram-placing-v2.patch create mode 100644 queue-4.4/drm-amdgpu-fix-issue-with-overlapping-userptrs.patch create mode 100644 queue-4.4/drm-amdgpu-fix-lost-sync_to-if-scheduler-is-enabled.patch create mode 100644 queue-4.4/drm-amdgpu-fix-off-by-one-errors-in-amdgpu_vm_bo_map.patch create mode 100644 queue-4.4/drm-amdgpu-fix-s4-resume.patch create mode 100644 queue-4.4/drm-amdgpu-fix-tonga-smu-resume.patch create mode 100644 queue-4.4/drm-amdgpu-hold-reference-to-fences-in-amdgpu_sa_bo_new-v2.patch create mode 100644 queue-4.4/drm-amdgpu-iceland-use-ci-based-mc-ip.patch create mode 100644 queue-4.4/drm-amdgpu-move-gmc7-support-out-of-cik-dependency.patch create mode 100644 queue-4.4/drm-amdgpu-no-need-to-load-mc-firmware-on-fiji.patch create mode 100644 queue-4.4/drm-amdgpu-pm-adjust-display-configuration-after-powerstate.patch create mode 100644 queue-4.4/drm-amdgpu-pull-topaz-gmc-bits-into-gmc_v7.patch create mode 100644 queue-4.4/drm-amdgpu-remove-exp-hardware-support-from-iceland.patch create mode 100644 queue-4.4/drm-amdgpu-remove-unnecessary-forward-declaration.patch create mode 100644 queue-4.4/drm-amdgpu-the-vi-specific-exe-bit-should-only-apply-to-gmc-v8.0-above.patch create mode 100644 queue-4.4/drm-amdgpu-use-post-decrement-in-error-handling.patch create mode 100644 queue-4.4/drm-dp-mst-always-send-reply-for-up-request.patch create mode 100644 queue-4.4/drm-dp-mst-calculate-mst-pbn-with-31.32-fixed-point.patch create mode 100644 queue-4.4/drm-dp-mst-deallocate-payload-on-port-destruction.patch create mode 100644 queue-4.4/drm-dp-mst-fix-in-mstb-rad-initialization.patch create mode 100644 queue-4.4/drm-dp-mst-fix-in-rad-element-access.patch create mode 100644 queue-4.4/drm-dp-mst-move-guid-storage-from-mgr-port-to-only-mst-branch.patch create mode 100644 queue-4.4/drm-dp-mst-process-broadcast-messages-correctly.patch create mode 100644 queue-4.4/drm-dp-mst-reverse-order-of-mst-enable-and-clearing-vc-payload-table.patch create mode 100644 queue-4.4/drm-nouveau-disp-dp-ensure-sink-is-powered-up-before-attempting-link-training.patch create mode 100644 queue-4.4/drm-nouveau-display-enable-vblank-irqs-after-display-engine-is-on-again.patch create mode 100644 queue-4.4/drm-nouveau-kms-take-mode_config-mutex-in-connector-hotplug-path.patch create mode 100644 queue-4.4/drm-nouveau-platform-fix-deferred-probe.patch create mode 100644 queue-4.4/drm-vmwgfx-fix-a-width-pitch-mismatch-on-framebuffer-updates.patch create mode 100644 queue-4.4/drm-vmwgfx-fix-an-incorrect-lock-check.patch create mode 100644 queue-4.4/drm-vmwgfx-respect-nomodeset.patch create mode 100644 queue-4.4/virtio_balloon-fix-race-between-migration-and-ballooning.patch create mode 100644 queue-4.4/virtio_balloon-fix-race-by-fill-and-leak.patch create mode 100644 queue-4.4/virtio_pci-fix-use-after-free-on-release.patch diff --git a/queue-4.4/drm-add-drm_fixp_from_fraction-and-drm_fixp2int_ceil.patch b/queue-4.4/drm-add-drm_fixp_from_fraction-and-drm_fixp2int_ceil.patch new file mode 100644 index 00000000000..6607851a12b --- /dev/null +++ b/queue-4.4/drm-add-drm_fixp_from_fraction-and-drm_fixp2int_ceil.patch @@ -0,0 +1,106 @@ +From 64566b5e767f9bc3161055ca1b443a51afb52aad Mon Sep 17 00:00:00 2001 +From: Harry Wentland +Date: Fri, 22 Jan 2016 17:07:25 -0500 +Subject: drm: Add drm_fixp_from_fraction and drm_fixp2int_ceil + +From: Harry Wentland + +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 +Signed-off-by: Harry Wentland +Reviewed-by: Alex Deucher +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + include/drm/drm_fixed.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 51 insertions(+), 2 deletions(-) + +--- a/include/drm/drm_fixed.h ++++ b/include/drm/drm_fixed.h +@@ -73,18 +73,28 @@ static inline u32 dfixed_div(fixed20_12 + #define DRM_FIXED_ONE (1ULL << DRM_FIXED_POINT) + #define DRM_FIXED_DECIMAL_MASK (DRM_FIXED_ONE - 1) + #define DRM_FIXED_DIGITS_MASK (~DRM_FIXED_DECIMAL_MASK) ++#define DRM_FIXED_EPSILON 1LL ++#define DRM_FIXED_ALMOST_ONE (DRM_FIXED_ONE - DRM_FIXED_EPSILON) + + static inline s64 drm_int2fixp(int a) + { + return ((s64)a) << DRM_FIXED_POINT; + } + +-static inline int drm_fixp2int(int64_t a) ++static inline int drm_fixp2int(s64 a) + { + return ((s64)a) >> DRM_FIXED_POINT; + } + +-static inline unsigned drm_fixp_msbset(int64_t a) ++static inline int drm_fixp2int_ceil(s64 a) ++{ ++ if (a > 0) ++ return drm_fixp2int(a + DRM_FIXED_ALMOST_ONE); ++ else ++ return drm_fixp2int(a - DRM_FIXED_ALMOST_ONE); ++} ++ ++static inline unsigned drm_fixp_msbset(s64 a) + { + unsigned shift, sign = (a >> 63) & 1; + +@@ -136,6 +146,45 @@ static inline s64 drm_fixp_div(s64 a, s6 + return result; + } + ++static inline s64 drm_fixp_from_fraction(s64 a, s64 b) ++{ ++ s64 res; ++ bool a_neg = a < 0; ++ bool b_neg = b < 0; ++ u64 a_abs = a_neg ? -a : a; ++ u64 b_abs = b_neg ? -b : b; ++ u64 rem; ++ ++ /* determine integer part */ ++ u64 res_abs = div64_u64_rem(a_abs, b_abs, &rem); ++ ++ /* determine fractional part */ ++ { ++ u32 i = DRM_FIXED_POINT; ++ ++ do { ++ rem <<= 1; ++ res_abs <<= 1; ++ if (rem >= b_abs) { ++ res_abs |= 1; ++ rem -= b_abs; ++ } ++ } while (--i != 0); ++ } ++ ++ /* round up LSB */ ++ { ++ u64 summand = (rem << 1) >= b_abs; ++ ++ res_abs += summand; ++ } ++ ++ res = (s64) res_abs; ++ if (a_neg ^ b_neg) ++ res = -res; ++ return res; ++} ++ + static inline s64 drm_fixp_exp(s64 x) + { + s64 tolerance = div64_s64(DRM_FIXED_ONE, 1000000); diff --git a/queue-4.4/drm-amdgpu-call-hpd_irq_event-on-resume.patch b/queue-4.4/drm-amdgpu-call-hpd_irq_event-on-resume.patch new file mode 100644 index 00000000000..5fcc9c4877c --- /dev/null +++ b/queue-4.4/drm-amdgpu-call-hpd_irq_event-on-resume.patch @@ -0,0 +1,29 @@ +From 54fb2a5cd0baf8e97d743de411e2f832d1afa68d Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Tue, 24 Nov 2015 14:30:56 -0500 +Subject: drm/amdgpu: call hpd_irq_event on resume + +From: Alex Deucher + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -1788,6 +1788,7 @@ int amdgpu_resume_kms(struct drm_device + } + + drm_kms_helper_poll_enable(dev); ++ drm_helper_hpd_irq_event(dev); + + if (fbcon) { + amdgpu_fbdev_set_suspend(adev, 0); diff --git a/queue-4.4/drm-amdgpu-don-t-hang-in-amdgpu_flip_work_func-on-disabled-crtc.patch b/queue-4.4/drm-amdgpu-don-t-hang-in-amdgpu_flip_work_func-on-disabled-crtc.patch new file mode 100644 index 00000000000..33da403ae89 --- /dev/null +++ b/queue-4.4/drm-amdgpu-don-t-hang-in-amdgpu_flip_work_func-on-disabled-crtc.patch @@ -0,0 +1,111 @@ +From e1d09dc0ccc6c91e3916476f636edb76da1f65bb Mon Sep 17 00:00:00 2001 +From: Mario Kleiner +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 + +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 + + + +Reported-by: Bernd Steinhauser +Signed-off-by: Mario Kleiner +Signed-off-by: Greg Kroah-Hartman + +Cc: Michel Dänzer +Cc: Alex Deucher +Reviewed-by: Michel Dänzer +Signed-off-by: Alex Deucher + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +@@ -72,8 +72,8 @@ static void amdgpu_flip_work_func(struct + + struct drm_crtc *crtc = &amdgpuCrtc->base; + unsigned long flags; +- unsigned i; +- int vpos, hpos, stat, min_udelay; ++ unsigned i, repcnt = 4; ++ int vpos, hpos, stat, min_udelay = 0; + struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id]; + + amdgpu_flip_wait_fence(adev, &work->excl); +@@ -96,7 +96,7 @@ static void amdgpu_flip_work_func(struct + * In practice this won't execute very often unless on very fast + * machines because the time window for this to happen is very small. + */ +- for (;;) { ++ while (amdgpuCrtc->enabled && repcnt--) { + /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank + * start in hpos, and to the "fudged earlier" vblank start in + * vpos. +@@ -114,10 +114,22 @@ static void amdgpu_flip_work_func(struct + /* Sleep at least until estimated real start of hw vblank */ + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5); ++ if (min_udelay > vblank->framedur_ns / 2000) { ++ /* Don't wait ridiculously long - something is wrong */ ++ repcnt = 0; ++ break; ++ } + usleep_range(min_udelay, 2 * min_udelay); + spin_lock_irqsave(&crtc->dev->event_lock, flags); + }; + ++ if (!repcnt) ++ DRM_DEBUG_DRIVER("Delay problem on crtc %d: min_udelay %d, " ++ "framedur %d, linedur %d, stat %d, vpos %d, " ++ "hpos %d\n", work->crtc_id, min_udelay, ++ vblank->framedur_ns / 1000, ++ vblank->linedur_ns / 1000, stat, vpos, hpos); ++ + /* do the flip (mmio) */ + adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base); + /* set the flip status */ diff --git a/queue-4.4/drm-amdgpu-don-t-load-mec2-on-topaz.patch b/queue-4.4/drm-amdgpu-don-t-load-mec2-on-topaz.patch new file mode 100644 index 00000000000..c4a117ca06b --- /dev/null +++ b/queue-4.4/drm-amdgpu-don-t-load-mec2-on-topaz.patch @@ -0,0 +1,79 @@ +From 97dde76a30c2e67fa5fb9cb6a4072c0178c9df26 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +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 + +commit 97dde76a30c2e67fa5fb9cb6a4072c0178c9df26 upstream. + +Not validated. + +Reviewed-by: Ken Wang +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 4 ++-- + drivers/gpu/drm/amd/amdgpu/iceland_smc.c | 12 +++--------- + 2 files changed, 5 insertions(+), 11 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +@@ -90,7 +90,6 @@ MODULE_FIRMWARE("amdgpu/topaz_ce.bin"); + MODULE_FIRMWARE("amdgpu/topaz_pfp.bin"); + MODULE_FIRMWARE("amdgpu/topaz_me.bin"); + MODULE_FIRMWARE("amdgpu/topaz_mec.bin"); +-MODULE_FIRMWARE("amdgpu/topaz_mec2.bin"); + MODULE_FIRMWARE("amdgpu/topaz_rlc.bin"); + + MODULE_FIRMWARE("amdgpu/fiji_ce.bin"); +@@ -807,7 +806,8 @@ static int gfx_v8_0_init_microcode(struc + adev->gfx.mec_fw_version = le32_to_cpu(cp_hdr->header.ucode_version); + adev->gfx.mec_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version); + +- if (adev->asic_type != CHIP_STONEY) { ++ if ((adev->asic_type != CHIP_STONEY) && ++ (adev->asic_type != CHIP_TOPAZ)) { + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name); + err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev); + if (!err) { +--- a/drivers/gpu/drm/amd/amdgpu/iceland_smc.c ++++ b/drivers/gpu/drm/amd/amdgpu/iceland_smc.c +@@ -432,7 +432,7 @@ static uint32_t iceland_smu_get_mask_for + case AMDGPU_UCODE_ID_CP_ME: + return UCODE_ID_CP_ME_MASK; + case AMDGPU_UCODE_ID_CP_MEC1: +- return UCODE_ID_CP_MEC_MASK | UCODE_ID_CP_MEC_JT1_MASK | UCODE_ID_CP_MEC_JT2_MASK; ++ return UCODE_ID_CP_MEC_MASK | UCODE_ID_CP_MEC_JT1_MASK; + case AMDGPU_UCODE_ID_CP_MEC2: + return UCODE_ID_CP_MEC_MASK; + case AMDGPU_UCODE_ID_RLC_G: +@@ -522,12 +522,6 @@ static int iceland_smu_request_load_fw(s + return -EINVAL; + } + +- if (iceland_smu_populate_single_firmware_entry(adev, UCODE_ID_CP_MEC_JT2, +- &toc->entry[toc->num_entries++])) { +- DRM_ERROR("Failed to get firmware entry for MEC_JT2\n"); +- return -EINVAL; +- } +- + if (iceland_smu_populate_single_firmware_entry(adev, UCODE_ID_SDMA0, + &toc->entry[toc->num_entries++])) { + DRM_ERROR("Failed to get firmware entry for SDMA0\n"); +@@ -550,8 +544,8 @@ static int iceland_smu_request_load_fw(s + UCODE_ID_CP_ME_MASK | + UCODE_ID_CP_PFP_MASK | + UCODE_ID_CP_MEC_MASK | +- UCODE_ID_CP_MEC_JT1_MASK | +- UCODE_ID_CP_MEC_JT2_MASK; ++ UCODE_ID_CP_MEC_JT1_MASK; ++ + + if (iceland_send_msg_to_smc_with_parameter_without_waiting(adev, PPSMC_MSG_LoadUcodes, fw_to_load)) { + DRM_ERROR("Fail to request SMU load ucode\n"); diff --git a/queue-4.4/drm-amdgpu-drop-topaz-support-from-gmc8-module.patch b/queue-4.4/drm-amdgpu-drop-topaz-support-from-gmc8-module.patch new file mode 100644 index 00000000000..81f55879a27 --- /dev/null +++ b/queue-4.4/drm-amdgpu-drop-topaz-support-from-gmc8-module.patch @@ -0,0 +1,88 @@ +From 8878d8548ac7fae43cd6d82579f966eb8825e282 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +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 + +commit 8878d8548ac7fae43cd6d82579f966eb8825e282 upstream. + +topaz is actually gmc7. + +Reviewed-by: Ken Wang +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 28 +--------------------------- + 1 file changed, 1 insertion(+), 27 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +@@ -42,7 +42,6 @@ + static void gmc_v8_0_set_gart_funcs(struct amdgpu_device *adev); + static void gmc_v8_0_set_irq_funcs(struct amdgpu_device *adev); + +-MODULE_FIRMWARE("amdgpu/topaz_mc.bin"); + MODULE_FIRMWARE("amdgpu/tonga_mc.bin"); + + static const u32 golden_settings_tonga_a11[] = +@@ -74,19 +73,6 @@ static const u32 fiji_mgcg_cgcg_init[] = + mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104 + }; + +-static const u32 golden_settings_iceland_a11[] = +-{ +- mmVM_PRT_APERTURE0_LOW_ADDR, 0x0fffffff, 0x0fffffff, +- mmVM_PRT_APERTURE1_LOW_ADDR, 0x0fffffff, 0x0fffffff, +- mmVM_PRT_APERTURE2_LOW_ADDR, 0x0fffffff, 0x0fffffff, +- mmVM_PRT_APERTURE3_LOW_ADDR, 0x0fffffff, 0x0fffffff +-}; +- +-static const u32 iceland_mgcg_cgcg_init[] = +-{ +- mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104 +-}; +- + static const u32 cz_mgcg_cgcg_init[] = + { + mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104 +@@ -101,14 +87,6 @@ static const u32 stoney_mgcg_cgcg_init[] + static void gmc_v8_0_init_golden_registers(struct amdgpu_device *adev) + { + switch (adev->asic_type) { +- case CHIP_TOPAZ: +- amdgpu_program_register_sequence(adev, +- iceland_mgcg_cgcg_init, +- (const u32)ARRAY_SIZE(iceland_mgcg_cgcg_init)); +- amdgpu_program_register_sequence(adev, +- golden_settings_iceland_a11, +- (const u32)ARRAY_SIZE(golden_settings_iceland_a11)); +- break; + case CHIP_FIJI: + amdgpu_program_register_sequence(adev, + fiji_mgcg_cgcg_init, +@@ -228,9 +206,6 @@ static int gmc_v8_0_init_microcode(struc + DRM_DEBUG("\n"); + + switch (adev->asic_type) { +- case CHIP_TOPAZ: +- chip_name = "topaz"; +- break; + case CHIP_TONGA: + chip_name = "tonga"; + break; +@@ -1000,8 +975,7 @@ static int gmc_v8_0_hw_init(void *handle + + gmc_v8_0_mc_program(adev); + +- if ((adev->asic_type == CHIP_TOPAZ) || +- (adev->asic_type == CHIP_TONGA)) { ++ if (adev->asic_type == CHIP_TONGA) { + r = gmc_v8_0_mc_load_microcode(adev); + if (r) { + DRM_ERROR("Failed to load MC firmware!\n"); diff --git a/queue-4.4/drm-amdgpu-fix-amdgpu_bo_pin_restricted-vram-placing-v2.patch b/queue-4.4/drm-amdgpu-fix-amdgpu_bo_pin_restricted-vram-placing-v2.patch new file mode 100644 index 00000000000..e4b4d879368 --- /dev/null +++ b/queue-4.4/drm-amdgpu-fix-amdgpu_bo_pin_restricted-vram-placing-v2.patch @@ -0,0 +1,38 @@ +From 78d0e182b6c1f5336f6e8cbb197f403276dabc7f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20K=C3=B6nig?= +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 + +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 +Reviewed-by: Alex Deucher (v1) +Reviewed-by: Rex Zhu (v1) +Reviewed-by: Michel Dänzer +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +@@ -399,7 +399,8 @@ int amdgpu_bo_pin_restricted(struct amdg + } + if (fpfn > bo->placements[i].fpfn) + bo->placements[i].fpfn = fpfn; +- if (lpfn && lpfn < bo->placements[i].lpfn) ++ if (!bo->placements[i].lpfn || ++ (lpfn && lpfn < bo->placements[i].lpfn)) + bo->placements[i].lpfn = lpfn; + bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; + } diff --git a/queue-4.4/drm-amdgpu-fix-issue-with-overlapping-userptrs.patch b/queue-4.4/drm-amdgpu-fix-issue-with-overlapping-userptrs.patch new file mode 100644 index 00000000000..3b398bc9dd9 --- /dev/null +++ b/queue-4.4/drm-amdgpu-fix-issue-with-overlapping-userptrs.patch @@ -0,0 +1,76 @@ +From cc1de6e800c253172334f8774c419dc64401cd2e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20K=C3=B6nig?= +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 + +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 +Acked-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++ + drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c | 3 ++- + drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 19 +++++++++++++++++++ + 3 files changed, 23 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +@@ -2312,6 +2312,8 @@ bool amdgpu_ttm_bo_is_amdgpu_bo(struct t + int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, + uint32_t flags); + bool amdgpu_ttm_tt_has_userptr(struct ttm_tt *ttm); ++bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, ++ unsigned long end); + bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm); + uint32_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, + struct ttm_mem_reg *mem); +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c +@@ -142,7 +142,8 @@ static void amdgpu_mn_invalidate_range_s + + list_for_each_entry(bo, &node->bos, mn_list) { + +- if (!bo->tbo.ttm || bo->tbo.ttm->state != tt_bound) ++ if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start, ++ end)) + continue; + + r = amdgpu_bo_reserve(bo, true); +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +@@ -783,6 +783,25 @@ bool amdgpu_ttm_tt_has_userptr(struct tt + return !!gtt->userptr; + } + ++bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, ++ unsigned long end) ++{ ++ struct amdgpu_ttm_tt *gtt = (void *)ttm; ++ unsigned long size; ++ ++ if (gtt == NULL) ++ return false; ++ ++ if (gtt->ttm.ttm.state != tt_bound || !gtt->userptr) ++ return false; ++ ++ size = (unsigned long)gtt->ttm.ttm.num_pages * PAGE_SIZE; ++ if (gtt->userptr > end || gtt->userptr + size <= start) ++ return false; ++ ++ return true; ++} ++ + bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm) + { + struct amdgpu_ttm_tt *gtt = (void *)ttm; diff --git a/queue-4.4/drm-amdgpu-fix-lost-sync_to-if-scheduler-is-enabled.patch b/queue-4.4/drm-amdgpu-fix-lost-sync_to-if-scheduler-is-enabled.patch new file mode 100644 index 00000000000..6153d91e8a7 --- /dev/null +++ b/queue-4.4/drm-amdgpu-fix-lost-sync_to-if-scheduler-is-enabled.patch @@ -0,0 +1,43 @@ +From 888c9e33e4c5a503285921046c621f7c73199d2f Mon Sep 17 00:00:00 2001 +From: Chunming Zhou +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 + +commit 888c9e33e4c5a503285921046c621f7c73199d2f upstream. + +when scheduler is enabled, the semaphore isn't used at all. + +Signed-off-by: Chunming Zhou +Reviewed-by: Christian König +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c +@@ -293,7 +293,8 @@ int amdgpu_sync_rings(struct amdgpu_sync + fence = to_amdgpu_fence(sync->sync_to[i]); + + /* check if we really need to sync */ +- if (!amdgpu_fence_need_sync(fence, ring)) ++ if (!amdgpu_enable_scheduler && ++ !amdgpu_fence_need_sync(fence, ring)) + continue; + + /* prevent GPU deadlocks */ +@@ -303,7 +304,7 @@ int amdgpu_sync_rings(struct amdgpu_sync + } + + if (amdgpu_enable_scheduler || !amdgpu_enable_semaphores) { +- r = fence_wait(&fence->base, true); ++ r = fence_wait(sync->sync_to[i], true); + if (r) + return r; + continue; diff --git a/queue-4.4/drm-amdgpu-fix-off-by-one-errors-in-amdgpu_vm_bo_map.patch b/queue-4.4/drm-amdgpu-fix-off-by-one-errors-in-amdgpu_vm_bo_map.patch new file mode 100644 index 00000000000..e81b3703728 --- /dev/null +++ b/queue-4.4/drm-amdgpu-fix-off-by-one-errors-in-amdgpu_vm_bo_map.patch @@ -0,0 +1,63 @@ +From 005ae95e6ec119c64e2d16eb65a94c49e1dcf9f0 Mon Sep 17 00:00:00 2001 +From: Felix Kuehling +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 + +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 +Reviewed-by: Christian König +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +@@ -1010,13 +1010,13 @@ int amdgpu_vm_bo_map(struct amdgpu_devic + return -EINVAL; + + /* make sure object fit at this offset */ +- eaddr = saddr + size; ++ eaddr = saddr + size - 1; + if ((saddr >= eaddr) || (offset + size > amdgpu_bo_size(bo_va->bo))) + return -EINVAL; + + last_pfn = eaddr / AMDGPU_GPU_PAGE_SIZE; +- if (last_pfn > adev->vm_manager.max_pfn) { +- dev_err(adev->dev, "va above limit (0x%08X > 0x%08X)\n", ++ if (last_pfn >= adev->vm_manager.max_pfn) { ++ dev_err(adev->dev, "va above limit (0x%08X >= 0x%08X)\n", + last_pfn, adev->vm_manager.max_pfn); + return -EINVAL; + } +@@ -1025,7 +1025,7 @@ int amdgpu_vm_bo_map(struct amdgpu_devic + eaddr /= AMDGPU_GPU_PAGE_SIZE; + + spin_lock(&vm->it_lock); +- it = interval_tree_iter_first(&vm->va, saddr, eaddr - 1); ++ it = interval_tree_iter_first(&vm->va, saddr, eaddr); + spin_unlock(&vm->it_lock); + if (it) { + struct amdgpu_bo_va_mapping *tmp; +@@ -1046,7 +1046,7 @@ int amdgpu_vm_bo_map(struct amdgpu_devic + + INIT_LIST_HEAD(&mapping->list); + mapping->it.start = saddr; +- mapping->it.last = eaddr - 1; ++ mapping->it.last = eaddr; + mapping->offset = offset; + mapping->flags = flags; + diff --git a/queue-4.4/drm-amdgpu-fix-s4-resume.patch b/queue-4.4/drm-amdgpu-fix-s4-resume.patch new file mode 100644 index 00000000000..88e9c7a91a4 --- /dev/null +++ b/queue-4.4/drm-amdgpu-fix-s4-resume.patch @@ -0,0 +1,47 @@ +From ca19852884c8937eed89560f924f5a34cfcc22af Mon Sep 17 00:00:00 2001 +From: Flora Cui +Date: Thu, 4 Feb 2016 15:10:08 +0800 +Subject: drm/amdgpu: fix s4 resume + +From: Flora Cui + +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 +Reviewed-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -1744,15 +1744,20 @@ int amdgpu_resume_kms(struct drm_device + } + + /* post card */ +- amdgpu_atom_asic_init(adev->mode_info.atom_context); ++ if (!amdgpu_card_posted(adev)) ++ amdgpu_atom_asic_init(adev->mode_info.atom_context); + + r = amdgpu_resume(adev); ++ if (r) ++ DRM_ERROR("amdgpu_resume failed (%d).\n", r); + + amdgpu_fence_driver_resume(adev); + +- r = amdgpu_ib_ring_tests(adev); +- if (r) +- DRM_ERROR("ib ring test failed (%d).\n", r); ++ if (resume) { ++ r = amdgpu_ib_ring_tests(adev); ++ if (r) ++ DRM_ERROR("ib ring test failed (%d).\n", r); ++ } + + r = amdgpu_late_init(adev); + if (r) diff --git a/queue-4.4/drm-amdgpu-fix-tonga-smu-resume.patch b/queue-4.4/drm-amdgpu-fix-tonga-smu-resume.patch new file mode 100644 index 00000000000..b23d6dd9344 --- /dev/null +++ b/queue-4.4/drm-amdgpu-fix-tonga-smu-resume.patch @@ -0,0 +1,55 @@ +From e160e4db833c7e8587ec3c88efaed0d84f1bcf42 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +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 + +commit e160e4db833c7e8587ec3c88efaed0d84f1bcf42 upstream. + +Need to make sure smu buffers are pinned on resume. This +matches what Fiji does. + +Reviewed-by: Junwei Zhang +Reviewed-by: Christian König +Reviewed-by: Ken Wang +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/tonga_dpm.c | 17 ++--------------- + 1 file changed, 2 insertions(+), 15 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c ++++ b/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c +@@ -122,25 +122,12 @@ static int tonga_dpm_hw_fini(void *handl + + static int tonga_dpm_suspend(void *handle) + { +- return 0; ++ return tonga_dpm_hw_fini(handle); + } + + static int tonga_dpm_resume(void *handle) + { +- int ret; +- struct amdgpu_device *adev = (struct amdgpu_device *)handle; +- +- mutex_lock(&adev->pm.mutex); +- +- ret = tonga_smu_start(adev); +- if (ret) { +- DRM_ERROR("SMU start failed\n"); +- goto fail; +- } +- +-fail: +- mutex_unlock(&adev->pm.mutex); +- return ret; ++ return tonga_dpm_hw_init(handle); + } + + static int tonga_dpm_set_clockgating_state(void *handle, diff --git a/queue-4.4/drm-amdgpu-hold-reference-to-fences-in-amdgpu_sa_bo_new-v2.patch b/queue-4.4/drm-amdgpu-hold-reference-to-fences-in-amdgpu_sa_bo_new-v2.patch new file mode 100644 index 00000000000..a1e1c9024cf --- /dev/null +++ b/queue-4.4/drm-amdgpu-hold-reference-to-fences-in-amdgpu_sa_bo_new-v2.patch @@ -0,0 +1,51 @@ +From a8d81b36267366603771431747438d18f32ae2d5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Nicolai=20H=C3=A4hnle?= +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 + +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 +Reviewed-by: Alex Deucher +Reviewed-by: Christian König +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c +@@ -354,12 +354,15 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_ma + + for (i = 0, count = 0; i < AMDGPU_MAX_RINGS; ++i) + if (fences[i]) +- fences[count++] = fences[i]; ++ fences[count++] = fence_get(fences[i]); + + if (count) { + spin_unlock(&sa_manager->wq.lock); + t = fence_wait_any_timeout(fences, count, false, + MAX_SCHEDULE_TIMEOUT); ++ for (i = 0; i < count; ++i) ++ fence_put(fences[i]); ++ + r = (t > 0) ? 0 : t; + spin_lock(&sa_manager->wq.lock); + } else { diff --git a/queue-4.4/drm-amdgpu-iceland-use-ci-based-mc-ip.patch b/queue-4.4/drm-amdgpu-iceland-use-ci-based-mc-ip.patch new file mode 100644 index 00000000000..27184323147 --- /dev/null +++ b/queue-4.4/drm-amdgpu-iceland-use-ci-based-mc-ip.patch @@ -0,0 +1,78 @@ +From 429c45deae6e57f1bb91bfb05b671063fb0cef60 Mon Sep 17 00:00:00 2001 +From: Ken Wang +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 + +commit 429c45deae6e57f1bb91bfb05b671063fb0cef60 upstream. + +Reviewed-by: Christian König +Reviewed-by: Alex Deucher +Signed-off-by: Ken Wang +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 10 +++++++++- + drivers/gpu/drm/amd/amdgpu/vi.c | 7 ++++--- + 2 files changed, 13 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +@@ -42,6 +42,7 @@ static void gmc_v7_0_set_irq_funcs(struc + + MODULE_FIRMWARE("radeon/bonaire_mc.bin"); + MODULE_FIRMWARE("radeon/hawaii_mc.bin"); ++MODULE_FIRMWARE("amdgpu/topaz_mc.bin"); + + /** + * gmc8_mc_wait_for_idle - wait for MC idle callback. +@@ -132,13 +133,20 @@ static int gmc_v7_0_init_microcode(struc + case CHIP_HAWAII: + chip_name = "hawaii"; + break; ++ case CHIP_TOPAZ: ++ chip_name = "topaz"; ++ break; + case CHIP_KAVERI: + case CHIP_KABINI: + return 0; + default: BUG(); + } + +- snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); ++ if(adev->asic_type == CHIP_TOPAZ) ++ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mc.bin", chip_name); ++ else ++ snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); ++ + err = request_firmware(&adev->mc.fw, fw_name, adev->dev); + if (err) + goto out; +--- a/drivers/gpu/drm/amd/amdgpu/vi.c ++++ b/drivers/gpu/drm/amd/amdgpu/vi.c +@@ -60,6 +60,7 @@ + #include "vi.h" + #include "vi_dpm.h" + #include "gmc_v8_0.h" ++#include "gmc_v7_0.h" + #include "gfx_v8_0.h" + #include "sdma_v2_4.h" + #include "sdma_v3_0.h" +@@ -1128,10 +1129,10 @@ static const struct amdgpu_ip_block_vers + }, + { + .type = AMD_IP_BLOCK_TYPE_GMC, +- .major = 8, +- .minor = 0, ++ .major = 7, ++ .minor = 4, + .rev = 0, +- .funcs = &gmc_v8_0_ip_funcs, ++ .funcs = &gmc_v7_0_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_IH, diff --git a/queue-4.4/drm-amdgpu-move-gmc7-support-out-of-cik-dependency.patch b/queue-4.4/drm-amdgpu-move-gmc7-support-out-of-cik-dependency.patch new file mode 100644 index 00000000000..d4340d97b08 --- /dev/null +++ b/queue-4.4/drm-amdgpu-move-gmc7-support-out-of-cik-dependency.patch @@ -0,0 +1,42 @@ +From e42d85261680edfc350a6c2a86b7fbb44a85014b Mon Sep 17 00:00:00 2001 +From: Alex Deucher +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 + +commit e42d85261680edfc350a6c2a86b7fbb44a85014b upstream. + +It's used by iceland which is VI. + +Reviewed-by: Ken Wang +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/Makefile | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/amd/amdgpu/Makefile ++++ b/drivers/gpu/drm/amd/amdgpu/Makefile +@@ -22,7 +22,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o + amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o + + # add asic specific block +-amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o gmc_v7_0.o cik_ih.o kv_smc.o kv_dpm.o \ ++amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \ + ci_smc.o ci_dpm.o dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o \ + amdgpu_amdkfd_gfx_v7.o + +@@ -31,6 +31,7 @@ amdgpu-y += \ + + # add GMC block + amdgpu-y += \ ++ gmc_v7_0.o \ + gmc_v8_0.o + + # add IH block diff --git a/queue-4.4/drm-amdgpu-no-need-to-load-mc-firmware-on-fiji.patch b/queue-4.4/drm-amdgpu-no-need-to-load-mc-firmware-on-fiji.patch new file mode 100644 index 00000000000..4e69c9796f9 --- /dev/null +++ b/queue-4.4/drm-amdgpu-no-need-to-load-mc-firmware-on-fiji.patch @@ -0,0 +1,48 @@ +From ad32152eb26043d165eed9406cb9e2f7011f6b10 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Thu, 28 Jan 2016 16:27:41 -0500 +Subject: drm/amdgpu: no need to load MC firmware on fiji + +From: Alex Deucher + +commit ad32152eb26043d165eed9406cb9e2f7011f6b10 upstream. + +Vbios does this for us on asic_init. + +Reviewed-by: Ken Wang >Qingqing.Wang@amd.com> +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +@@ -44,7 +44,6 @@ static void gmc_v8_0_set_irq_funcs(struc + + MODULE_FIRMWARE("amdgpu/topaz_mc.bin"); + MODULE_FIRMWARE("amdgpu/tonga_mc.bin"); +-MODULE_FIRMWARE("amdgpu/fiji_mc.bin"); + + static const u32 golden_settings_tonga_a11[] = + { +@@ -236,8 +235,6 @@ static int gmc_v8_0_init_microcode(struc + chip_name = "tonga"; + break; + case CHIP_FIJI: +- chip_name = "fiji"; +- break; + case CHIP_CARRIZO: + case CHIP_STONEY: + return 0; +@@ -1003,7 +1000,8 @@ static int gmc_v8_0_hw_init(void *handle + + gmc_v8_0_mc_program(adev); + +- if (!(adev->flags & AMD_IS_APU)) { ++ if ((adev->asic_type == CHIP_TOPAZ) || ++ (adev->asic_type == CHIP_TONGA)) { + r = gmc_v8_0_mc_load_microcode(adev); + if (r) { + DRM_ERROR("Failed to load MC firmware!\n"); diff --git a/queue-4.4/drm-amdgpu-pm-adjust-display-configuration-after-powerstate.patch b/queue-4.4/drm-amdgpu-pm-adjust-display-configuration-after-powerstate.patch new file mode 100644 index 00000000000..16d1e75b543 --- /dev/null +++ b/queue-4.4/drm-amdgpu-pm-adjust-display-configuration-after-powerstate.patch @@ -0,0 +1,49 @@ +From 8e7cedc6f7fe762ffe6e348502be34b11fa79298 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +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 + +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 +Acked-by: Jordan Lazare +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +@@ -595,8 +595,6 @@ force: + + /* update display watermarks based on new power state */ + amdgpu_display_bandwidth_update(adev); +- /* update displays */ +- amdgpu_dpm_display_configuration_changed(adev); + + adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; + adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; +@@ -616,6 +614,9 @@ force: + + amdgpu_dpm_post_set_power_state(adev); + ++ /* update displays */ ++ amdgpu_dpm_display_configuration_changed(adev); ++ + if (adev->pm.funcs->force_performance_level) { + if (adev->pm.dpm.thermal_active) { + enum amdgpu_dpm_forced_level level = adev->pm.dpm.forced_level; diff --git a/queue-4.4/drm-amdgpu-pull-topaz-gmc-bits-into-gmc_v7.patch b/queue-4.4/drm-amdgpu-pull-topaz-gmc-bits-into-gmc_v7.patch new file mode 100644 index 00000000000..54b32d52be2 --- /dev/null +++ b/queue-4.4/drm-amdgpu-pull-topaz-gmc-bits-into-gmc_v7.patch @@ -0,0 +1,82 @@ +From 72b459c8f716ef03a8a0c78078547ce64d8d29a2 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +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 + +commit 72b459c8f716ef03a8a0c78078547ce64d8d29a2 upstream. + +Add the topaz golden settings into the gmc7 module. + +Reviewed-by: Ken Wang +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 35 ++++++++++++++++++++++++++++++++-- + 1 file changed, 33 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +@@ -44,8 +44,37 @@ MODULE_FIRMWARE("radeon/bonaire_mc.bin") + MODULE_FIRMWARE("radeon/hawaii_mc.bin"); + MODULE_FIRMWARE("amdgpu/topaz_mc.bin"); + ++static const u32 golden_settings_iceland_a11[] = ++{ ++ mmVM_PRT_APERTURE0_LOW_ADDR, 0x0fffffff, 0x0fffffff, ++ mmVM_PRT_APERTURE1_LOW_ADDR, 0x0fffffff, 0x0fffffff, ++ mmVM_PRT_APERTURE2_LOW_ADDR, 0x0fffffff, 0x0fffffff, ++ mmVM_PRT_APERTURE3_LOW_ADDR, 0x0fffffff, 0x0fffffff ++}; ++ ++static const u32 iceland_mgcg_cgcg_init[] = ++{ ++ mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104 ++}; ++ ++static void gmc_v7_0_init_golden_registers(struct amdgpu_device *adev) ++{ ++ switch (adev->asic_type) { ++ case CHIP_TOPAZ: ++ amdgpu_program_register_sequence(adev, ++ iceland_mgcg_cgcg_init, ++ (const u32)ARRAY_SIZE(iceland_mgcg_cgcg_init)); ++ amdgpu_program_register_sequence(adev, ++ golden_settings_iceland_a11, ++ (const u32)ARRAY_SIZE(golden_settings_iceland_a11)); ++ break; ++ default: ++ break; ++ } ++} ++ + /** +- * gmc8_mc_wait_for_idle - wait for MC idle callback. ++ * gmc7_mc_wait_for_idle - wait for MC idle callback. + * + * @adev: amdgpu_device pointer + * +@@ -142,7 +171,7 @@ static int gmc_v7_0_init_microcode(struc + default: BUG(); + } + +- if(adev->asic_type == CHIP_TOPAZ) ++ if (adev->asic_type == CHIP_TOPAZ) + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mc.bin", chip_name); + else + snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); +@@ -988,6 +1017,8 @@ static int gmc_v7_0_hw_init(void *handle + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + ++ gmc_v7_0_init_golden_registers(adev); ++ + gmc_v7_0_mc_program(adev); + + if (!(adev->flags & AMD_IS_APU)) { diff --git a/queue-4.4/drm-amdgpu-remove-exp-hardware-support-from-iceland.patch b/queue-4.4/drm-amdgpu-remove-exp-hardware-support-from-iceland.patch new file mode 100644 index 00000000000..167dfccc360 --- /dev/null +++ b/queue-4.4/drm-amdgpu-remove-exp-hardware-support-from-iceland.patch @@ -0,0 +1,45 @@ +From dba280b20bfd1c2bed8a07ce3f75a6da8ba7d247 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +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 + +commit dba280b20bfd1c2bed8a07ce3f75a6da8ba7d247 upstream. + +It's working now. + +bug: +https://bugs.freedesktop.org/show_bug.cgi?id=92270 + +Reviewed-by: Ken Wang +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +@@ -250,11 +250,11 @@ static struct pci_device_id pciidlist[] + {0x1002, 0x985F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU}, + #endif + /* topaz */ +- {0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT}, +- {0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT}, +- {0x1002, 0x6902, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT}, +- {0x1002, 0x6903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT}, +- {0x1002, 0x6907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT}, ++ {0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, ++ {0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, ++ {0x1002, 0x6902, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, ++ {0x1002, 0x6903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, ++ {0x1002, 0x6907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, + /* tonga */ + {0x1002, 0x6920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA}, + {0x1002, 0x6921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA}, diff --git a/queue-4.4/drm-amdgpu-remove-unnecessary-forward-declaration.patch b/queue-4.4/drm-amdgpu-remove-unnecessary-forward-declaration.patch new file mode 100644 index 00000000000..b775970953e --- /dev/null +++ b/queue-4.4/drm-amdgpu-remove-unnecessary-forward-declaration.patch @@ -0,0 +1,32 @@ +From b19763d0d867eb863953500a5c87f2fd663863b8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Nicolai=20H=C3=A4hnle?= +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 + +commit b19763d0d867eb863953500a5c87f2fd663863b8 upstream. + +Signed-off-by: Nicolai Hähnle +Reviewed-by: Alex Deucher +Reviewed-by: Christian König +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +@@ -604,8 +604,6 @@ struct amdgpu_sa_manager { + uint32_t align; + }; + +-struct amdgpu_sa_bo; +- + /* sub-allocation buffer */ + struct amdgpu_sa_bo { + struct list_head olist; diff --git a/queue-4.4/drm-amdgpu-the-vi-specific-exe-bit-should-only-apply-to-gmc-v8.0-above.patch b/queue-4.4/drm-amdgpu-the-vi-specific-exe-bit-should-only-apply-to-gmc-v8.0-above.patch new file mode 100644 index 00000000000..552f1bce8c6 --- /dev/null +++ b/queue-4.4/drm-amdgpu-the-vi-specific-exe-bit-should-only-apply-to-gmc-v8.0-above.patch @@ -0,0 +1,32 @@ +From 8f3c162961fc2d92ec73a66496aab69eb2e19c36 Mon Sep 17 00:00:00 2001 +From: Ken Wang +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 + +commit 8f3c162961fc2d92ec73a66496aab69eb2e19c36 upstream. + +Reviewed-by: Christian König +Reviewed-by: Alex Deucher +Signed-off-by: Ken Wang +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +@@ -808,7 +808,7 @@ uint32_t amdgpu_ttm_tt_pte_flags(struct + flags |= AMDGPU_PTE_SNOOPED; + } + +- if (adev->asic_type >= CHIP_TOPAZ) ++ if (adev->asic_type >= CHIP_TONGA) + flags |= AMDGPU_PTE_EXECUTABLE; + + flags |= AMDGPU_PTE_READABLE; diff --git a/queue-4.4/drm-amdgpu-use-post-decrement-in-error-handling.patch b/queue-4.4/drm-amdgpu-use-post-decrement-in-error-handling.patch new file mode 100644 index 00000000000..eed87258eb4 --- /dev/null +++ b/queue-4.4/drm-amdgpu-use-post-decrement-in-error-handling.patch @@ -0,0 +1,36 @@ +From 09ccbb74b6718ad4d1290de3f5669212c0ac7d4b Mon Sep 17 00:00:00 2001 +From: Rasmus Villemoes +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 + +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 +Signed-off-by: Rasmus Villemoes +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +@@ -712,7 +712,7 @@ static int amdgpu_ttm_tt_populate(struct + 0, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(adev->pdev, gtt->ttm.dma_address[i])) { +- while (--i) { ++ while (i--) { + pci_unmap_page(adev->pdev, gtt->ttm.dma_address[i], + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + gtt->ttm.dma_address[i] = 0; diff --git a/queue-4.4/drm-dp-mst-always-send-reply-for-up-request.patch b/queue-4.4/drm-dp-mst-always-send-reply-for-up-request.patch new file mode 100644 index 00000000000..da65a77f221 --- /dev/null +++ b/queue-4.4/drm-dp-mst-always-send-reply-for-up-request.patch @@ -0,0 +1,96 @@ +From 1f16ee7fa13649f4e55aa48ad31c3eb0722a62d3 Mon Sep 17 00:00:00 2001 +From: Mykola Lysenko +Date: Fri, 18 Dec 2015 17:14:43 -0500 +Subject: drm/dp/mst: always send reply for UP request + +From: Mykola Lysenko + +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 +Signed-off-by: Mykola Lysenko +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_dp_mst_topology.c | 30 +++++++++++------------------- + include/drm/drm_dp_mst_helper.h | 2 -- + 2 files changed, 11 insertions(+), 21 deletions(-) + +--- a/drivers/gpu/drm/drm_dp_mst_topology.c ++++ b/drivers/gpu/drm/drm_dp_mst_topology.c +@@ -1489,26 +1489,18 @@ static void process_single_down_tx_qlock + } + + /* called holding qlock */ +-static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr) ++static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr, ++ struct drm_dp_sideband_msg_tx *txmsg) + { +- struct drm_dp_sideband_msg_tx *txmsg; + int ret; + + /* construct a chunk from the first msg in the tx_msg queue */ +- if (list_empty(&mgr->tx_msg_upq)) { +- mgr->tx_up_in_progress = false; +- return; +- } +- +- txmsg = list_first_entry(&mgr->tx_msg_upq, struct drm_dp_sideband_msg_tx, next); + ret = process_single_tx_qlock(mgr, txmsg, true); +- if (ret == 1) { +- /* up txmsgs aren't put in slots - so free after we send it */ +- list_del(&txmsg->next); +- kfree(txmsg); +- } else if (ret) ++ ++ if (ret != 1) + DRM_DEBUG_KMS("failed to send msg in q %d\n", ret); +- mgr->tx_up_in_progress = true; ++ ++ txmsg->dst->tx_slots[txmsg->seqno] = NULL; + } + + static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr, +@@ -1895,11 +1887,12 @@ static int drm_dp_send_up_ack_reply(stru + drm_dp_encode_up_ack_reply(txmsg, req_type); + + mutex_lock(&mgr->qlock); +- list_add_tail(&txmsg->next, &mgr->tx_msg_upq); +- if (!mgr->tx_up_in_progress) { +- process_single_up_tx_qlock(mgr); +- } ++ ++ process_single_up_tx_qlock(mgr, txmsg); ++ + mutex_unlock(&mgr->qlock); ++ ++ kfree(txmsg); + return 0; + } + +@@ -2809,7 +2802,6 @@ int drm_dp_mst_topology_mgr_init(struct + mutex_init(&mgr->qlock); + mutex_init(&mgr->payload_lock); + mutex_init(&mgr->destroy_connector_lock); +- INIT_LIST_HEAD(&mgr->tx_msg_upq); + INIT_LIST_HEAD(&mgr->tx_msg_downq); + INIT_LIST_HEAD(&mgr->destroy_connector_list); + INIT_WORK(&mgr->work, drm_dp_mst_link_probe_work); +--- a/include/drm/drm_dp_mst_helper.h ++++ b/include/drm/drm_dp_mst_helper.h +@@ -450,9 +450,7 @@ struct drm_dp_mst_topology_mgr { + the mstb tx_slots and txmsg->state once they are queued */ + struct mutex qlock; + struct list_head tx_msg_downq; +- struct list_head tx_msg_upq; + bool tx_down_in_progress; +- bool tx_up_in_progress; + + /* payload info + lock for it */ + struct mutex payload_lock; diff --git a/queue-4.4/drm-dp-mst-calculate-mst-pbn-with-31.32-fixed-point.patch b/queue-4.4/drm-dp-mst-calculate-mst-pbn-with-31.32-fixed-point.patch new file mode 100644 index 00000000000..a3fb1bac927 --- /dev/null +++ b/queue-4.4/drm-dp-mst-calculate-mst-pbn-with-31.32-fixed-point.patch @@ -0,0 +1,110 @@ +From a9ebb3e46c7ef6112c0da466ef0954673ad36832 Mon Sep 17 00:00:00 2001 +From: Harry Wentland +Date: Fri, 22 Jan 2016 17:07:26 -0500 +Subject: drm/dp/mst: Calculate MST PBN with 31.32 fixed point + +From: Harry Wentland + +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 +Reviewed-by: Alex Deucher +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_dp_mst_topology.c | 67 +++++++++++++++++++--------------- + 1 file changed, 39 insertions(+), 28 deletions(-) + +--- a/drivers/gpu/drm/drm_dp_mst_topology.c ++++ b/drivers/gpu/drm/drm_dp_mst_topology.c +@@ -2571,32 +2571,31 @@ EXPORT_SYMBOL(drm_dp_check_act_status); + */ + int drm_dp_calc_pbn_mode(int clock, int bpp) + { +- fixed20_12 pix_bw; +- fixed20_12 fbpp; +- fixed20_12 result; +- fixed20_12 margin, tmp; +- u32 res; +- +- pix_bw.full = dfixed_const(clock); +- fbpp.full = dfixed_const(bpp); +- tmp.full = dfixed_const(8); +- fbpp.full = dfixed_div(fbpp, tmp); +- +- result.full = dfixed_mul(pix_bw, fbpp); +- margin.full = dfixed_const(54); +- tmp.full = dfixed_const(64); +- margin.full = dfixed_div(margin, tmp); +- result.full = dfixed_div(result, margin); +- +- margin.full = dfixed_const(1006); +- tmp.full = dfixed_const(1000); +- margin.full = dfixed_div(margin, tmp); +- result.full = dfixed_mul(result, margin); +- +- result.full = dfixed_div(result, tmp); +- result.full = dfixed_ceil(result); +- res = dfixed_trunc(result); +- return res; ++ u64 kbps; ++ s64 peak_kbps; ++ u32 numerator; ++ u32 denominator; ++ ++ kbps = clock * bpp; ++ ++ /* ++ * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006 ++ * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on ++ * common multiplier to render an integer PBN for all link rate/lane ++ * counts combinations ++ * calculate ++ * peak_kbps *= (1006/1000) ++ * peak_kbps *= (64/54) ++ * peak_kbps *= 8 convert to bytes ++ */ ++ ++ numerator = 64 * 1006; ++ denominator = 54 * 8 * 1000 * 1000; ++ ++ kbps *= numerator; ++ peak_kbps = drm_fixp_from_fraction(kbps, denominator); ++ ++ return drm_fixp2int_ceil(peak_kbps); + } + EXPORT_SYMBOL(drm_dp_calc_pbn_mode); + +@@ -2604,11 +2603,23 @@ static int test_calc_pbn_mode(void) + { + int ret; + ret = drm_dp_calc_pbn_mode(154000, 30); +- if (ret != 689) ++ if (ret != 689) { ++ DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n", ++ 154000, 30, 689, ret); + return -EINVAL; ++ } + ret = drm_dp_calc_pbn_mode(234000, 30); +- if (ret != 1047) ++ if (ret != 1047) { ++ DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n", ++ 234000, 30, 1047, ret); ++ return -EINVAL; ++ } ++ ret = drm_dp_calc_pbn_mode(297000, 24); ++ if (ret != 1063) { ++ DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n", ++ 297000, 24, 1063, ret); + return -EINVAL; ++ } + return 0; + } + diff --git a/queue-4.4/drm-dp-mst-deallocate-payload-on-port-destruction.patch b/queue-4.4/drm-dp-mst-deallocate-payload-on-port-destruction.patch new file mode 100644 index 00000000000..45554387177 --- /dev/null +++ b/queue-4.4/drm-dp-mst-deallocate-payload-on-port-destruction.patch @@ -0,0 +1,195 @@ +From 91a25e463130c8e19bdb42f2d827836c7937992e Mon Sep 17 00:00:00 2001 +From: Mykola Lysenko +Date: Wed, 27 Jan 2016 09:39:36 -0500 +Subject: drm/dp/mst: deallocate payload on port destruction + +From: Mykola Lysenko + +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 +Reviewed-by: Harry Wentland +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_dp_mst_topology.c | 91 +++++++++++++++++++++++++++++++--- + 1 file changed, 83 insertions(+), 8 deletions(-) + +--- a/drivers/gpu/drm/drm_dp_mst_topology.c ++++ b/drivers/gpu/drm/drm_dp_mst_topology.c +@@ -798,6 +798,18 @@ static struct drm_dp_mst_branch *drm_dp_ + return mstb; + } + ++static void drm_dp_free_mst_port(struct kref *kref); ++ ++static void drm_dp_free_mst_branch_device(struct kref *kref) ++{ ++ struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref); ++ if (mstb->port_parent) { ++ if (list_empty(&mstb->port_parent->next)) ++ kref_put(&mstb->port_parent->kref, drm_dp_free_mst_port); ++ } ++ kfree(mstb); ++} ++ + static void drm_dp_destroy_mst_branch_device(struct kref *kref) + { + struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref); +@@ -805,6 +817,15 @@ static void drm_dp_destroy_mst_branch_de + bool wake_tx = false; + + /* ++ * init kref again to be used by ports to remove mst branch when it is ++ * not needed anymore ++ */ ++ kref_init(kref); ++ ++ if (mstb->port_parent && list_empty(&mstb->port_parent->next)) ++ kref_get(&mstb->port_parent->kref); ++ ++ /* + * destroy all ports - don't need lock + * as there are no more references to the mst branch + * device at this point. +@@ -830,7 +851,8 @@ static void drm_dp_destroy_mst_branch_de + + if (wake_tx) + wake_up(&mstb->mgr->tx_waitq); +- kfree(mstb); ++ ++ kref_put(kref, drm_dp_free_mst_branch_device); + } + + static void drm_dp_put_mst_branch_device(struct drm_dp_mst_branch *mstb) +@@ -878,6 +900,7 @@ static void drm_dp_destroy_port(struct k + * from an EDID retrieval */ + + mutex_lock(&mgr->destroy_connector_lock); ++ kref_get(&port->parent->kref); + list_add(&port->next, &mgr->destroy_connector_list); + mutex_unlock(&mgr->destroy_connector_lock); + schedule_work(&mgr->destroy_connector_work); +@@ -1602,6 +1625,37 @@ static int drm_dp_send_enum_path_resourc + return 0; + } + ++static struct drm_dp_mst_port *drm_dp_get_last_connected_port_to_mstb(struct drm_dp_mst_branch *mstb) ++{ ++ if (!mstb->port_parent) ++ return NULL; ++ ++ if (mstb->port_parent->mstb != mstb) ++ return mstb->port_parent; ++ ++ return drm_dp_get_last_connected_port_to_mstb(mstb->port_parent->parent); ++} ++ ++static struct drm_dp_mst_branch *drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr, ++ struct drm_dp_mst_branch *mstb, ++ int *port_num) ++{ ++ struct drm_dp_mst_branch *rmstb = NULL; ++ struct drm_dp_mst_port *found_port; ++ mutex_lock(&mgr->lock); ++ if (mgr->mst_primary) { ++ found_port = drm_dp_get_last_connected_port_to_mstb(mstb); ++ ++ if (found_port) { ++ rmstb = found_port->parent; ++ kref_get(&rmstb->kref); ++ *port_num = found_port->port_num; ++ } ++ } ++ mutex_unlock(&mgr->lock); ++ return rmstb; ++} ++ + static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port, + int id, +@@ -1609,11 +1663,16 @@ static int drm_dp_payload_send_msg(struc + { + struct drm_dp_sideband_msg_tx *txmsg; + struct drm_dp_mst_branch *mstb; +- int len, ret; ++ int len, ret, port_num; + ++ port_num = port->port_num; + mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent); +- if (!mstb) +- return -EINVAL; ++ if (!mstb) { ++ mstb = drm_dp_get_last_connected_port_and_mstb(mgr, port->parent, &port_num); ++ ++ if (!mstb) ++ return -EINVAL; ++ } + + txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); + if (!txmsg) { +@@ -1622,7 +1681,7 @@ static int drm_dp_payload_send_msg(struc + } + + txmsg->dst = mstb; +- len = build_allocate_payload(txmsg, port->port_num, ++ len = build_allocate_payload(txmsg, port_num, + id, + pbn); + +@@ -2752,6 +2811,13 @@ static void drm_dp_tx_work(struct work_s + mutex_unlock(&mgr->qlock); + } + ++static void drm_dp_free_mst_port(struct kref *kref) ++{ ++ struct drm_dp_mst_port *port = container_of(kref, struct drm_dp_mst_port, kref); ++ kref_put(&port->parent->kref, drm_dp_free_mst_branch_device); ++ kfree(port); ++} ++ + static void drm_dp_destroy_connector_work(struct work_struct *work) + { + struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work); +@@ -2772,13 +2838,22 @@ static void drm_dp_destroy_connector_wor + list_del(&port->next); + mutex_unlock(&mgr->destroy_connector_lock); + ++ kref_init(&port->kref); ++ INIT_LIST_HEAD(&port->next); ++ + mgr->cbs->destroy_connector(mgr, port->connector); + + drm_dp_port_teardown_pdt(port, port->pdt); + +- if (!port->input && port->vcpi.vcpi > 0) +- drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi); +- kfree(port); ++ if (!port->input && port->vcpi.vcpi > 0) { ++ if (mgr->mst_state) { ++ drm_dp_mst_reset_vcpi_slots(mgr, port); ++ drm_dp_update_payload_part1(mgr); ++ drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi); ++ } ++ } ++ ++ kref_put(&port->kref, drm_dp_free_mst_port); + send_hotplug = true; + } + if (send_hotplug) diff --git a/queue-4.4/drm-dp-mst-fix-in-mstb-rad-initialization.patch b/queue-4.4/drm-dp-mst-fix-in-mstb-rad-initialization.patch new file mode 100644 index 00000000000..3fb35091d2e --- /dev/null +++ b/queue-4.4/drm-dp-mst-fix-in-mstb-rad-initialization.patch @@ -0,0 +1,48 @@ +From 75af4c8c4c0f60d7ad135419805798f144e9baf9 Mon Sep 17 00:00:00 2001 +From: Mykola Lysenko +Date: Fri, 25 Dec 2015 16:14:47 +0800 +Subject: drm/dp/mst: fix in MSTB RAD initialization + +From: Mykola Lysenko + +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 +Signed-off-by: Mykola Lysenko +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_dp_mst_topology.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/drm_dp_mst_topology.c ++++ b/drivers/gpu/drm/drm_dp_mst_topology.c +@@ -973,17 +973,17 @@ static struct drm_dp_mst_port *drm_dp_ge + static u8 drm_dp_calculate_rad(struct drm_dp_mst_port *port, + u8 *rad) + { +- int lct = port->parent->lct; ++ int parent_lct = port->parent->lct; + int shift = 4; +- int idx = lct / 2; +- if (lct > 1) { +- memcpy(rad, port->parent->rad, idx); +- shift = (lct % 2) ? 4 : 0; ++ int idx = (parent_lct - 1) / 2; ++ if (parent_lct > 1) { ++ memcpy(rad, port->parent->rad, idx + 1); ++ shift = (parent_lct % 2) ? 4 : 0; + } else + rad[0] = 0; + + rad[idx] |= port->port_num << shift; +- return lct + 1; ++ return parent_lct + 1; + } + + /* diff --git a/queue-4.4/drm-dp-mst-fix-in-rad-element-access.patch b/queue-4.4/drm-dp-mst-fix-in-rad-element-access.patch new file mode 100644 index 00000000000..60975b9adea --- /dev/null +++ b/queue-4.4/drm-dp-mst-fix-in-rad-element-access.patch @@ -0,0 +1,41 @@ +From 7a11a334aa6af4c65c6a0d81b60c97fc18673532 Mon Sep 17 00:00:00 2001 +From: Mykola Lysenko +Date: Fri, 25 Dec 2015 16:14:48 +0800 +Subject: drm/dp/mst: fix in RAD element access + +From: Mykola Lysenko + +commit 7a11a334aa6af4c65c6a0d81b60c97fc18673532 upstream. + +This is needed to receive correct port +number from RAD, so MSTB could be found + +Acked-by: Dave Airlie +Signed-off-by: Mykola Lysenko +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_dp_mst_topology.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/drm_dp_mst_topology.c ++++ b/drivers/gpu/drm/drm_dp_mst_topology.c +@@ -1039,7 +1039,7 @@ static void build_mst_prop_path(const st + snprintf(proppath, proppath_size, "mst:%d", mstb->mgr->conn_base_id); + for (i = 0; i < (mstb->lct - 1); i++) { + int shift = (i % 2) ? 0 : 4; +- int port_num = mstb->rad[i / 2] >> shift; ++ int port_num = (mstb->rad[i / 2] >> shift) & 0xf; + snprintf(temp, sizeof(temp), "-%d", port_num); + strlcat(proppath, temp, proppath_size); + } +@@ -1190,7 +1190,7 @@ static struct drm_dp_mst_branch *drm_dp_ + + for (i = 0; i < lct - 1; i++) { + int shift = (i % 2) ? 0 : 4; +- int port_num = rad[i / 2] >> shift; ++ int port_num = (rad[i / 2] >> shift) & 0xf; + + list_for_each_entry(port, &mstb->ports, next) { + if (port->port_num == port_num) { diff --git a/queue-4.4/drm-dp-mst-move-guid-storage-from-mgr-port-to-only-mst-branch.patch b/queue-4.4/drm-dp-mst-move-guid-storage-from-mgr-port-to-only-mst-branch.patch new file mode 100644 index 00000000000..4cb69b1ef5a --- /dev/null +++ b/queue-4.4/drm-dp-mst-move-guid-storage-from-mgr-port-to-only-mst-branch.patch @@ -0,0 +1,244 @@ +From 5e93b8208d3c419b515fb75e2601931c027e12ab Mon Sep 17 00:00:00 2001 +From: Hersen Wu +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 + +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 +Reviewed-by: Harry Wentland +Acked-by: Alex Deucher +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_dp_mst_topology.c | 64 ++++++++++++++-------------------- + include/drm/drm_dp_mst_helper.h | 25 +++++-------- + 2 files changed, 38 insertions(+), 51 deletions(-) + +--- a/drivers/gpu/drm/drm_dp_mst_topology.c ++++ b/drivers/gpu/drm/drm_dp_mst_topology.c +@@ -1013,18 +1013,27 @@ static bool drm_dp_port_setup_pdt(struct + return send_link; + } + +-static void drm_dp_check_port_guid(struct drm_dp_mst_branch *mstb, +- struct drm_dp_mst_port *port) ++static void drm_dp_check_mstb_guid(struct drm_dp_mst_branch *mstb, u8 *guid) + { + int ret; +- if (port->dpcd_rev >= 0x12) { +- port->guid_valid = drm_dp_validate_guid(mstb->mgr, port->guid); +- if (!port->guid_valid) { +- ret = drm_dp_send_dpcd_write(mstb->mgr, +- port, +- DP_GUID, +- 16, port->guid); +- port->guid_valid = true; ++ ++ memcpy(mstb->guid, guid, 16); ++ ++ if (!drm_dp_validate_guid(mstb->mgr, mstb->guid)) { ++ if (mstb->port_parent) { ++ ret = drm_dp_send_dpcd_write( ++ mstb->mgr, ++ mstb->port_parent, ++ DP_GUID, ++ 16, ++ mstb->guid); ++ } else { ++ ++ ret = drm_dp_dpcd_write( ++ mstb->mgr->aux, ++ DP_GUID, ++ mstb->guid, ++ 16); + } + } + } +@@ -1081,7 +1090,6 @@ static void drm_dp_add_port(struct drm_d + port->dpcd_rev = port_msg->dpcd_revision; + port->num_sdp_streams = port_msg->num_sdp_streams; + port->num_sdp_stream_sinks = port_msg->num_sdp_stream_sinks; +- memcpy(port->guid, port_msg->peer_guid, 16); + + /* manage mstb port lists with mgr lock - take a reference + for this list */ +@@ -1094,11 +1102,9 @@ static void drm_dp_add_port(struct drm_d + + if (old_ddps != port->ddps) { + if (port->ddps) { +- drm_dp_check_port_guid(mstb, port); + if (!port->input) + drm_dp_send_enum_path_resources(mstb->mgr, mstb, port); + } else { +- port->guid_valid = false; + port->available_pbn = 0; + } + } +@@ -1157,10 +1163,8 @@ static void drm_dp_update_port(struct dr + + if (old_ddps != port->ddps) { + if (port->ddps) { +- drm_dp_check_port_guid(mstb, port); + dowork = true; + } else { +- port->guid_valid = false; + port->available_pbn = 0; + } + } +@@ -1217,13 +1221,14 @@ static struct drm_dp_mst_branch *get_mst + struct drm_dp_mst_branch *found_mstb; + struct drm_dp_mst_port *port; + ++ if (memcmp(mstb->guid, guid, 16) == 0) ++ return mstb; ++ ++ + list_for_each_entry(port, &mstb->ports, next) { + if (!port->mstb) + continue; + +- if (port->guid_valid && memcmp(port->guid, guid, 16) == 0) +- return port->mstb; +- + found_mstb = get_mst_branch_device_by_guid_helper(port->mstb, guid); + + if (found_mstb) +@@ -1242,10 +1247,7 @@ static struct drm_dp_mst_branch *drm_dp_ + /* find the port by iterating down */ + mutex_lock(&mgr->lock); + +- if (mgr->guid_valid && memcmp(mgr->guid, guid, 16) == 0) +- mstb = mgr->mst_primary; +- else +- mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid); ++ mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid); + + if (mstb) + kref_get(&mstb->kref); +@@ -1550,6 +1552,9 @@ static void drm_dp_send_link_address(str + txmsg->reply.u.link_addr.ports[i].num_sdp_streams, + txmsg->reply.u.link_addr.ports[i].num_sdp_stream_sinks); + } ++ ++ drm_dp_check_mstb_guid(mstb, txmsg->reply.u.link_addr.guid); ++ + for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) { + drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]); + } +@@ -1984,20 +1989,6 @@ int drm_dp_mst_topology_mgr_set_mst(stru + goto out_unlock; + } + +- +- /* sort out guid */ +- ret = drm_dp_dpcd_read(mgr->aux, DP_GUID, mgr->guid, 16); +- if (ret != 16) { +- DRM_DEBUG_KMS("failed to read DP GUID %d\n", ret); +- goto out_unlock; +- } +- +- mgr->guid_valid = drm_dp_validate_guid(mgr, mgr->guid); +- if (!mgr->guid_valid) { +- ret = drm_dp_dpcd_write(mgr->aux, DP_GUID, mgr->guid, 16); +- mgr->guid_valid = true; +- } +- + queue_work(system_long_wq, &mgr->work); + + ret = 0; +@@ -2219,6 +2210,7 @@ static int drm_dp_mst_handle_up_req(stru + } + + drm_dp_update_port(mstb, &msg.u.conn_stat); ++ + DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type); + (*mgr->cbs->hotplug)(mgr); + +--- a/include/drm/drm_dp_mst_helper.h ++++ b/include/drm/drm_dp_mst_helper.h +@@ -44,8 +44,6 @@ struct drm_dp_vcpi { + /** + * struct drm_dp_mst_port - MST port + * @kref: reference count for this port. +- * @guid_valid: for DP 1.2 devices if we have validated the GUID. +- * @guid: guid for DP 1.2 device on this port. + * @port_num: port number + * @input: if this port is an input port. + * @mcs: message capability status - DP 1.2 spec. +@@ -70,10 +68,6 @@ struct drm_dp_vcpi { + struct drm_dp_mst_port { + struct kref kref; + +- /* if dpcd 1.2 device is on this port - its GUID info */ +- bool guid_valid; +- u8 guid[16]; +- + u8 port_num; + bool input; + bool mcs; +@@ -109,10 +103,12 @@ struct drm_dp_mst_port { + * @tx_slots: transmission slots for this device. + * @last_seqno: last sequence number used to talk to this. + * @link_address_sent: if a link address message has been sent to this device yet. ++ * @guid: guid for DP 1.2 branch device. port under this branch can be ++ * identified by port #. + * + * This structure represents an MST branch device, there is one +- * primary branch device at the root, along with any others connected +- * to downstream ports ++ * primary branch device at the root, along with any other branches connected ++ * to downstream port of parent branches. + */ + struct drm_dp_mst_branch { + struct kref kref; +@@ -131,6 +127,9 @@ struct drm_dp_mst_branch { + struct drm_dp_sideband_msg_tx *tx_slots[2]; + int last_seqno; + bool link_address_sent; ++ ++ /* global unique identifier to identify branch devices */ ++ u8 guid[16]; + }; + + +@@ -405,11 +404,9 @@ struct drm_dp_payload { + * @conn_base_id: DRM connector ID this mgr is connected to. + * @down_rep_recv: msg receiver state for down replies. + * @up_req_recv: msg receiver state for up requests. +- * @lock: protects mst state, primary, guid, dpcd. ++ * @lock: protects mst state, primary, dpcd. + * @mst_state: if this manager is enabled for an MST capable port. + * @mst_primary: pointer to the primary branch device. +- * @guid_valid: GUID valid for the primary branch device. +- * @guid: GUID for primary port. + * @dpcd: cache of DPCD for primary port. + * @pbn_div: PBN to slots divisor. + * +@@ -431,13 +428,11 @@ struct drm_dp_mst_topology_mgr { + struct drm_dp_sideband_msg_rx up_req_recv; + + /* pointer to info about the initial MST device */ +- struct mutex lock; /* protects mst_state + primary + guid + dpcd */ ++ struct mutex lock; /* protects mst_state + primary + dpcd */ + + bool mst_state; + struct drm_dp_mst_branch *mst_primary; +- /* primary MST device GUID */ +- bool guid_valid; +- u8 guid[16]; ++ + u8 dpcd[DP_RECEIVER_CAP_SIZE]; + u8 sink_count; + int pbn_div; diff --git a/queue-4.4/drm-dp-mst-process-broadcast-messages-correctly.patch b/queue-4.4/drm-dp-mst-process-broadcast-messages-correctly.patch new file mode 100644 index 00000000000..2ae08e3ed6b --- /dev/null +++ b/queue-4.4/drm-dp-mst-process-broadcast-messages-correctly.patch @@ -0,0 +1,163 @@ +From bd9343208704fcc70a5b919f228a7d26ae472727 Mon Sep 17 00:00:00 2001 +From: Mykola Lysenko +Date: Fri, 18 Dec 2015 17:14:42 -0500 +Subject: drm/dp/mst: process broadcast messages correctly + +From: Mykola Lysenko + +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 +Signed-off-by: Mykola Lysenko +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_dp_mst_topology.c | 95 ++++++++++++++++++++++++++++++---- + 1 file changed, 84 insertions(+), 11 deletions(-) + +--- a/drivers/gpu/drm/drm_dp_mst_topology.c ++++ b/drivers/gpu/drm/drm_dp_mst_topology.c +@@ -1210,6 +1210,50 @@ out: + return mstb; + } + ++static struct drm_dp_mst_branch *get_mst_branch_device_by_guid_helper( ++ struct drm_dp_mst_branch *mstb, ++ uint8_t *guid) ++{ ++ struct drm_dp_mst_branch *found_mstb; ++ struct drm_dp_mst_port *port; ++ ++ list_for_each_entry(port, &mstb->ports, next) { ++ if (!port->mstb) ++ continue; ++ ++ if (port->guid_valid && memcmp(port->guid, guid, 16) == 0) ++ return port->mstb; ++ ++ found_mstb = get_mst_branch_device_by_guid_helper(port->mstb, guid); ++ ++ if (found_mstb) ++ return found_mstb; ++ } ++ ++ return NULL; ++} ++ ++static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device_by_guid( ++ struct drm_dp_mst_topology_mgr *mgr, ++ uint8_t *guid) ++{ ++ struct drm_dp_mst_branch *mstb; ++ ++ /* find the port by iterating down */ ++ mutex_lock(&mgr->lock); ++ ++ if (mgr->guid_valid && memcmp(mgr->guid, guid, 16) == 0) ++ mstb = mgr->mst_primary; ++ else ++ mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid); ++ ++ if (mstb) ++ kref_get(&mstb->kref); ++ ++ mutex_unlock(&mgr->lock); ++ return mstb; ++} ++ + static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_branch *mstb) + { +@@ -1320,6 +1364,7 @@ static int set_hdr_from_dst_qlock(struct + struct drm_dp_sideband_msg_tx *txmsg) + { + struct drm_dp_mst_branch *mstb = txmsg->dst; ++ u8 req_type; + + /* both msg slots are full */ + if (txmsg->seqno == -1) { +@@ -1336,7 +1381,13 @@ static int set_hdr_from_dst_qlock(struct + txmsg->seqno = 1; + mstb->tx_slots[txmsg->seqno] = txmsg; + } +- hdr->broadcast = 0; ++ ++ req_type = txmsg->msg[0] & 0x7f; ++ if (req_type == DP_CONNECTION_STATUS_NOTIFY || ++ req_type == DP_RESOURCE_STATUS_NOTIFY) ++ hdr->broadcast = 1; ++ else ++ hdr->broadcast = 0; + hdr->path_msg = txmsg->path_msg; + hdr->lct = mstb->lct; + hdr->lcr = mstb->lct - 1; +@@ -2145,28 +2196,50 @@ static int drm_dp_mst_handle_up_req(stru + + if (mgr->up_req_recv.have_eomt) { + struct drm_dp_sideband_msg_req_body msg; +- struct drm_dp_mst_branch *mstb; ++ struct drm_dp_mst_branch *mstb = NULL; + bool seqno; +- mstb = drm_dp_get_mst_branch_device(mgr, +- mgr->up_req_recv.initial_hdr.lct, +- mgr->up_req_recv.initial_hdr.rad); +- if (!mstb) { +- DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct); +- memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx)); +- return 0; ++ ++ if (!mgr->up_req_recv.initial_hdr.broadcast) { ++ mstb = drm_dp_get_mst_branch_device(mgr, ++ mgr->up_req_recv.initial_hdr.lct, ++ mgr->up_req_recv.initial_hdr.rad); ++ if (!mstb) { ++ DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct); ++ memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx)); ++ return 0; ++ } + } + + seqno = mgr->up_req_recv.initial_hdr.seqno; + drm_dp_sideband_parse_req(&mgr->up_req_recv, &msg); + + if (msg.req_type == DP_CONNECTION_STATUS_NOTIFY) { +- drm_dp_send_up_ack_reply(mgr, mstb, msg.req_type, seqno, false); ++ drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false); ++ ++ if (!mstb) ++ mstb = drm_dp_get_mst_branch_device_by_guid(mgr, msg.u.conn_stat.guid); ++ ++ if (!mstb) { ++ DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct); ++ memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx)); ++ return 0; ++ } ++ + drm_dp_update_port(mstb, &msg.u.conn_stat); + DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type); + (*mgr->cbs->hotplug)(mgr); + + } else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) { +- drm_dp_send_up_ack_reply(mgr, mstb, msg.req_type, seqno, false); ++ drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false); ++ if (!mstb) ++ mstb = drm_dp_get_mst_branch_device_by_guid(mgr, msg.u.resource_stat.guid); ++ ++ if (!mstb) { ++ DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct); ++ memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx)); ++ return 0; ++ } ++ + DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n", msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn); + } + diff --git a/queue-4.4/drm-dp-mst-reverse-order-of-mst-enable-and-clearing-vc-payload-table.patch b/queue-4.4/drm-dp-mst-reverse-order-of-mst-enable-and-clearing-vc-payload-table.patch new file mode 100644 index 00000000000..a47960a6ea8 --- /dev/null +++ b/queue-4.4/drm-dp-mst-reverse-order-of-mst-enable-and-clearing-vc-payload-table.patch @@ -0,0 +1,50 @@ +From c175cd16df272119534058f28cbd5eeac6ff2d24 Mon Sep 17 00:00:00 2001 +From: Andrey Grodzovsky +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 + +commit c175cd16df272119534058f28cbd5eeac6ff2d24 upstream. + +On DELL U3014 if you clear the table before enabling MST it sometimes +hangs the receiver. + +Signed-off-by: Andrey Grodzovsky +Reviewed-by: Harry Wentland +Acked-by: Alex Deucher +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_dp_mst_topology.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/drm_dp_mst_topology.c ++++ b/drivers/gpu/drm/drm_dp_mst_topology.c +@@ -1976,6 +1976,12 @@ int drm_dp_mst_topology_mgr_set_mst(stru + mgr->mst_primary = mstb; + kref_get(&mgr->mst_primary->kref); + ++ ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL, ++ DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC); ++ if (ret < 0) { ++ goto out_unlock; ++ } ++ + { + struct drm_dp_payload reset_pay; + reset_pay.start_slot = 0; +@@ -1983,12 +1989,6 @@ int drm_dp_mst_topology_mgr_set_mst(stru + drm_dp_dpcd_write_payload(mgr, 0, &reset_pay); + } + +- ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL, +- DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC); +- if (ret < 0) { +- goto out_unlock; +- } +- + queue_work(system_long_wq, &mgr->work); + + ret = 0; diff --git a/queue-4.4/drm-nouveau-disp-dp-ensure-sink-is-powered-up-before-attempting-link-training.patch b/queue-4.4/drm-nouveau-disp-dp-ensure-sink-is-powered-up-before-attempting-link-training.patch new file mode 100644 index 00000000000..130b73ccc7d --- /dev/null +++ b/queue-4.4/drm-nouveau-disp-dp-ensure-sink-is-powered-up-before-attempting-link-training.patch @@ -0,0 +1,62 @@ +From 95664e66fad964c3dd7945d6edfb1d0931844664 Mon Sep 17 00:00:00 2001 +From: Ben Skeggs +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 + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c | 10 ++++++++++ + drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h | 6 ++++++ + 2 files changed, 16 insertions(+) + +--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c +@@ -328,6 +328,7 @@ nvkm_dp_train(struct work_struct *w) + .outp = outp, + }, *dp = &_dp; + u32 datarate = 0; ++ u8 pwr; + int ret; + + if (!outp->base.info.location && disp->func->sor.magic) +@@ -355,6 +356,15 @@ nvkm_dp_train(struct work_struct *w) + /* disable link interrupt handling during link training */ + nvkm_notify_put(&outp->irq); + ++ /* ensure sink is not in a low-power state */ ++ if (!nvkm_rdaux(outp->aux, DPCD_SC00, &pwr, 1)) { ++ if ((pwr & DPCD_SC00_SET_POWER) != DPCD_SC00_SET_POWER_D0) { ++ pwr &= ~DPCD_SC00_SET_POWER; ++ pwr |= DPCD_SC00_SET_POWER_D0; ++ nvkm_wraux(outp->aux, DPCD_SC00, &pwr, 1); ++ } ++ } ++ + /* enable down-spreading and execute pre-train script from vbios */ + dp_link_train_init(dp, outp->dpcd[3] & 0x01); + +--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h +@@ -71,5 +71,11 @@ + #define DPCD_LS0C_LANE1_POST_CURSOR2 0x0c + #define DPCD_LS0C_LANE0_POST_CURSOR2 0x03 + ++/* DPCD Sink Control */ ++#define DPCD_SC00 0x00600 ++#define DPCD_SC00_SET_POWER 0x03 ++#define DPCD_SC00_SET_POWER_D0 0x01 ++#define DPCD_SC00_SET_POWER_D3 0x03 ++ + void nvkm_dp_train(struct work_struct *); + #endif diff --git a/queue-4.4/drm-nouveau-display-enable-vblank-irqs-after-display-engine-is-on-again.patch b/queue-4.4/drm-nouveau-display-enable-vblank-irqs-after-display-engine-is-on-again.patch new file mode 100644 index 00000000000..fe71adb8ebc --- /dev/null +++ b/queue-4.4/drm-nouveau-display-enable-vblank-irqs-after-display-engine-is-on-again.patch @@ -0,0 +1,60 @@ +From ff683df7bf34f90766a50c7e7454e219aef2710e Mon Sep 17 00:00:00 2001 +From: Mario Kleiner +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 + +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 +Cc: Ben Skeggs +Cc: ville.syrjala@linux.intel.com +Cc: daniel.vetter@ffwll.ch +Cc: dri-devel@lists.freedesktop.org +Reviewed-by: Daniel Vetter +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nouveau_display.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/nouveau/nouveau_display.c ++++ b/drivers/gpu/drm/nouveau/nouveau_display.c +@@ -634,10 +634,6 @@ nouveau_display_resume(struct drm_device + nv_crtc->lut.depth = 0; + } + +- /* Make sure that drm and hw vblank irqs get resumed if needed. */ +- for (head = 0; head < dev->mode_config.num_crtc; head++) +- drm_vblank_on(dev, head); +- + /* This should ensure we don't hit a locking problem when someone + * wakes us up via a connector. We should never go into suspend + * while the display is on anyways. +@@ -647,6 +643,10 @@ nouveau_display_resume(struct drm_device + + drm_helper_resume_force_mode(dev); + ++ /* Make sure that drm and hw vblank irqs get resumed if needed. */ ++ for (head = 0; head < dev->mode_config.num_crtc; head++) ++ drm_vblank_on(dev, head); ++ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + diff --git a/queue-4.4/drm-nouveau-kms-take-mode_config-mutex-in-connector-hotplug-path.patch b/queue-4.4/drm-nouveau-kms-take-mode_config-mutex-in-connector-hotplug-path.patch new file mode 100644 index 00000000000..e10319e913a --- /dev/null +++ b/queue-4.4/drm-nouveau-kms-take-mode_config-mutex-in-connector-hotplug-path.patch @@ -0,0 +1,34 @@ +From 0a882cadbc63fd2da3994af7115b4ada2fcbd638 Mon Sep 17 00:00:00 2001 +From: Ben Skeggs +Date: Fri, 8 Jan 2016 08:56:51 +1000 +Subject: drm/nouveau/kms: take mode_config mutex in connector hotplug path + +From: Ben Skeggs + +commit 0a882cadbc63fd2da3994af7115b4ada2fcbd638 upstream. + +fdo#93634 + +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nouveau_connector.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/gpu/drm/nouveau/nouveau_connector.c ++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c +@@ -969,10 +969,13 @@ nouveau_connector_hotplug(struct nvif_no + + NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name); + ++ mutex_lock(&drm->dev->mode_config.mutex); + if (plugged) + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); + else + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); ++ mutex_unlock(&drm->dev->mode_config.mutex); ++ + drm_helper_hpd_irq_event(connector->dev); + } + diff --git a/queue-4.4/drm-nouveau-platform-fix-deferred-probe.patch b/queue-4.4/drm-nouveau-platform-fix-deferred-probe.patch new file mode 100644 index 00000000000..15f2d13447c --- /dev/null +++ b/queue-4.4/drm-nouveau-platform-fix-deferred-probe.patch @@ -0,0 +1,108 @@ +From 870571a5698b2e9d0f4d2e5c6245967b582aab45 Mon Sep 17 00:00:00 2001 +From: Thierry Reding +Date: Wed, 24 Feb 2016 18:34:43 +0100 +Subject: drm/nouveau: platform: Fix deferred probe + +From: Thierry Reding + +commit 870571a5698b2e9d0f4d2e5c6245967b582aab45 upstream. + +The error cleanup paths aren't quite correct and will crash upon +deferred probe. + +Reviewed-by: Ben Skeggs +Reviewed-by: Alexandre Courbot +Signed-off-by: Thierry Reding +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nouveau_platform.c | 2 - + drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c | 40 +++++++++++++++------ + 2 files changed, 30 insertions(+), 12 deletions(-) + +--- a/drivers/gpu/drm/nouveau/nouveau_platform.c ++++ b/drivers/gpu/drm/nouveau/nouveau_platform.c +@@ -24,7 +24,7 @@ + static int nouveau_platform_probe(struct platform_device *pdev) + { + const struct nvkm_device_tegra_func *func; +- struct nvkm_device *device; ++ struct nvkm_device *device = NULL; + struct drm_device *drm; + int ret; + +--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c +@@ -252,32 +252,40 @@ nvkm_device_tegra_new(const struct nvkm_ + + if (!(tdev = kzalloc(sizeof(*tdev), GFP_KERNEL))) + return -ENOMEM; +- *pdevice = &tdev->device; ++ + tdev->func = func; + tdev->pdev = pdev; + tdev->irq = -1; + + tdev->vdd = devm_regulator_get(&pdev->dev, "vdd"); +- if (IS_ERR(tdev->vdd)) +- return PTR_ERR(tdev->vdd); ++ if (IS_ERR(tdev->vdd)) { ++ ret = PTR_ERR(tdev->vdd); ++ goto free; ++ } + + tdev->rst = devm_reset_control_get(&pdev->dev, "gpu"); +- if (IS_ERR(tdev->rst)) +- return PTR_ERR(tdev->rst); ++ if (IS_ERR(tdev->rst)) { ++ ret = PTR_ERR(tdev->rst); ++ goto free; ++ } + + tdev->clk = devm_clk_get(&pdev->dev, "gpu"); +- if (IS_ERR(tdev->clk)) +- return PTR_ERR(tdev->clk); ++ if (IS_ERR(tdev->clk)) { ++ ret = PTR_ERR(tdev->clk); ++ goto free; ++ } + + tdev->clk_pwr = devm_clk_get(&pdev->dev, "pwr"); +- if (IS_ERR(tdev->clk_pwr)) +- return PTR_ERR(tdev->clk_pwr); ++ if (IS_ERR(tdev->clk_pwr)) { ++ ret = PTR_ERR(tdev->clk_pwr); ++ goto free; ++ } + + nvkm_device_tegra_probe_iommu(tdev); + + ret = nvkm_device_tegra_power_up(tdev); + if (ret) +- return ret; ++ goto remove; + + tdev->gpu_speedo = tegra_sku_info.gpu_speedo_value; + ret = nvkm_device_ctor(&nvkm_device_tegra_func, NULL, &pdev->dev, +@@ -285,9 +293,19 @@ nvkm_device_tegra_new(const struct nvkm_ + cfg, dbg, detect, mmio, subdev_mask, + &tdev->device); + if (ret) +- return ret; ++ goto powerdown; ++ ++ *pdevice = &tdev->device; + + return 0; ++ ++powerdown: ++ nvkm_device_tegra_power_down(tdev); ++remove: ++ nvkm_device_tegra_remove_iommu(tdev); ++free: ++ kfree(tdev); ++ return ret; + } + #else + int diff --git a/queue-4.4/drm-vmwgfx-fix-a-width-pitch-mismatch-on-framebuffer-updates.patch b/queue-4.4/drm-vmwgfx-fix-a-width-pitch-mismatch-on-framebuffer-updates.patch new file mode 100644 index 00000000000..b8452fc4b4b --- /dev/null +++ b/queue-4.4/drm-vmwgfx-fix-a-width-pitch-mismatch-on-framebuffer-updates.patch @@ -0,0 +1,65 @@ +From a50e2bf5a0f674d62b69f51f6935a30e82bd015c Mon Sep 17 00:00:00 2001 +From: Thomas Hellstrom +Date: Fri, 8 Jan 2016 20:29:40 +0100 +Subject: drm/vmwgfx: Fix a width / pitch mismatch on framebuffer updates + +From: Thomas Hellstrom + +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 +Tested-by: Mati Aharoni +Signed-off-by: Thomas Hellstrom +Reviewed-by: Brian Paul +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +@@ -763,21 +763,25 @@ static int vmw_create_dmabuf_proxy(struc + uint32_t format; + struct drm_vmw_size content_base_size; + struct vmw_resource *res; ++ unsigned int bytes_pp; + int ret; + + switch (mode_cmd->depth) { + case 32: + case 24: + format = SVGA3D_X8R8G8B8; ++ bytes_pp = 4; + break; + + case 16: + case 15: + format = SVGA3D_R5G6B5; ++ bytes_pp = 2; + break; + + case 8: + format = SVGA3D_P8; ++ bytes_pp = 1; + break; + + default: +@@ -785,7 +789,7 @@ static int vmw_create_dmabuf_proxy(struc + return -EINVAL; + } + +- content_base_size.width = mode_cmd->width; ++ content_base_size.width = mode_cmd->pitch / bytes_pp; + content_base_size.height = mode_cmd->height; + content_base_size.depth = 1; + diff --git a/queue-4.4/drm-vmwgfx-fix-an-incorrect-lock-check.patch b/queue-4.4/drm-vmwgfx-fix-an-incorrect-lock-check.patch new file mode 100644 index 00000000000..294963e615c --- /dev/null +++ b/queue-4.4/drm-vmwgfx-fix-an-incorrect-lock-check.patch @@ -0,0 +1,34 @@ +From fb89ac5102ae2875d685c847e6b5dbc141622d43 Mon Sep 17 00:00:00 2001 +From: Thomas Hellstrom +Date: Fri, 8 Jan 2016 20:29:39 +0100 +Subject: drm/vmwgfx: Fix an incorrect lock check + +From: Thomas Hellstrom + +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 +Signed-off-by: Thomas Hellstrom +Reviewed-by: Sinclair Yeh +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c +@@ -247,7 +247,7 @@ static void __vmw_cmdbuf_header_free(str + { + struct vmw_cmdbuf_man *man = header->man; + +- BUG_ON(!spin_is_locked(&man->lock)); ++ lockdep_assert_held_once(&man->lock); + + if (header->inline_space) { + vmw_cmdbuf_header_inline_free(header); diff --git a/queue-4.4/drm-vmwgfx-respect-nomodeset.patch b/queue-4.4/drm-vmwgfx-respect-nomodeset.patch new file mode 100644 index 00000000000..15356d551a1 --- /dev/null +++ b/queue-4.4/drm-vmwgfx-respect-nomodeset.patch @@ -0,0 +1,41 @@ +From 96c5d076f0a5e2023ecdb44d8261f87641ee71e0 Mon Sep 17 00:00:00 2001 +From: Rob Clark +Date: Wed, 15 Oct 2014 15:00:47 -0400 +Subject: drm/vmwgfx: respect 'nomodeset' + +From: Rob Clark + +commit 96c5d076f0a5e2023ecdb44d8261f87641ee71e0 upstream. + +Signed-off-by: Rob Clark +Reviewed-by: Thomas Hellstrom . +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + 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 ++#include + + #include + #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"); diff --git a/queue-4.4/series b/queue-4.4/series index bd231e03884..95bf492c5c5 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -163,3 +163,42 @@ cxl-use-correct-operator-when-writing-pcie-config-space-values.patch clk-exynos-use-irqsave-version-of-spin_lock-to-avoid-deadlock-with-irqs.patch regulator-axp20x-fix-gpio-ldo-enable-value-for-axp22x.patch regulator-mt6311-mt6311_regulator-needs-to-select-regmap_i2c.patch +virtio_balloon-fix-race-by-fill-and-leak.patch +virtio_balloon-fix-race-between-migration-and-ballooning.patch +virtio_pci-fix-use-after-free-on-release.patch +drm-vmwgfx-fix-an-incorrect-lock-check.patch +drm-vmwgfx-fix-a-width-pitch-mismatch-on-framebuffer-updates.patch +drm-vmwgfx-respect-nomodeset.patch +drm-amdgpu-fix-off-by-one-errors-in-amdgpu_vm_bo_map.patch +drm-amdgpu-call-hpd_irq_event-on-resume.patch +drm-amdgpu-fix-lost-sync_to-if-scheduler-is-enabled.patch +drm-amdgpu-fix-tonga-smu-resume.patch +drm-amdgpu-fix-amdgpu_bo_pin_restricted-vram-placing-v2.patch +drm-amdgpu-no-need-to-load-mc-firmware-on-fiji.patch +drm-amdgpu-move-gmc7-support-out-of-cik-dependency.patch +drm-amdgpu-iceland-use-ci-based-mc-ip.patch +drm-amdgpu-the-vi-specific-exe-bit-should-only-apply-to-gmc-v8.0-above.patch +drm-amdgpu-pull-topaz-gmc-bits-into-gmc_v7.patch +drm-amdgpu-drop-topaz-support-from-gmc8-module.patch +drm-amdgpu-don-t-load-mec2-on-topaz.patch +drm-amdgpu-remove-exp-hardware-support-from-iceland.patch +drm-amdgpu-fix-s4-resume.patch +drm-amdgpu-remove-unnecessary-forward-declaration.patch +drm-amdgpu-hold-reference-to-fences-in-amdgpu_sa_bo_new-v2.patch +drm-amdgpu-fix-issue-with-overlapping-userptrs.patch +drm-amdgpu-use-post-decrement-in-error-handling.patch +drm-amdgpu-don-t-hang-in-amdgpu_flip_work_func-on-disabled-crtc.patch +drm-amdgpu-pm-adjust-display-configuration-after-powerstate.patch +drm-nouveau-kms-take-mode_config-mutex-in-connector-hotplug-path.patch +drm-nouveau-display-enable-vblank-irqs-after-display-engine-is-on-again.patch +drm-nouveau-disp-dp-ensure-sink-is-powered-up-before-attempting-link-training.patch +drm-nouveau-platform-fix-deferred-probe.patch +drm-dp-mst-process-broadcast-messages-correctly.patch +drm-dp-mst-always-send-reply-for-up-request.patch +drm-dp-mst-fix-in-mstb-rad-initialization.patch +drm-dp-mst-fix-in-rad-element-access.patch +drm-add-drm_fixp_from_fraction-and-drm_fixp2int_ceil.patch +drm-dp-mst-calculate-mst-pbn-with-31.32-fixed-point.patch +drm-dp-mst-move-guid-storage-from-mgr-port-to-only-mst-branch.patch +drm-dp-mst-reverse-order-of-mst-enable-and-clearing-vc-payload-table.patch +drm-dp-mst-deallocate-payload-on-port-destruction.patch diff --git a/queue-4.4/virtio_balloon-fix-race-between-migration-and-ballooning.patch b/queue-4.4/virtio_balloon-fix-race-between-migration-and-ballooning.patch new file mode 100644 index 00000000000..3460d0a15e8 --- /dev/null +++ b/queue-4.4/virtio_balloon-fix-race-between-migration-and-ballooning.patch @@ -0,0 +1,91 @@ +From 21ea9fb69e7c4b1b1559c3e410943d3ff248ffcb Mon Sep 17 00:00:00 2001 +From: Minchan Kim +Date: Mon, 28 Dec 2015 08:35:13 +0900 +Subject: virtio_balloon: fix race between migration and ballooning + +From: Minchan Kim + +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:[] [] 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: + [] leak_balloon+0x93/0x1a0 + [] balloon+0x217/0x2a0 + [] ? __schedule+0x31e/0x8b0 + [] ? abort_exclusive_wait+0xb0/0xb0 + [] ? update_balloon_stats+0xf0/0xf0 + [] kthread+0xc9/0xe0 + [] ? kthread_park+0x60/0x60 + [] ret_from_fork+0x3f/0x70 + [] ? 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 [] balloon_page_dequeue+0x54/0x130 + RSP +---[ end trace 43cf28060d708d5f ]--- +Kernel panic - not syncing: Fatal exception +Dumping ftrace buffer: + (ftrace buffer empty) +Kernel Offset: disabled + +Signed-off-by: Minchan Kim +Signed-off-by: Michael S. Tsirkin +Acked-by: Rafael Aquini +Signed-off-by: Greg Kroah-Hartman + +--- + mm/balloon_compaction.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/mm/balloon_compaction.c ++++ b/mm/balloon_compaction.c +@@ -61,6 +61,7 @@ struct page *balloon_page_dequeue(struct + bool dequeued_page; + + dequeued_page = false; ++ spin_lock_irqsave(&b_dev_info->pages_lock, flags); + list_for_each_entry_safe(page, tmp, &b_dev_info->pages, lru) { + /* + * Block others from accessing the 'page' while we get around +@@ -75,15 +76,14 @@ struct page *balloon_page_dequeue(struct + continue; + } + #endif +- spin_lock_irqsave(&b_dev_info->pages_lock, flags); + balloon_page_delete(page); + __count_vm_event(BALLOON_DEFLATE); +- spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); + unlock_page(page); + dequeued_page = true; + break; + } + } ++ spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); + + if (!dequeued_page) { + /* diff --git a/queue-4.4/virtio_balloon-fix-race-by-fill-and-leak.patch b/queue-4.4/virtio_balloon-fix-race-by-fill-and-leak.patch new file mode 100644 index 00000000000..ea2d028cf94 --- /dev/null +++ b/queue-4.4/virtio_balloon-fix-race-by-fill-and-leak.patch @@ -0,0 +1,42 @@ +From f68b992bbb474641881932c61c92dcfa6f5b3689 Mon Sep 17 00:00:00 2001 +From: Minchan Kim +Date: Mon, 28 Dec 2015 08:35:12 +0900 +Subject: virtio_balloon: fix race by fill and leak + +From: Minchan Kim + +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 +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/virtio/virtio_balloon.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/virtio/virtio_balloon.c ++++ b/drivers/virtio/virtio_balloon.c +@@ -209,8 +209,8 @@ static unsigned leak_balloon(struct virt + */ + if (vb->num_pfns != 0) + tell_host(vb, vb->deflate_vq); +- mutex_unlock(&vb->balloon_lock); + release_pages_balloon(vb); ++ mutex_unlock(&vb->balloon_lock); + return num_freed_pages; + } + diff --git a/queue-4.4/virtio_pci-fix-use-after-free-on-release.patch b/queue-4.4/virtio_pci-fix-use-after-free-on-release.patch new file mode 100644 index 00000000000..581ea2b49ad --- /dev/null +++ b/queue-4.4/virtio_pci-fix-use-after-free-on-release.patch @@ -0,0 +1,45 @@ +From 2989be09a8a9d62a785137586ad941f916e08f83 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +Date: Thu, 14 Jan 2016 16:00:41 +0200 +Subject: virtio_pci: fix use after free on release + +From: Michael S. Tsirkin + +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 +Cc: Sasha Levin +Signed-off-by: Michael S. Tsirkin +Tested-by: Jerome Marchand +Signed-off-by: Greg Kroah-Hartman + +--- + 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 = { -- 2.47.3