diff options
Diffstat (limited to 'drivers/gpu')
30 files changed, 387 insertions, 91 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)); |
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c index 651129f2ec1d..3a4820e863ec 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c | |||
@@ -288,6 +288,7 @@ amd_sched_entity_pop_job(struct amd_sched_entity *entity) | |||
288 | */ | 288 | */ |
289 | static bool amd_sched_entity_in(struct amd_sched_job *sched_job) | 289 | static bool amd_sched_entity_in(struct amd_sched_job *sched_job) |
290 | { | 290 | { |
291 | struct amd_gpu_scheduler *sched = sched_job->sched; | ||
291 | struct amd_sched_entity *entity = sched_job->s_entity; | 292 | struct amd_sched_entity *entity = sched_job->s_entity; |
292 | bool added, first = false; | 293 | bool added, first = false; |
293 | 294 | ||
@@ -302,7 +303,7 @@ static bool amd_sched_entity_in(struct amd_sched_job *sched_job) | |||
302 | 303 | ||
303 | /* first job wakes up scheduler */ | 304 | /* first job wakes up scheduler */ |
304 | if (first) | 305 | if (first) |
305 | amd_sched_wakeup(sched_job->sched); | 306 | amd_sched_wakeup(sched); |
306 | 307 | ||
307 | return added; | 308 | return added; |
308 | } | 309 | } |
@@ -318,9 +319,9 @@ void amd_sched_entity_push_job(struct amd_sched_job *sched_job) | |||
318 | { | 319 | { |
319 | struct amd_sched_entity *entity = sched_job->s_entity; | 320 | struct amd_sched_entity *entity = sched_job->s_entity; |
320 | 321 | ||
322 | trace_amd_sched_job(sched_job); | ||
321 | wait_event(entity->sched->job_scheduled, | 323 | wait_event(entity->sched->job_scheduled, |
322 | amd_sched_entity_in(sched_job)); | 324 | amd_sched_entity_in(sched_job)); |
323 | trace_amd_sched_job(sched_job); | ||
324 | } | 325 | } |
325 | 326 | ||
326 | /** | 327 | /** |
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 248953d2fdb7..0154db43860c 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c | |||
@@ -8472,7 +8472,7 @@ restart_ih: | |||
8472 | if (queue_dp) | 8472 | if (queue_dp) |
8473 | schedule_work(&rdev->dp_work); | 8473 | schedule_work(&rdev->dp_work); |
8474 | if (queue_hotplug) | 8474 | if (queue_hotplug) |
8475 | schedule_work(&rdev->hotplug_work); | 8475 | schedule_delayed_work(&rdev->hotplug_work, 0); |
8476 | if (queue_reset) { | 8476 | if (queue_reset) { |
8477 | rdev->needs_reset = true; | 8477 | rdev->needs_reset = true; |
8478 | wake_up_all(&rdev->fence_queue); | 8478 | wake_up_all(&rdev->fence_queue); |
@@ -9630,6 +9630,9 @@ static void dce8_program_watermarks(struct radeon_device *rdev, | |||
9630 | (rdev->disp_priority == 2)) { | 9630 | (rdev->disp_priority == 2)) { |
9631 | DRM_DEBUG_KMS("force priority to high\n"); | 9631 | DRM_DEBUG_KMS("force priority to high\n"); |
9632 | } | 9632 | } |
9633 | |||
9634 | /* Save number of lines the linebuffer leads before the scanout */ | ||
9635 | radeon_crtc->lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode->crtc_hdisplay); | ||
9633 | } | 9636 | } |
9634 | 9637 | ||
9635 | /* select wm A */ | 9638 | /* select wm A */ |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 7f33767d7ed6..2ad462896896 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -2372,6 +2372,9 @@ static void evergreen_program_watermarks(struct radeon_device *rdev, | |||
2372 | c.full = dfixed_div(c, a); | 2372 | c.full = dfixed_div(c, a); |
2373 | priority_b_mark = dfixed_trunc(c); | 2373 | priority_b_mark = dfixed_trunc(c); |
2374 | priority_b_cnt |= priority_b_mark & PRIORITY_MARK_MASK; | 2374 | priority_b_cnt |= priority_b_mark & PRIORITY_MARK_MASK; |
2375 | |||
2376 | /* Save number of lines the linebuffer leads before the scanout */ | ||
2377 | radeon_crtc->lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode->crtc_hdisplay); | ||
2375 | } | 2378 | } |
2376 | 2379 | ||
2377 | /* select wm A */ | 2380 | /* select wm A */ |
@@ -5344,7 +5347,7 @@ restart_ih: | |||
5344 | if (queue_dp) | 5347 | if (queue_dp) |
5345 | schedule_work(&rdev->dp_work); | 5348 | schedule_work(&rdev->dp_work); |
5346 | if (queue_hotplug) | 5349 | if (queue_hotplug) |
5347 | schedule_work(&rdev->hotplug_work); | 5350 | schedule_delayed_work(&rdev->hotplug_work, 0); |
5348 | if (queue_hdmi) | 5351 | if (queue_hdmi) |
5349 | schedule_work(&rdev->audio_work); | 5352 | schedule_work(&rdev->audio_work); |
5350 | if (queue_thermal && rdev->pm.dpm_enabled) | 5353 | if (queue_thermal && rdev->pm.dpm_enabled) |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 238b13f045c1..9e7e2bf03b81 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
@@ -806,7 +806,7 @@ int r100_irq_process(struct radeon_device *rdev) | |||
806 | status = r100_irq_ack(rdev); | 806 | status = r100_irq_ack(rdev); |
807 | } | 807 | } |
808 | if (queue_hotplug) | 808 | if (queue_hotplug) |
809 | schedule_work(&rdev->hotplug_work); | 809 | schedule_delayed_work(&rdev->hotplug_work, 0); |
810 | if (rdev->msi_enabled) { | 810 | if (rdev->msi_enabled) { |
811 | switch (rdev->family) { | 811 | switch (rdev->family) { |
812 | case CHIP_RS400: | 812 | case CHIP_RS400: |
@@ -3217,6 +3217,9 @@ void r100_bandwidth_update(struct radeon_device *rdev) | |||
3217 | uint32_t pixel_bytes1 = 0; | 3217 | uint32_t pixel_bytes1 = 0; |
3218 | uint32_t pixel_bytes2 = 0; | 3218 | uint32_t pixel_bytes2 = 0; |
3219 | 3219 | ||
3220 | /* Guess line buffer size to be 8192 pixels */ | ||
3221 | u32 lb_size = 8192; | ||
3222 | |||
3220 | if (!rdev->mode_info.mode_config_initialized) | 3223 | if (!rdev->mode_info.mode_config_initialized) |
3221 | return; | 3224 | return; |
3222 | 3225 | ||
@@ -3631,6 +3634,13 @@ void r100_bandwidth_update(struct radeon_device *rdev) | |||
3631 | DRM_DEBUG_KMS("GRPH2_BUFFER_CNTL from to %x\n", | 3634 | DRM_DEBUG_KMS("GRPH2_BUFFER_CNTL from to %x\n", |
3632 | (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL)); | 3635 | (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL)); |
3633 | } | 3636 | } |
3637 | |||
3638 | /* Save number of lines the linebuffer leads before the scanout */ | ||
3639 | if (mode1) | ||
3640 | rdev->mode_info.crtcs[0]->lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode1->crtc_hdisplay); | ||
3641 | |||
3642 | if (mode2) | ||
3643 | rdev->mode_info.crtcs[1]->lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode2->crtc_hdisplay); | ||
3634 | } | 3644 | } |
3635 | 3645 | ||
3636 | int r100_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) | 3646 | int r100_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 4ea5b10ff5f4..cc2fdf0be37a 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -4276,7 +4276,7 @@ restart_ih: | |||
4276 | WREG32(IH_RB_RPTR, rptr); | 4276 | WREG32(IH_RB_RPTR, rptr); |
4277 | } | 4277 | } |
4278 | if (queue_hotplug) | 4278 | if (queue_hotplug) |
4279 | schedule_work(&rdev->hotplug_work); | 4279 | schedule_delayed_work(&rdev->hotplug_work, 0); |
4280 | if (queue_hdmi) | 4280 | if (queue_hdmi) |
4281 | schedule_work(&rdev->audio_work); | 4281 | schedule_work(&rdev->audio_work); |
4282 | if (queue_thermal && rdev->pm.dpm_enabled) | 4282 | if (queue_thermal && rdev->pm.dpm_enabled) |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index b6cbd816537e..87db64983ea8 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -2414,7 +2414,7 @@ struct radeon_device { | |||
2414 | struct r600_ih ih; /* r6/700 interrupt ring */ | 2414 | struct r600_ih ih; /* r6/700 interrupt ring */ |
2415 | struct radeon_rlc rlc; | 2415 | struct radeon_rlc rlc; |
2416 | struct radeon_mec mec; | 2416 | struct radeon_mec mec; |
2417 | struct work_struct hotplug_work; | 2417 | struct delayed_work hotplug_work; |
2418 | struct work_struct dp_work; | 2418 | struct work_struct dp_work; |
2419 | struct work_struct audio_work; | 2419 | struct work_struct audio_work; |
2420 | int num_crtc; /* number of crtcs */ | 2420 | int num_crtc; /* number of crtcs */ |
diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c index fe994aac3b04..c77d349c561c 100644 --- a/drivers/gpu/drm/radeon/radeon_agp.c +++ b/drivers/gpu/drm/radeon/radeon_agp.c | |||
@@ -54,6 +54,9 @@ static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = { | |||
54 | /* Intel 82855PM host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (lp #195051) */ | 54 | /* Intel 82855PM host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (lp #195051) */ |
55 | { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4e50, | 55 | { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4e50, |
56 | PCI_VENDOR_ID_IBM, 0x0550, 1}, | 56 | PCI_VENDOR_ID_IBM, 0x0550, 1}, |
57 | /* Intel 82855PM host bridge / RV250/M9 GL [Mobility FireGL 9000/Radeon 9000] needs AGPMode 1 (Thinkpad T40p) */ | ||
58 | { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c66, | ||
59 | PCI_VENDOR_ID_IBM, 0x054d, 1}, | ||
57 | /* Intel 82855PM host bridge / Mobility M7 needs AGPMode 1 */ | 60 | /* Intel 82855PM host bridge / Mobility M7 needs AGPMode 1 */ |
58 | { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c57, | 61 | { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c57, |
59 | PCI_VENDOR_ID_IBM, 0x0530, 1}, | 62 | PCI_VENDOR_ID_IBM, 0x0530, 1}, |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 5a2cafb4f1bc..340f3f549f29 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
@@ -1234,13 +1234,32 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) | |||
1234 | if (r < 0) | 1234 | if (r < 0) |
1235 | return connector_status_disconnected; | 1235 | return connector_status_disconnected; |
1236 | 1236 | ||
1237 | if (radeon_connector->detected_hpd_without_ddc) { | ||
1238 | force = true; | ||
1239 | radeon_connector->detected_hpd_without_ddc = false; | ||
1240 | } | ||
1241 | |||
1237 | if (!force && radeon_check_hpd_status_unchanged(connector)) { | 1242 | if (!force && radeon_check_hpd_status_unchanged(connector)) { |
1238 | ret = connector->status; | 1243 | ret = connector->status; |
1239 | goto exit; | 1244 | goto exit; |
1240 | } | 1245 | } |
1241 | 1246 | ||
1242 | if (radeon_connector->ddc_bus) | 1247 | if (radeon_connector->ddc_bus) { |
1243 | dret = radeon_ddc_probe(radeon_connector, false); | 1248 | dret = radeon_ddc_probe(radeon_connector, false); |
1249 | |||
1250 | /* Sometimes the pins required for the DDC probe on DVI | ||
1251 | * connectors don't make contact at the same time that the ones | ||
1252 | * for HPD do. If the DDC probe fails even though we had an HPD | ||
1253 | * signal, try again later */ | ||
1254 | if (!dret && !force && | ||
1255 | connector->status != connector_status_connected) { | ||
1256 | DRM_DEBUG_KMS("hpd detected without ddc, retrying in 1 second\n"); | ||
1257 | radeon_connector->detected_hpd_without_ddc = true; | ||
1258 | schedule_delayed_work(&rdev->hotplug_work, | ||
1259 | msecs_to_jiffies(1000)); | ||
1260 | goto exit; | ||
1261 | } | ||
1262 | } | ||
1244 | if (dret) { | 1263 | if (dret) { |
1245 | radeon_connector->detected_by_load = false; | 1264 | radeon_connector->detected_by_load = false; |
1246 | radeon_connector_free_edid(connector); | 1265 | radeon_connector_free_edid(connector); |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index a8d9927ed9eb..1eca0acac016 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -322,7 +322,9 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) | |||
322 | * to complete in this vblank? | 322 | * to complete in this vblank? |
323 | */ | 323 | */ |
324 | if (update_pending && | 324 | if (update_pending && |
325 | (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, 0, | 325 | (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, |
326 | crtc_id, | ||
327 | USE_REAL_VBLANKSTART, | ||
326 | &vpos, &hpos, NULL, NULL, | 328 | &vpos, &hpos, NULL, NULL, |
327 | &rdev->mode_info.crtcs[crtc_id]->base.hwmode)) && | 329 | &rdev->mode_info.crtcs[crtc_id]->base.hwmode)) && |
328 | ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) || | 330 | ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) || |
@@ -401,6 +403,8 @@ static void radeon_flip_work_func(struct work_struct *__work) | |||
401 | struct drm_crtc *crtc = &radeon_crtc->base; | 403 | struct drm_crtc *crtc = &radeon_crtc->base; |
402 | unsigned long flags; | 404 | unsigned long flags; |
403 | int r; | 405 | int r; |
406 | int vpos, hpos, stat, min_udelay; | ||
407 | struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id]; | ||
404 | 408 | ||
405 | down_read(&rdev->exclusive_lock); | 409 | down_read(&rdev->exclusive_lock); |
406 | if (work->fence) { | 410 | if (work->fence) { |
@@ -437,6 +441,41 @@ static void radeon_flip_work_func(struct work_struct *__work) | |||
437 | /* set the proper interrupt */ | 441 | /* set the proper interrupt */ |
438 | radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id); | 442 | radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id); |
439 | 443 | ||
444 | /* If this happens to execute within the "virtually extended" vblank | ||
445 | * interval before the start of the real vblank interval then it needs | ||
446 | * to delay programming the mmio flip until the real vblank is entered. | ||
447 | * This prevents completing a flip too early due to the way we fudge | ||
448 | * our vblank counter and vblank timestamps in order to work around the | ||
449 | * problem that the hw fires vblank interrupts before actual start of | ||
450 | * vblank (when line buffer refilling is done for a frame). It | ||
451 | * complements the fudging logic in radeon_get_crtc_scanoutpos() for | ||
452 | * timestamping and radeon_get_vblank_counter_kms() for vblank counts. | ||
453 | * | ||
454 | * In practice this won't execute very often unless on very fast | ||
455 | * machines because the time window for this to happen is very small. | ||
456 | */ | ||
457 | for (;;) { | ||
458 | /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank | ||
459 | * start in hpos, and to the "fudged earlier" vblank start in | ||
460 | * vpos. | ||
461 | */ | ||
462 | stat = radeon_get_crtc_scanoutpos(rdev->ddev, work->crtc_id, | ||
463 | GET_DISTANCE_TO_VBLANKSTART, | ||
464 | &vpos, &hpos, NULL, NULL, | ||
465 | &crtc->hwmode); | ||
466 | |||
467 | if ((stat & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE)) != | ||
468 | (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE) || | ||
469 | !(vpos >= 0 && hpos <= 0)) | ||
470 | break; | ||
471 | |||
472 | /* Sleep at least until estimated real start of hw vblank */ | ||
473 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); | ||
474 | min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5); | ||
475 | usleep_range(min_udelay, 2 * min_udelay); | ||
476 | spin_lock_irqsave(&crtc->dev->event_lock, flags); | ||
477 | }; | ||
478 | |||
440 | /* do the flip (mmio) */ | 479 | /* do the flip (mmio) */ |
441 | radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base); | 480 | radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base); |
442 | 481 | ||
@@ -1768,6 +1807,15 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | |||
1768 | * \param dev Device to query. | 1807 | * \param dev Device to query. |
1769 | * \param crtc Crtc to query. | 1808 | * \param crtc Crtc to query. |
1770 | * \param flags Flags from caller (DRM_CALLED_FROM_VBLIRQ or 0). | 1809 | * \param flags Flags from caller (DRM_CALLED_FROM_VBLIRQ or 0). |
1810 | * For driver internal use only also supports these flags: | ||
1811 | * | ||
1812 | * USE_REAL_VBLANKSTART to use the real start of vblank instead | ||
1813 | * of a fudged earlier start of vblank. | ||
1814 | * | ||
1815 | * GET_DISTANCE_TO_VBLANKSTART to return distance to the | ||
1816 | * fudged earlier start of vblank in *vpos and the distance | ||
1817 | * to true start of vblank in *hpos. | ||
1818 | * | ||
1771 | * \param *vpos Location where vertical scanout position should be stored. | 1819 | * \param *vpos Location where vertical scanout position should be stored. |
1772 | * \param *hpos Location where horizontal scanout position should go. | 1820 | * \param *hpos Location where horizontal scanout position should go. |
1773 | * \param *stime Target location for timestamp taken immediately before | 1821 | * \param *stime Target location for timestamp taken immediately before |
@@ -1911,10 +1959,40 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, | |||
1911 | vbl_end = 0; | 1959 | vbl_end = 0; |
1912 | } | 1960 | } |
1913 | 1961 | ||
1962 | /* Called from driver internal vblank counter query code? */ | ||
1963 | if (flags & GET_DISTANCE_TO_VBLANKSTART) { | ||
1964 | /* Caller wants distance from real vbl_start in *hpos */ | ||
1965 | *hpos = *vpos - vbl_start; | ||
1966 | } | ||
1967 | |||
1968 | /* Fudge vblank to start a few scanlines earlier to handle the | ||
1969 | * problem that vblank irqs fire a few scanlines before start | ||
1970 | * of vblank. Some driver internal callers need the true vblank | ||
1971 | * start to be used and signal this via the USE_REAL_VBLANKSTART flag. | ||
1972 | * | ||
1973 | * The cause of the "early" vblank irq is that the irq is triggered | ||
1974 | * by the line buffer logic when the line buffer read position enters | ||
1975 | * the vblank, whereas our crtc scanout position naturally lags the | ||
1976 | * line buffer read position. | ||
1977 | */ | ||
1978 | if (!(flags & USE_REAL_VBLANKSTART)) | ||
1979 | vbl_start -= rdev->mode_info.crtcs[pipe]->lb_vblank_lead_lines; | ||
1980 | |||
1914 | /* Test scanout position against vblank region. */ | 1981 | /* Test scanout position against vblank region. */ |
1915 | if ((*vpos < vbl_start) && (*vpos >= vbl_end)) | 1982 | if ((*vpos < vbl_start) && (*vpos >= vbl_end)) |
1916 | in_vbl = false; | 1983 | in_vbl = false; |
1917 | 1984 | ||
1985 | /* In vblank? */ | ||
1986 | if (in_vbl) | ||
1987 | ret |= DRM_SCANOUTPOS_IN_VBLANK; | ||
1988 | |||
1989 | /* Called from driver internal vblank counter query code? */ | ||
1990 | if (flags & GET_DISTANCE_TO_VBLANKSTART) { | ||
1991 | /* Caller wants distance from fudged earlier vbl_start */ | ||
1992 | *vpos -= vbl_start; | ||
1993 | return ret; | ||
1994 | } | ||
1995 | |||
1918 | /* Check if inside vblank area and apply corrective offsets: | 1996 | /* Check if inside vblank area and apply corrective offsets: |
1919 | * vpos will then be >=0 in video scanout area, but negative | 1997 | * vpos will then be >=0 in video scanout area, but negative |
1920 | * within vblank area, counting down the number of lines until | 1998 | * within vblank area, counting down the number of lines until |
@@ -1930,31 +2008,5 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, | |||
1930 | /* Correct for shifted end of vbl at vbl_end. */ | 2008 | /* Correct for shifted end of vbl at vbl_end. */ |
1931 | *vpos = *vpos - vbl_end; | 2009 | *vpos = *vpos - vbl_end; |
1932 | 2010 | ||
1933 | /* In vblank? */ | ||
1934 | if (in_vbl) | ||
1935 | ret |= DRM_SCANOUTPOS_IN_VBLANK; | ||
1936 | |||
1937 | /* Is vpos outside nominal vblank area, but less than | ||
1938 | * 1/100 of a frame height away from start of vblank? | ||
1939 | * If so, assume this isn't a massively delayed vblank | ||
1940 | * interrupt, but a vblank interrupt that fired a few | ||
1941 | * microseconds before true start of vblank. Compensate | ||
1942 | * by adding a full frame duration to the final timestamp. | ||
1943 | * Happens, e.g., on ATI R500, R600. | ||
1944 | * | ||
1945 | * We only do this if DRM_CALLED_FROM_VBLIRQ. | ||
1946 | */ | ||
1947 | if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) { | ||
1948 | vbl_start = mode->crtc_vdisplay; | ||
1949 | vtotal = mode->crtc_vtotal; | ||
1950 | |||
1951 | if (vbl_start - *vpos < vtotal / 100) { | ||
1952 | *vpos -= vtotal; | ||
1953 | |||
1954 | /* Signal this correction as "applied". */ | ||
1955 | ret |= 0x8; | ||
1956 | } | ||
1957 | } | ||
1958 | |||
1959 | return ret; | 2011 | return ret; |
1960 | } | 2012 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 171d3e43c30c..979f3bf65f2c 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c | |||
@@ -74,7 +74,7 @@ irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg) | |||
74 | static void radeon_hotplug_work_func(struct work_struct *work) | 74 | static void radeon_hotplug_work_func(struct work_struct *work) |
75 | { | 75 | { |
76 | struct radeon_device *rdev = container_of(work, struct radeon_device, | 76 | struct radeon_device *rdev = container_of(work, struct radeon_device, |
77 | hotplug_work); | 77 | hotplug_work.work); |
78 | struct drm_device *dev = rdev->ddev; | 78 | struct drm_device *dev = rdev->ddev; |
79 | struct drm_mode_config *mode_config = &dev->mode_config; | 79 | struct drm_mode_config *mode_config = &dev->mode_config; |
80 | struct drm_connector *connector; | 80 | struct drm_connector *connector; |
@@ -302,7 +302,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev) | |||
302 | } | 302 | } |
303 | } | 303 | } |
304 | 304 | ||
305 | INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func); | 305 | INIT_DELAYED_WORK(&rdev->hotplug_work, radeon_hotplug_work_func); |
306 | INIT_WORK(&rdev->dp_work, radeon_dp_work_func); | 306 | INIT_WORK(&rdev->dp_work, radeon_dp_work_func); |
307 | INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi); | 307 | INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi); |
308 | 308 | ||
@@ -310,7 +310,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev) | |||
310 | r = drm_irq_install(rdev->ddev, rdev->ddev->pdev->irq); | 310 | r = drm_irq_install(rdev->ddev, rdev->ddev->pdev->irq); |
311 | if (r) { | 311 | if (r) { |
312 | rdev->irq.installed = false; | 312 | rdev->irq.installed = false; |
313 | flush_work(&rdev->hotplug_work); | 313 | flush_delayed_work(&rdev->hotplug_work); |
314 | return r; | 314 | return r; |
315 | } | 315 | } |
316 | 316 | ||
@@ -333,7 +333,7 @@ void radeon_irq_kms_fini(struct radeon_device *rdev) | |||
333 | rdev->irq.installed = false; | 333 | rdev->irq.installed = false; |
334 | if (rdev->msi_enabled) | 334 | if (rdev->msi_enabled) |
335 | pci_disable_msi(rdev->pdev); | 335 | pci_disable_msi(rdev->pdev); |
336 | flush_work(&rdev->hotplug_work); | 336 | flush_delayed_work(&rdev->hotplug_work); |
337 | } | 337 | } |
338 | } | 338 | } |
339 | 339 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 0ec6fcca16d3..d290a8a09036 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c | |||
@@ -755,6 +755,8 @@ void radeon_driver_preclose_kms(struct drm_device *dev, | |||
755 | */ | 755 | */ |
756 | u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) | 756 | u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) |
757 | { | 757 | { |
758 | int vpos, hpos, stat; | ||
759 | u32 count; | ||
758 | struct radeon_device *rdev = dev->dev_private; | 760 | struct radeon_device *rdev = dev->dev_private; |
759 | 761 | ||
760 | if (crtc < 0 || crtc >= rdev->num_crtc) { | 762 | if (crtc < 0 || crtc >= rdev->num_crtc) { |
@@ -762,7 +764,53 @@ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) | |||
762 | return -EINVAL; | 764 | return -EINVAL; |
763 | } | 765 | } |
764 | 766 | ||
765 | return radeon_get_vblank_counter(rdev, crtc); | 767 | /* The hw increments its frame counter at start of vsync, not at start |
768 | * of vblank, as is required by DRM core vblank counter handling. | ||
769 | * Cook the hw count here to make it appear to the caller as if it | ||
770 | * incremented at start of vblank. We measure distance to start of | ||
771 | * vblank in vpos. vpos therefore will be >= 0 between start of vblank | ||
772 | * and start of vsync, so vpos >= 0 means to bump the hw frame counter | ||
773 | * result by 1 to give the proper appearance to caller. | ||
774 | */ | ||
775 | if (rdev->mode_info.crtcs[crtc]) { | ||
776 | /* Repeat readout if needed to provide stable result if | ||
777 | * we cross start of vsync during the queries. | ||
778 | */ | ||
779 | do { | ||
780 | count = radeon_get_vblank_counter(rdev, crtc); | ||
781 | /* Ask radeon_get_crtc_scanoutpos to return vpos as | ||
782 | * distance to start of vblank, instead of regular | ||
783 | * vertical scanout pos. | ||
784 | */ | ||
785 | stat = radeon_get_crtc_scanoutpos( | ||
786 | dev, crtc, GET_DISTANCE_TO_VBLANKSTART, | ||
787 | &vpos, &hpos, NULL, NULL, | ||
788 | &rdev->mode_info.crtcs[crtc]->base.hwmode); | ||
789 | } while (count != radeon_get_vblank_counter(rdev, crtc)); | ||
790 | |||
791 | if (((stat & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE)) != | ||
792 | (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE))) { | ||
793 | DRM_DEBUG_VBL("Query failed! stat %d\n", stat); | ||
794 | } | ||
795 | else { | ||
796 | DRM_DEBUG_VBL("crtc %d: dist from vblank start %d\n", | ||
797 | crtc, vpos); | ||
798 | |||
799 | /* Bump counter if we are at >= leading edge of vblank, | ||
800 | * but before vsync where vpos would turn negative and | ||
801 | * the hw counter really increments. | ||
802 | */ | ||
803 | if (vpos >= 0) | ||
804 | count++; | ||
805 | } | ||
806 | } | ||
807 | else { | ||
808 | /* Fallback to use value as is. */ | ||
809 | count = radeon_get_vblank_counter(rdev, crtc); | ||
810 | DRM_DEBUG_VBL("NULL mode info! Returned count may be wrong.\n"); | ||
811 | } | ||
812 | |||
813 | return count; | ||
766 | } | 814 | } |
767 | 815 | ||
768 | /** | 816 | /** |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 830e171c3a9e..bba112628b47 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
@@ -367,6 +367,7 @@ struct radeon_crtc { | |||
367 | u32 line_time; | 367 | u32 line_time; |
368 | u32 wm_low; | 368 | u32 wm_low; |
369 | u32 wm_high; | 369 | u32 wm_high; |
370 | u32 lb_vblank_lead_lines; | ||
370 | struct drm_display_mode hw_mode; | 371 | struct drm_display_mode hw_mode; |
371 | enum radeon_output_csc output_csc; | 372 | enum radeon_output_csc output_csc; |
372 | }; | 373 | }; |
@@ -553,6 +554,7 @@ struct radeon_connector { | |||
553 | void *con_priv; | 554 | void *con_priv; |
554 | bool dac_load_detect; | 555 | bool dac_load_detect; |
555 | bool detected_by_load; /* if the connection status was determined by load */ | 556 | bool detected_by_load; /* if the connection status was determined by load */ |
557 | bool detected_hpd_without_ddc; /* if an HPD signal was detected on DVI, but ddc probing failed */ | ||
556 | uint16_t connector_object_id; | 558 | uint16_t connector_object_id; |
557 | struct radeon_hpd hpd; | 559 | struct radeon_hpd hpd; |
558 | struct radeon_router router; | 560 | struct radeon_router router; |
@@ -686,6 +688,9 @@ struct atom_voltage_table | |||
686 | struct atom_voltage_table_entry entries[MAX_VOLTAGE_ENTRIES]; | 688 | struct atom_voltage_table_entry entries[MAX_VOLTAGE_ENTRIES]; |
687 | }; | 689 | }; |
688 | 690 | ||
691 | /* Driver internal use only flags of radeon_get_crtc_scanoutpos() */ | ||
692 | #define USE_REAL_VBLANKSTART (1 << 30) | ||
693 | #define GET_DISTANCE_TO_VBLANKSTART (1 << 31) | ||
689 | 694 | ||
690 | extern void | 695 | extern void |
691 | radeon_add_atom_connector(struct drm_device *dev, | 696 | radeon_add_atom_connector(struct drm_device *dev, |
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index f4f03dcc1530..59abebd6b5dc 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
@@ -1756,7 +1756,9 @@ static bool radeon_pm_in_vbl(struct radeon_device *rdev) | |||
1756 | */ | 1756 | */ |
1757 | for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) { | 1757 | for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) { |
1758 | if (rdev->pm.active_crtcs & (1 << crtc)) { | 1758 | if (rdev->pm.active_crtcs & (1 << crtc)) { |
1759 | vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, 0, | 1759 | vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, |
1760 | crtc, | ||
1761 | USE_REAL_VBLANKSTART, | ||
1760 | &vpos, &hpos, NULL, NULL, | 1762 | &vpos, &hpos, NULL, NULL, |
1761 | &rdev->mode_info.crtcs[crtc]->base.hwmode); | 1763 | &rdev->mode_info.crtcs[crtc]->base.hwmode); |
1762 | if ((vbl_status & DRM_SCANOUTPOS_VALID) && | 1764 | if ((vbl_status & DRM_SCANOUTPOS_VALID) && |
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 97a904835759..6244f4e44e9a 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c | |||
@@ -813,7 +813,7 @@ int rs600_irq_process(struct radeon_device *rdev) | |||
813 | status = rs600_irq_ack(rdev); | 813 | status = rs600_irq_ack(rdev); |
814 | } | 814 | } |
815 | if (queue_hotplug) | 815 | if (queue_hotplug) |
816 | schedule_work(&rdev->hotplug_work); | 816 | schedule_delayed_work(&rdev->hotplug_work, 0); |
817 | if (queue_hdmi) | 817 | if (queue_hdmi) |
818 | schedule_work(&rdev->audio_work); | 818 | schedule_work(&rdev->audio_work); |
819 | if (rdev->msi_enabled) { | 819 | if (rdev->msi_enabled) { |
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 516ca27cfa12..6bc44c24e837 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c | |||
@@ -207,6 +207,9 @@ void rs690_line_buffer_adjust(struct radeon_device *rdev, | |||
207 | { | 207 | { |
208 | u32 tmp; | 208 | u32 tmp; |
209 | 209 | ||
210 | /* Guess line buffer size to be 8192 pixels */ | ||
211 | u32 lb_size = 8192; | ||
212 | |||
210 | /* | 213 | /* |
211 | * Line Buffer Setup | 214 | * Line Buffer Setup |
212 | * There is a single line buffer shared by both display controllers. | 215 | * There is a single line buffer shared by both display controllers. |
@@ -243,6 +246,13 @@ void rs690_line_buffer_adjust(struct radeon_device *rdev, | |||
243 | tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; | 246 | tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; |
244 | } | 247 | } |
245 | WREG32(R_006520_DC_LB_MEMORY_SPLIT, tmp); | 248 | WREG32(R_006520_DC_LB_MEMORY_SPLIT, tmp); |
249 | |||
250 | /* Save number of lines the linebuffer leads before the scanout */ | ||
251 | if (mode1) | ||
252 | rdev->mode_info.crtcs[0]->lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode1->crtc_hdisplay); | ||
253 | |||
254 | if (mode2) | ||
255 | rdev->mode_info.crtcs[1]->lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode2->crtc_hdisplay); | ||
246 | } | 256 | } |
247 | 257 | ||
248 | struct rs690_watermark { | 258 | struct rs690_watermark { |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 07037e32dea3..f878d6962da5 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
@@ -2376,6 +2376,9 @@ static void dce6_program_watermarks(struct radeon_device *rdev, | |||
2376 | c.full = dfixed_div(c, a); | 2376 | c.full = dfixed_div(c, a); |
2377 | priority_b_mark = dfixed_trunc(c); | 2377 | priority_b_mark = dfixed_trunc(c); |
2378 | priority_b_cnt |= priority_b_mark & PRIORITY_MARK_MASK; | 2378 | priority_b_cnt |= priority_b_mark & PRIORITY_MARK_MASK; |
2379 | |||
2380 | /* Save number of lines the linebuffer leads before the scanout */ | ||
2381 | radeon_crtc->lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode->crtc_hdisplay); | ||
2379 | } | 2382 | } |
2380 | 2383 | ||
2381 | /* select wm A */ | 2384 | /* select wm A */ |
@@ -6848,7 +6851,7 @@ restart_ih: | |||
6848 | if (queue_dp) | 6851 | if (queue_dp) |
6849 | schedule_work(&rdev->dp_work); | 6852 | schedule_work(&rdev->dp_work); |
6850 | if (queue_hotplug) | 6853 | if (queue_hotplug) |
6851 | schedule_work(&rdev->hotplug_work); | 6854 | schedule_delayed_work(&rdev->hotplug_work, 0); |
6852 | if (queue_thermal && rdev->pm.dpm_enabled) | 6855 | if (queue_thermal && rdev->pm.dpm_enabled) |
6853 | schedule_work(&rdev->pm.dpm.thermal.work); | 6856 | schedule_work(&rdev->pm.dpm.thermal.work); |
6854 | rdev->ih.rptr = rptr; | 6857 | rdev->ih.rptr = rptr; |