diff options
author | Dave Airlie <airlied@gmail.com> | 2015-12-05 01:15:38 -0500 |
---|---|---|
committer | Dave Airlie <airlied@gmail.com> | 2015-12-05 01:15:38 -0500 |
commit | df4d4aa96d1db1657e14b848a341fc614c8d61eb (patch) | |
tree | 2adc46d577b369551e4f94252b48f07d9e7f6dd7 /drivers/gpu/drm/amd/amdgpu | |
parent | bbc8764f80eb872d2b36302882ddfc9882de4b16 (diff) | |
parent | 8e36f9d33c134d5c6448ad65b423a9fd94e045cf (diff) |
Merge branch 'drm-fixes-4.4' of git://people.freedesktop.org/~agd5f/linux into drm-next
A few more last minute fixes for 4.4 on top of my pull request from
earlier this week. The big change here is a vblank regression fix due to
commit 4dfd6486 "drm: Use vblank timestamps to guesstimate how many vblanks
were missed". Beyond that, a hotplug fix and a few VM fixes.
* 'drm-fixes-4.4' of git://people.freedesktop.org/~agd5f/linux:
drm/amdgpu: Fixup hw vblank counter/ts for new drm_update_vblank_count() (v3)
drm/radeon: Fixup hw vblank counter/ts for new drm_update_vblank_count() (v2)
drm/radeon: Retry DDC probing on DVI on failure if we got an HPD interrupt
drm/amdgpu: add spin lock to protect freed list in vm (v2)
drm/amdgpu: partially revert "drm/amdgpu: fix VM_CONTEXT*_PAGE_TABLE_END_ADDR" v2
drm/amdgpu: take a BO reference for the user fence
drm/amdgpu: take a BO reference in the display code
drm/amdgpu: set snooped flags only on system addresses v2
drm/amdgpu: fix race condition in amd_sched_entity_push_job
drm/amdgpu: add err check for pin userptr
add blacklist for thinkpad T40p
drm/amdgpu: fix VM page table reference counting
drm/amdgpu: fix userptr flags check
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 108 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 48 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 2 |
14 files changed, 185 insertions, 48 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 251b14736de9..5a5f04d0902d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h | |||
@@ -539,6 +539,7 @@ struct amdgpu_bo { | |||
539 | /* Constant after initialization */ | 539 | /* Constant after initialization */ |
540 | struct amdgpu_device *adev; | 540 | struct amdgpu_device *adev; |
541 | struct drm_gem_object gem_base; | 541 | struct drm_gem_object gem_base; |
542 | struct amdgpu_bo *parent; | ||
542 | 543 | ||
543 | struct ttm_bo_kmap_obj dma_buf_vmap; | 544 | struct ttm_bo_kmap_obj dma_buf_vmap; |
544 | pid_t pid; | 545 | pid_t pid; |
@@ -955,6 +956,8 @@ struct amdgpu_vm { | |||
955 | struct amdgpu_vm_id ids[AMDGPU_MAX_RINGS]; | 956 | struct amdgpu_vm_id ids[AMDGPU_MAX_RINGS]; |
956 | /* for interval tree */ | 957 | /* for interval tree */ |
957 | spinlock_t it_lock; | 958 | spinlock_t it_lock; |
959 | /* protecting freed */ | ||
960 | spinlock_t freed_lock; | ||
958 | }; | 961 | }; |
959 | 962 | ||
960 | struct amdgpu_vm_manager { | 963 | struct amdgpu_vm_manager { |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 1d44d508d4d4..4f352ec9dec4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | |||
@@ -222,6 +222,8 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) | |||
222 | } | 222 | } |
223 | 223 | ||
224 | p->uf.bo = gem_to_amdgpu_bo(gobj); | 224 | p->uf.bo = gem_to_amdgpu_bo(gobj); |
225 | amdgpu_bo_ref(p->uf.bo); | ||
226 | drm_gem_object_unreference_unlocked(gobj); | ||
225 | p->uf.offset = fence_data->offset; | 227 | p->uf.offset = fence_data->offset; |
226 | } else { | 228 | } else { |
227 | ret = -EINVAL; | 229 | ret = -EINVAL; |
@@ -487,7 +489,7 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo | |||
487 | amdgpu_ib_free(parser->adev, &parser->ibs[i]); | 489 | amdgpu_ib_free(parser->adev, &parser->ibs[i]); |
488 | kfree(parser->ibs); | 490 | kfree(parser->ibs); |
489 | if (parser->uf.bo) | 491 | if (parser->uf.bo) |
490 | drm_gem_object_unreference_unlocked(&parser->uf.bo->gem_base); | 492 | amdgpu_bo_unref(&parser->uf.bo); |
491 | } | 493 | } |
492 | 494 | ||
493 | static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p, | 495 | static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p, |
@@ -776,7 +778,7 @@ static int amdgpu_cs_free_job(struct amdgpu_job *job) | |||
776 | amdgpu_ib_free(job->adev, &job->ibs[i]); | 778 | amdgpu_ib_free(job->adev, &job->ibs[i]); |
777 | kfree(job->ibs); | 779 | kfree(job->ibs); |
778 | if (job->uf.bo) | 780 | if (job->uf.bo) |
779 | drm_gem_object_unreference_unlocked(&job->uf.bo->gem_base); | 781 | amdgpu_bo_unref(&job->uf.bo); |
780 | return 0; | 782 | return 0; |
781 | } | 783 | } |
782 | 784 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index e173a5a02f0d..5580d3420c3a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | |||
@@ -73,6 +73,8 @@ static void amdgpu_flip_work_func(struct work_struct *__work) | |||
73 | struct drm_crtc *crtc = &amdgpuCrtc->base; | 73 | struct drm_crtc *crtc = &amdgpuCrtc->base; |
74 | unsigned long flags; | 74 | unsigned long flags; |
75 | unsigned i; | 75 | unsigned i; |
76 | int vpos, hpos, stat, min_udelay; | ||
77 | struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id]; | ||
76 | 78 | ||
77 | amdgpu_flip_wait_fence(adev, &work->excl); | 79 | amdgpu_flip_wait_fence(adev, &work->excl); |
78 | for (i = 0; i < work->shared_count; ++i) | 80 | for (i = 0; i < work->shared_count; ++i) |
@@ -81,6 +83,41 @@ static void amdgpu_flip_work_func(struct work_struct *__work) | |||
81 | /* We borrow the event spin lock for protecting flip_status */ | 83 | /* We borrow the event spin lock for protecting flip_status */ |
82 | spin_lock_irqsave(&crtc->dev->event_lock, flags); | 84 | spin_lock_irqsave(&crtc->dev->event_lock, flags); |
83 | 85 | ||
86 | /* If this happens to execute within the "virtually extended" vblank | ||
87 | * interval before the start of the real vblank interval then it needs | ||
88 | * to delay programming the mmio flip until the real vblank is entered. | ||
89 | * This prevents completing a flip too early due to the way we fudge | ||
90 | * our vblank counter and vblank timestamps in order to work around the | ||
91 | * problem that the hw fires vblank interrupts before actual start of | ||
92 | * vblank (when line buffer refilling is done for a frame). It | ||
93 | * complements the fudging logic in amdgpu_get_crtc_scanoutpos() for | ||
94 | * timestamping and amdgpu_get_vblank_counter_kms() for vblank counts. | ||
95 | * | ||
96 | * In practice this won't execute very often unless on very fast | ||
97 | * machines because the time window for this to happen is very small. | ||
98 | */ | ||
99 | for (;;) { | ||
100 | /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank | ||
101 | * start in hpos, and to the "fudged earlier" vblank start in | ||
102 | * vpos. | ||
103 | */ | ||
104 | stat = amdgpu_get_crtc_scanoutpos(adev->ddev, work->crtc_id, | ||
105 | GET_DISTANCE_TO_VBLANKSTART, | ||
106 | &vpos, &hpos, NULL, NULL, | ||
107 | &crtc->hwmode); | ||
108 | |||
109 | if ((stat & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE)) != | ||
110 | (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE) || | ||
111 | !(vpos >= 0 && hpos <= 0)) | ||
112 | break; | ||
113 | |||
114 | /* Sleep at least until estimated real start of hw vblank */ | ||
115 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); | ||
116 | min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5); | ||
117 | usleep_range(min_udelay, 2 * min_udelay); | ||
118 | spin_lock_irqsave(&crtc->dev->event_lock, flags); | ||
119 | }; | ||
120 | |||
84 | /* do the flip (mmio) */ | 121 | /* do the flip (mmio) */ |
85 | adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base); | 122 | adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base); |
86 | /* set the flip status */ | 123 | /* set the flip status */ |
@@ -109,7 +146,7 @@ static void amdgpu_unpin_work_func(struct work_struct *__work) | |||
109 | } else | 146 | } else |
110 | DRM_ERROR("failed to reserve buffer after flip\n"); | 147 | DRM_ERROR("failed to reserve buffer after flip\n"); |
111 | 148 | ||
112 | drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base); | 149 | amdgpu_bo_unref(&work->old_rbo); |
113 | kfree(work->shared); | 150 | kfree(work->shared); |
114 | kfree(work); | 151 | kfree(work); |
115 | } | 152 | } |
@@ -148,8 +185,8 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc, | |||
148 | obj = old_amdgpu_fb->obj; | 185 | obj = old_amdgpu_fb->obj; |
149 | 186 | ||
150 | /* take a reference to the old object */ | 187 | /* take a reference to the old object */ |
151 | drm_gem_object_reference(obj); | ||
152 | work->old_rbo = gem_to_amdgpu_bo(obj); | 188 | work->old_rbo = gem_to_amdgpu_bo(obj); |
189 | amdgpu_bo_ref(work->old_rbo); | ||
153 | 190 | ||
154 | new_amdgpu_fb = to_amdgpu_framebuffer(fb); | 191 | new_amdgpu_fb = to_amdgpu_framebuffer(fb); |
155 | obj = new_amdgpu_fb->obj; | 192 | obj = new_amdgpu_fb->obj; |
@@ -222,7 +259,7 @@ pflip_cleanup: | |||
222 | amdgpu_bo_unreserve(new_rbo); | 259 | amdgpu_bo_unreserve(new_rbo); |
223 | 260 | ||
224 | cleanup: | 261 | cleanup: |
225 | drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base); | 262 | amdgpu_bo_unref(&work->old_rbo); |
226 | fence_put(work->excl); | 263 | fence_put(work->excl); |
227 | for (i = 0; i < work->shared_count; ++i) | 264 | for (i = 0; i < work->shared_count; ++i) |
228 | fence_put(work->shared[i]); | 265 | fence_put(work->shared[i]); |
@@ -712,6 +749,15 @@ bool amdgpu_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | |||
712 | * \param dev Device to query. | 749 | * \param dev Device to query. |
713 | * \param pipe Crtc to query. | 750 | * \param pipe Crtc to query. |
714 | * \param flags Flags from caller (DRM_CALLED_FROM_VBLIRQ or 0). | 751 | * \param flags Flags from caller (DRM_CALLED_FROM_VBLIRQ or 0). |
752 | * For driver internal use only also supports these flags: | ||
753 | * | ||
754 | * USE_REAL_VBLANKSTART to use the real start of vblank instead | ||
755 | * of a fudged earlier start of vblank. | ||
756 | * | ||
757 | * GET_DISTANCE_TO_VBLANKSTART to return distance to the | ||
758 | * fudged earlier start of vblank in *vpos and the distance | ||
759 | * to true start of vblank in *hpos. | ||
760 | * | ||
715 | * \param *vpos Location where vertical scanout position should be stored. | 761 | * \param *vpos Location where vertical scanout position should be stored. |
716 | * \param *hpos Location where horizontal scanout position should go. | 762 | * \param *hpos Location where horizontal scanout position should go. |
717 | * \param *stime Target location for timestamp taken immediately before | 763 | * \param *stime Target location for timestamp taken immediately before |
@@ -776,10 +822,40 @@ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, | |||
776 | vbl_end = 0; | 822 | vbl_end = 0; |
777 | } | 823 | } |
778 | 824 | ||
825 | /* Called from driver internal vblank counter query code? */ | ||
826 | if (flags & GET_DISTANCE_TO_VBLANKSTART) { | ||
827 | /* Caller wants distance from real vbl_start in *hpos */ | ||
828 | *hpos = *vpos - vbl_start; | ||
829 | } | ||
830 | |||
831 | /* Fudge vblank to start a few scanlines earlier to handle the | ||
832 | * problem that vblank irqs fire a few scanlines before start | ||
833 | * of vblank. Some driver internal callers need the true vblank | ||
834 | * start to be used and signal this via the USE_REAL_VBLANKSTART flag. | ||
835 | * | ||
836 | * The cause of the "early" vblank irq is that the irq is triggered | ||
837 | * by the line buffer logic when the line buffer read position enters | ||
838 | * the vblank, whereas our crtc scanout position naturally lags the | ||
839 | * line buffer read position. | ||
840 | */ | ||
841 | if (!(flags & USE_REAL_VBLANKSTART)) | ||
842 | vbl_start -= adev->mode_info.crtcs[pipe]->lb_vblank_lead_lines; | ||
843 | |||
779 | /* Test scanout position against vblank region. */ | 844 | /* Test scanout position against vblank region. */ |
780 | if ((*vpos < vbl_start) && (*vpos >= vbl_end)) | 845 | if ((*vpos < vbl_start) && (*vpos >= vbl_end)) |
781 | in_vbl = false; | 846 | in_vbl = false; |
782 | 847 | ||
848 | /* In vblank? */ | ||
849 | if (in_vbl) | ||
850 | ret |= DRM_SCANOUTPOS_IN_VBLANK; | ||
851 | |||
852 | /* Called from driver internal vblank counter query code? */ | ||
853 | if (flags & GET_DISTANCE_TO_VBLANKSTART) { | ||
854 | /* Caller wants distance from fudged earlier vbl_start */ | ||
855 | *vpos -= vbl_start; | ||
856 | return ret; | ||
857 | } | ||
858 | |||
783 | /* Check if inside vblank area and apply corrective offsets: | 859 | /* Check if inside vblank area and apply corrective offsets: |
784 | * vpos will then be >=0 in video scanout area, but negative | 860 | * vpos will then be >=0 in video scanout area, but negative |
785 | * within vblank area, counting down the number of lines until | 861 | * within vblank area, counting down the number of lines until |
@@ -795,32 +871,6 @@ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, | |||
795 | /* Correct for shifted end of vbl at vbl_end. */ | 871 | /* Correct for shifted end of vbl at vbl_end. */ |
796 | *vpos = *vpos - vbl_end; | 872 | *vpos = *vpos - vbl_end; |
797 | 873 | ||
798 | /* In vblank? */ | ||
799 | if (in_vbl) | ||
800 | ret |= DRM_SCANOUTPOS_IN_VBLANK; | ||
801 | |||
802 | /* Is vpos outside nominal vblank area, but less than | ||
803 | * 1/100 of a frame height away from start of vblank? | ||
804 | * If so, assume this isn't a massively delayed vblank | ||
805 | * interrupt, but a vblank interrupt that fired a few | ||
806 | * microseconds before true start of vblank. Compensate | ||
807 | * by adding a full frame duration to the final timestamp. | ||
808 | * Happens, e.g., on ATI R500, R600. | ||
809 | * | ||
810 | * We only do this if DRM_CALLED_FROM_VBLIRQ. | ||
811 | */ | ||
812 | if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) { | ||
813 | vbl_start = mode->crtc_vdisplay; | ||
814 | vtotal = mode->crtc_vtotal; | ||
815 | |||
816 | if (vbl_start - *vpos < vtotal / 100) { | ||
817 | *vpos -= vtotal; | ||
818 | |||
819 | /* Signal this correction as "applied". */ | ||
820 | ret |= 0x8; | ||
821 | } | ||
822 | } | ||
823 | |||
824 | return ret; | 874 | return ret; |
825 | } | 875 | } |
826 | 876 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index fc32fc01a64b..f6ea4b43a60c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | |||
@@ -235,8 +235,9 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data, | |||
235 | AMDGPU_GEM_USERPTR_REGISTER)) | 235 | AMDGPU_GEM_USERPTR_REGISTER)) |
236 | return -EINVAL; | 236 | return -EINVAL; |
237 | 237 | ||
238 | if (!(args->flags & AMDGPU_GEM_USERPTR_ANONONLY) || | 238 | if (!(args->flags & AMDGPU_GEM_USERPTR_READONLY) && ( |
239 | !(args->flags & AMDGPU_GEM_USERPTR_REGISTER)) { | 239 | !(args->flags & AMDGPU_GEM_USERPTR_ANONONLY) || |
240 | !(args->flags & AMDGPU_GEM_USERPTR_REGISTER))) { | ||
240 | 241 | ||
241 | /* if we want to write to it we must require anonymous | 242 | /* if we want to write to it we must require anonymous |
242 | memory and install a MMU notifier */ | 243 | memory and install a MMU notifier */ |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 1618e2294a16..e23843f4d877 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | |||
@@ -611,13 +611,59 @@ void amdgpu_driver_preclose_kms(struct drm_device *dev, | |||
611 | u32 amdgpu_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe) | 611 | u32 amdgpu_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe) |
612 | { | 612 | { |
613 | struct amdgpu_device *adev = dev->dev_private; | 613 | struct amdgpu_device *adev = dev->dev_private; |
614 | int vpos, hpos, stat; | ||
615 | u32 count; | ||
614 | 616 | ||
615 | if (pipe >= adev->mode_info.num_crtc) { | 617 | if (pipe >= adev->mode_info.num_crtc) { |
616 | DRM_ERROR("Invalid crtc %u\n", pipe); | 618 | DRM_ERROR("Invalid crtc %u\n", pipe); |
617 | return -EINVAL; | 619 | return -EINVAL; |
618 | } | 620 | } |
619 | 621 | ||
620 | return amdgpu_display_vblank_get_counter(adev, pipe); | 622 | /* The hw increments its frame counter at start of vsync, not at start |
623 | * of vblank, as is required by DRM core vblank counter handling. | ||
624 | * Cook the hw count here to make it appear to the caller as if it | ||
625 | * incremented at start of vblank. We measure distance to start of | ||
626 | * vblank in vpos. vpos therefore will be >= 0 between start of vblank | ||
627 | * and start of vsync, so vpos >= 0 means to bump the hw frame counter | ||
628 | * result by 1 to give the proper appearance to caller. | ||
629 | */ | ||
630 | if (adev->mode_info.crtcs[pipe]) { | ||
631 | /* Repeat readout if needed to provide stable result if | ||
632 | * we cross start of vsync during the queries. | ||
633 | */ | ||
634 | do { | ||
635 | count = amdgpu_display_vblank_get_counter(adev, pipe); | ||
636 | /* Ask amdgpu_get_crtc_scanoutpos to return vpos as | ||
637 | * distance to start of vblank, instead of regular | ||
638 | * vertical scanout pos. | ||
639 | */ | ||
640 | stat = amdgpu_get_crtc_scanoutpos( | ||
641 | dev, pipe, GET_DISTANCE_TO_VBLANKSTART, | ||
642 | &vpos, &hpos, NULL, NULL, | ||
643 | &adev->mode_info.crtcs[pipe]->base.hwmode); | ||
644 | } while (count != amdgpu_display_vblank_get_counter(adev, pipe)); | ||
645 | |||
646 | if (((stat & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE)) != | ||
647 | (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE))) { | ||
648 | DRM_DEBUG_VBL("Query failed! stat %d\n", stat); | ||
649 | } else { | ||
650 | DRM_DEBUG_VBL("crtc %d: dist from vblank start %d\n", | ||
651 | pipe, vpos); | ||
652 | |||
653 | /* Bump counter if we are at >= leading edge of vblank, | ||
654 | * but before vsync where vpos would turn negative and | ||
655 | * the hw counter really increments. | ||
656 | */ | ||
657 | if (vpos >= 0) | ||
658 | count++; | ||
659 | } | ||
660 | } else { | ||
661 | /* Fallback to use value as is. */ | ||
662 | count = amdgpu_display_vblank_get_counter(adev, pipe); | ||
663 | DRM_DEBUG_VBL("NULL mode info! Returned count may be wrong.\n"); | ||
664 | } | ||
665 | |||
666 | return count; | ||
621 | } | 667 | } |
622 | 668 | ||
623 | /** | 669 | /** |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index b62c1710cab6..064ebb347074 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | |||
@@ -407,6 +407,7 @@ struct amdgpu_crtc { | |||
407 | u32 line_time; | 407 | u32 line_time; |
408 | u32 wm_low; | 408 | u32 wm_low; |
409 | u32 wm_high; | 409 | u32 wm_high; |
410 | u32 lb_vblank_lead_lines; | ||
410 | struct drm_display_mode hw_mode; | 411 | struct drm_display_mode hw_mode; |
411 | }; | 412 | }; |
412 | 413 | ||
@@ -528,6 +529,10 @@ struct amdgpu_framebuffer { | |||
528 | #define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \ | 529 | #define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \ |
529 | ((em) == ATOM_ENCODER_MODE_DP_MST)) | 530 | ((em) == ATOM_ENCODER_MODE_DP_MST)) |
530 | 531 | ||
532 | /* Driver internal use only flags of amdgpu_get_crtc_scanoutpos() */ | ||
533 | #define USE_REAL_VBLANKSTART (1 << 30) | ||
534 | #define GET_DISTANCE_TO_VBLANKSTART (1 << 31) | ||
535 | |||
531 | void amdgpu_link_encoder_connector(struct drm_device *dev); | 536 | void amdgpu_link_encoder_connector(struct drm_device *dev); |
532 | 537 | ||
533 | struct drm_connector * | 538 | struct drm_connector * |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 0d524384ff79..c3ce103b6a33 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | |||
@@ -100,6 +100,7 @@ static void amdgpu_ttm_bo_destroy(struct ttm_buffer_object *tbo) | |||
100 | list_del_init(&bo->list); | 100 | list_del_init(&bo->list); |
101 | mutex_unlock(&bo->adev->gem.mutex); | 101 | mutex_unlock(&bo->adev->gem.mutex); |
102 | drm_gem_object_release(&bo->gem_base); | 102 | drm_gem_object_release(&bo->gem_base); |
103 | amdgpu_bo_unref(&bo->parent); | ||
103 | kfree(bo->metadata); | 104 | kfree(bo->metadata); |
104 | kfree(bo); | 105 | kfree(bo); |
105 | } | 106 | } |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index d4bac5f49939..8a1752ff3d8e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | |||
@@ -587,9 +587,13 @@ static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, | |||
587 | uint32_t flags = amdgpu_ttm_tt_pte_flags(gtt->adev, ttm, bo_mem); | 587 | uint32_t flags = amdgpu_ttm_tt_pte_flags(gtt->adev, ttm, bo_mem); |
588 | int r; | 588 | int r; |
589 | 589 | ||
590 | if (gtt->userptr) | 590 | if (gtt->userptr) { |
591 | amdgpu_ttm_tt_pin_userptr(ttm); | 591 | r = amdgpu_ttm_tt_pin_userptr(ttm); |
592 | 592 | if (r) { | |
593 | DRM_ERROR("failed to pin userptr\n"); | ||
594 | return r; | ||
595 | } | ||
596 | } | ||
593 | gtt->offset = (unsigned long)(bo_mem->start << PAGE_SHIFT); | 597 | gtt->offset = (unsigned long)(bo_mem->start << PAGE_SHIFT); |
594 | if (!ttm->num_pages) { | 598 | if (!ttm->num_pages) { |
595 | WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n", | 599 | WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n", |
@@ -797,11 +801,12 @@ uint32_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, | |||
797 | if (mem && mem->mem_type != TTM_PL_SYSTEM) | 801 | if (mem && mem->mem_type != TTM_PL_SYSTEM) |
798 | flags |= AMDGPU_PTE_VALID; | 802 | flags |= AMDGPU_PTE_VALID; |
799 | 803 | ||
800 | if (mem && mem->mem_type == TTM_PL_TT) | 804 | if (mem && mem->mem_type == TTM_PL_TT) { |
801 | flags |= AMDGPU_PTE_SYSTEM; | 805 | flags |= AMDGPU_PTE_SYSTEM; |
802 | 806 | ||
803 | if (!ttm || ttm->caching_state == tt_cached) | 807 | if (ttm->caching_state == tt_cached) |
804 | flags |= AMDGPU_PTE_SNOOPED; | 808 | flags |= AMDGPU_PTE_SNOOPED; |
809 | } | ||
805 | 810 | ||
806 | if (adev->asic_type >= CHIP_TOPAZ) | 811 | if (adev->asic_type >= CHIP_TOPAZ) |
807 | flags |= AMDGPU_PTE_EXECUTABLE; | 812 | flags |= AMDGPU_PTE_EXECUTABLE; |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index ae037e5b6ad0..b53d273eb7a1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |||
@@ -885,17 +885,21 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev, | |||
885 | struct amdgpu_bo_va_mapping *mapping; | 885 | struct amdgpu_bo_va_mapping *mapping; |
886 | int r; | 886 | int r; |
887 | 887 | ||
888 | spin_lock(&vm->freed_lock); | ||
888 | while (!list_empty(&vm->freed)) { | 889 | while (!list_empty(&vm->freed)) { |
889 | mapping = list_first_entry(&vm->freed, | 890 | mapping = list_first_entry(&vm->freed, |
890 | struct amdgpu_bo_va_mapping, list); | 891 | struct amdgpu_bo_va_mapping, list); |
891 | list_del(&mapping->list); | 892 | list_del(&mapping->list); |
892 | 893 | spin_unlock(&vm->freed_lock); | |
893 | r = amdgpu_vm_bo_update_mapping(adev, vm, mapping, 0, 0, NULL); | 894 | r = amdgpu_vm_bo_update_mapping(adev, vm, mapping, 0, 0, NULL); |
894 | kfree(mapping); | 895 | kfree(mapping); |
895 | if (r) | 896 | if (r) |
896 | return r; | 897 | return r; |
897 | 898 | ||
899 | spin_lock(&vm->freed_lock); | ||
898 | } | 900 | } |
901 | spin_unlock(&vm->freed_lock); | ||
902 | |||
899 | return 0; | 903 | return 0; |
900 | 904 | ||
901 | } | 905 | } |
@@ -1079,6 +1083,11 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, | |||
1079 | if (r) | 1083 | if (r) |
1080 | goto error_free; | 1084 | goto error_free; |
1081 | 1085 | ||
1086 | /* Keep a reference to the page table to avoid freeing | ||
1087 | * them up in the wrong order. | ||
1088 | */ | ||
1089 | pt->parent = amdgpu_bo_ref(vm->page_directory); | ||
1090 | |||
1082 | r = amdgpu_vm_clear_bo(adev, pt); | 1091 | r = amdgpu_vm_clear_bo(adev, pt); |
1083 | if (r) { | 1092 | if (r) { |
1084 | amdgpu_bo_unref(&pt); | 1093 | amdgpu_bo_unref(&pt); |
@@ -1150,10 +1159,13 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev, | |||
1150 | spin_unlock(&vm->it_lock); | 1159 | spin_unlock(&vm->it_lock); |
1151 | trace_amdgpu_vm_bo_unmap(bo_va, mapping); | 1160 | trace_amdgpu_vm_bo_unmap(bo_va, mapping); |
1152 | 1161 | ||
1153 | if (valid) | 1162 | if (valid) { |
1163 | spin_lock(&vm->freed_lock); | ||
1154 | list_add(&mapping->list, &vm->freed); | 1164 | list_add(&mapping->list, &vm->freed); |
1155 | else | 1165 | spin_unlock(&vm->freed_lock); |
1166 | } else { | ||
1156 | kfree(mapping); | 1167 | kfree(mapping); |
1168 | } | ||
1157 | 1169 | ||
1158 | return 0; | 1170 | return 0; |
1159 | } | 1171 | } |
@@ -1186,7 +1198,9 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, | |||
1186 | interval_tree_remove(&mapping->it, &vm->va); | 1198 | interval_tree_remove(&mapping->it, &vm->va); |
1187 | spin_unlock(&vm->it_lock); | 1199 | spin_unlock(&vm->it_lock); |
1188 | trace_amdgpu_vm_bo_unmap(bo_va, mapping); | 1200 | trace_amdgpu_vm_bo_unmap(bo_va, mapping); |
1201 | spin_lock(&vm->freed_lock); | ||
1189 | list_add(&mapping->list, &vm->freed); | 1202 | list_add(&mapping->list, &vm->freed); |
1203 | spin_unlock(&vm->freed_lock); | ||
1190 | } | 1204 | } |
1191 | list_for_each_entry_safe(mapping, next, &bo_va->invalids, list) { | 1205 | list_for_each_entry_safe(mapping, next, &bo_va->invalids, list) { |
1192 | list_del(&mapping->list); | 1206 | list_del(&mapping->list); |
@@ -1247,6 +1261,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm) | |||
1247 | INIT_LIST_HEAD(&vm->cleared); | 1261 | INIT_LIST_HEAD(&vm->cleared); |
1248 | INIT_LIST_HEAD(&vm->freed); | 1262 | INIT_LIST_HEAD(&vm->freed); |
1249 | spin_lock_init(&vm->it_lock); | 1263 | spin_lock_init(&vm->it_lock); |
1264 | spin_lock_init(&vm->freed_lock); | ||
1250 | pd_size = amdgpu_vm_directory_size(adev); | 1265 | pd_size = amdgpu_vm_directory_size(adev); |
1251 | pd_entries = amdgpu_vm_num_pdes(adev); | 1266 | pd_entries = amdgpu_vm_num_pdes(adev); |
1252 | 1267 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index cb0f7747e3dc..4dcc8fba5792 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | |||
@@ -1250,7 +1250,7 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev, | |||
1250 | u32 pixel_period; | 1250 | u32 pixel_period; |
1251 | u32 line_time = 0; | 1251 | u32 line_time = 0; |
1252 | u32 latency_watermark_a = 0, latency_watermark_b = 0; | 1252 | u32 latency_watermark_a = 0, latency_watermark_b = 0; |
1253 | u32 tmp, wm_mask; | 1253 | u32 tmp, wm_mask, lb_vblank_lead_lines = 0; |
1254 | 1254 | ||
1255 | if (amdgpu_crtc->base.enabled && num_heads && mode) { | 1255 | if (amdgpu_crtc->base.enabled && num_heads && mode) { |
1256 | pixel_period = 1000000 / (u32)mode->clock; | 1256 | pixel_period = 1000000 / (u32)mode->clock; |
@@ -1333,6 +1333,7 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev, | |||
1333 | (adev->mode_info.disp_priority == 2)) { | 1333 | (adev->mode_info.disp_priority == 2)) { |
1334 | DRM_DEBUG_KMS("force priority to high\n"); | 1334 | DRM_DEBUG_KMS("force priority to high\n"); |
1335 | } | 1335 | } |
1336 | lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode->crtc_hdisplay); | ||
1336 | } | 1337 | } |
1337 | 1338 | ||
1338 | /* select wm A */ | 1339 | /* select wm A */ |
@@ -1357,6 +1358,8 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev, | |||
1357 | amdgpu_crtc->line_time = line_time; | 1358 | amdgpu_crtc->line_time = line_time; |
1358 | amdgpu_crtc->wm_high = latency_watermark_a; | 1359 | amdgpu_crtc->wm_high = latency_watermark_a; |
1359 | amdgpu_crtc->wm_low = latency_watermark_b; | 1360 | amdgpu_crtc->wm_low = latency_watermark_b; |
1361 | /* Save number of lines the linebuffer leads before the scanout */ | ||
1362 | amdgpu_crtc->lb_vblank_lead_lines = lb_vblank_lead_lines; | ||
1360 | } | 1363 | } |
1361 | 1364 | ||
1362 | /** | 1365 | /** |
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 5af3721851d6..8f1e51128b33 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | |||
@@ -1238,7 +1238,7 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev, | |||
1238 | u32 pixel_period; | 1238 | u32 pixel_period; |
1239 | u32 line_time = 0; | 1239 | u32 line_time = 0; |
1240 | u32 latency_watermark_a = 0, latency_watermark_b = 0; | 1240 | u32 latency_watermark_a = 0, latency_watermark_b = 0; |
1241 | u32 tmp, wm_mask; | 1241 | u32 tmp, wm_mask, lb_vblank_lead_lines = 0; |
1242 | 1242 | ||
1243 | if (amdgpu_crtc->base.enabled && num_heads && mode) { | 1243 | if (amdgpu_crtc->base.enabled && num_heads && mode) { |
1244 | pixel_period = 1000000 / (u32)mode->clock; | 1244 | pixel_period = 1000000 / (u32)mode->clock; |
@@ -1321,6 +1321,7 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev, | |||
1321 | (adev->mode_info.disp_priority == 2)) { | 1321 | (adev->mode_info.disp_priority == 2)) { |
1322 | DRM_DEBUG_KMS("force priority to high\n"); | 1322 | DRM_DEBUG_KMS("force priority to high\n"); |
1323 | } | 1323 | } |
1324 | lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode->crtc_hdisplay); | ||
1324 | } | 1325 | } |
1325 | 1326 | ||
1326 | /* select wm A */ | 1327 | /* select wm A */ |
@@ -1345,6 +1346,8 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev, | |||
1345 | amdgpu_crtc->line_time = line_time; | 1346 | amdgpu_crtc->line_time = line_time; |
1346 | amdgpu_crtc->wm_high = latency_watermark_a; | 1347 | amdgpu_crtc->wm_high = latency_watermark_a; |
1347 | amdgpu_crtc->wm_low = latency_watermark_b; | 1348 | amdgpu_crtc->wm_low = latency_watermark_b; |
1349 | /* Save number of lines the linebuffer leads before the scanout */ | ||
1350 | amdgpu_crtc->lb_vblank_lead_lines = lb_vblank_lead_lines; | ||
1348 | } | 1351 | } |
1349 | 1352 | ||
1350 | /** | 1353 | /** |
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index 4f7b49a6dc50..42d954dc436d 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | |||
@@ -1193,7 +1193,7 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev, | |||
1193 | u32 pixel_period; | 1193 | u32 pixel_period; |
1194 | u32 line_time = 0; | 1194 | u32 line_time = 0; |
1195 | u32 latency_watermark_a = 0, latency_watermark_b = 0; | 1195 | u32 latency_watermark_a = 0, latency_watermark_b = 0; |
1196 | u32 tmp, wm_mask; | 1196 | u32 tmp, wm_mask, lb_vblank_lead_lines = 0; |
1197 | 1197 | ||
1198 | if (amdgpu_crtc->base.enabled && num_heads && mode) { | 1198 | if (amdgpu_crtc->base.enabled && num_heads && mode) { |
1199 | pixel_period = 1000000 / (u32)mode->clock; | 1199 | pixel_period = 1000000 / (u32)mode->clock; |
@@ -1276,6 +1276,7 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev, | |||
1276 | (adev->mode_info.disp_priority == 2)) { | 1276 | (adev->mode_info.disp_priority == 2)) { |
1277 | DRM_DEBUG_KMS("force priority to high\n"); | 1277 | DRM_DEBUG_KMS("force priority to high\n"); |
1278 | } | 1278 | } |
1279 | lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode->crtc_hdisplay); | ||
1279 | } | 1280 | } |
1280 | 1281 | ||
1281 | /* select wm A */ | 1282 | /* select wm A */ |
@@ -1302,6 +1303,8 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev, | |||
1302 | amdgpu_crtc->line_time = line_time; | 1303 | amdgpu_crtc->line_time = line_time; |
1303 | amdgpu_crtc->wm_high = latency_watermark_a; | 1304 | amdgpu_crtc->wm_high = latency_watermark_a; |
1304 | amdgpu_crtc->wm_low = latency_watermark_b; | 1305 | amdgpu_crtc->wm_low = latency_watermark_b; |
1306 | /* Save number of lines the linebuffer leads before the scanout */ | ||
1307 | amdgpu_crtc->lb_vblank_lead_lines = lb_vblank_lead_lines; | ||
1305 | } | 1308 | } |
1306 | 1309 | ||
1307 | /** | 1310 | /** |
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 7427d8cd4c43..ed8abb58a785 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | |||
@@ -513,7 +513,7 @@ static int gmc_v7_0_gart_enable(struct amdgpu_device *adev) | |||
513 | WREG32(mmVM_L2_CNTL3, tmp); | 513 | WREG32(mmVM_L2_CNTL3, tmp); |
514 | /* setup context0 */ | 514 | /* setup context0 */ |
515 | WREG32(mmVM_CONTEXT0_PAGE_TABLE_START_ADDR, adev->mc.gtt_start >> 12); | 515 | WREG32(mmVM_CONTEXT0_PAGE_TABLE_START_ADDR, adev->mc.gtt_start >> 12); |
516 | WREG32(mmVM_CONTEXT0_PAGE_TABLE_END_ADDR, (adev->mc.gtt_end >> 12) - 1); | 516 | WREG32(mmVM_CONTEXT0_PAGE_TABLE_END_ADDR, adev->mc.gtt_end >> 12); |
517 | WREG32(mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR, adev->gart.table_addr >> 12); | 517 | WREG32(mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR, adev->gart.table_addr >> 12); |
518 | WREG32(mmVM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, | 518 | WREG32(mmVM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, |
519 | (u32)(adev->dummy_page.addr >> 12)); | 519 | (u32)(adev->dummy_page.addr >> 12)); |
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index cb0e50ebb528..d39028440814 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | |||
@@ -657,7 +657,7 @@ static int gmc_v8_0_gart_enable(struct amdgpu_device *adev) | |||
657 | WREG32(mmVM_L2_CNTL4, tmp); | 657 | WREG32(mmVM_L2_CNTL4, tmp); |
658 | /* setup context0 */ | 658 | /* setup context0 */ |
659 | WREG32(mmVM_CONTEXT0_PAGE_TABLE_START_ADDR, adev->mc.gtt_start >> 12); | 659 | WREG32(mmVM_CONTEXT0_PAGE_TABLE_START_ADDR, adev->mc.gtt_start >> 12); |
660 | WREG32(mmVM_CONTEXT0_PAGE_TABLE_END_ADDR, (adev->mc.gtt_end >> 12) - 1); | 660 | WREG32(mmVM_CONTEXT0_PAGE_TABLE_END_ADDR, adev->mc.gtt_end >> 12); |
661 | WREG32(mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR, adev->gart.table_addr >> 12); | 661 | WREG32(mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR, adev->gart.table_addr >> 12); |
662 | WREG32(mmVM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, | 662 | WREG32(mmVM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, |
663 | (u32)(adev->dummy_page.addr >> 12)); | 663 | (u32)(adev->dummy_page.addr >> 12)); |