Skip to content

Commit df4d4aa

Browse files
committed
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 4dfd648 "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
2 parents bbc8764 + 8e36f9d commit df4d4aa

30 files changed

+387
-91
lines changed

drivers/gpu/drm/amd/amdgpu/amdgpu.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,7 @@ struct amdgpu_bo {
539539
/* Constant after initialization */
540540
struct amdgpu_device *adev;
541541
struct drm_gem_object gem_base;
542+
struct amdgpu_bo *parent;
542543

543544
struct ttm_bo_kmap_obj dma_buf_vmap;
544545
pid_t pid;
@@ -955,6 +956,8 @@ struct amdgpu_vm {
955956
struct amdgpu_vm_id ids[AMDGPU_MAX_RINGS];
956957
/* for interval tree */
957958
spinlock_t it_lock;
959+
/* protecting freed */
960+
spinlock_t freed_lock;
958961
};
959962

960963
struct amdgpu_vm_manager {

drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
222222
}
223223

224224
p->uf.bo = gem_to_amdgpu_bo(gobj);
225+
amdgpu_bo_ref(p->uf.bo);
226+
drm_gem_object_unreference_unlocked(gobj);
225227
p->uf.offset = fence_data->offset;
226228
} else {
227229
ret = -EINVAL;
@@ -487,7 +489,7 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo
487489
amdgpu_ib_free(parser->adev, &parser->ibs[i]);
488490
kfree(parser->ibs);
489491
if (parser->uf.bo)
490-
drm_gem_object_unreference_unlocked(&parser->uf.bo->gem_base);
492+
amdgpu_bo_unref(&parser->uf.bo);
491493
}
492494

493495
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)
776778
amdgpu_ib_free(job->adev, &job->ibs[i]);
777779
kfree(job->ibs);
778780
if (job->uf.bo)
779-
drm_gem_object_unreference_unlocked(&job->uf.bo->gem_base);
781+
amdgpu_bo_unref(&job->uf.bo);
780782
return 0;
781783
}
782784

drivers/gpu/drm/amd/amdgpu/amdgpu_display.c

Lines changed: 79 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
7373
struct drm_crtc *crtc = &amdgpuCrtc->base;
7474
unsigned long flags;
7575
unsigned i;
76+
int vpos, hpos, stat, min_udelay;
77+
struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];
7678

7779
amdgpu_flip_wait_fence(adev, &work->excl);
7880
for (i = 0; i < work->shared_count; ++i)
@@ -81,6 +83,41 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
8183
/* We borrow the event spin lock for protecting flip_status */
8284
spin_lock_irqsave(&crtc->dev->event_lock, flags);
8385

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+
84121
/* do the flip (mmio) */
85122
adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base);
86123
/* set the flip status */
@@ -109,7 +146,7 @@ static void amdgpu_unpin_work_func(struct work_struct *__work)
109146
} else
110147
DRM_ERROR("failed to reserve buffer after flip\n");
111148

112-
drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
149+
amdgpu_bo_unref(&work->old_rbo);
113150
kfree(work->shared);
114151
kfree(work);
115152
}
@@ -148,8 +185,8 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
148185
obj = old_amdgpu_fb->obj;
149186

150187
/* take a reference to the old object */
151-
drm_gem_object_reference(obj);
152188
work->old_rbo = gem_to_amdgpu_bo(obj);
189+
amdgpu_bo_ref(work->old_rbo);
153190

154191
new_amdgpu_fb = to_amdgpu_framebuffer(fb);
155192
obj = new_amdgpu_fb->obj;
@@ -222,7 +259,7 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
222259
amdgpu_bo_unreserve(new_rbo);
223260

224261
cleanup:
225-
drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
262+
amdgpu_bo_unref(&work->old_rbo);
226263
fence_put(work->excl);
227264
for (i = 0; i < work->shared_count; ++i)
228265
fence_put(work->shared[i]);
@@ -712,6 +749,15 @@ bool amdgpu_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
712749
* \param dev Device to query.
713750
* \param pipe Crtc to query.
714751
* \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+
*
715761
* \param *vpos Location where vertical scanout position should be stored.
716762
* \param *hpos Location where horizontal scanout position should go.
717763
* \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,
776822
vbl_end = 0;
777823
}
778824

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+
779844
/* Test scanout position against vblank region. */
780845
if ((*vpos < vbl_start) && (*vpos >= vbl_end))
781846
in_vbl = false;
782847

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+
783859
/* Check if inside vblank area and apply corrective offsets:
784860
* vpos will then be >=0 in video scanout area, but negative
785861
* 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,
795871
/* Correct for shifted end of vbl at vbl_end. */
796872
*vpos = *vpos - vbl_end;
797873

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-
824874
return ret;
825875
}
826876

drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,9 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data,
235235
AMDGPU_GEM_USERPTR_REGISTER))
236236
return -EINVAL;
237237

238-
if (!(args->flags & AMDGPU_GEM_USERPTR_ANONONLY) ||
239-
!(args->flags & AMDGPU_GEM_USERPTR_REGISTER)) {
238+
if (!(args->flags & AMDGPU_GEM_USERPTR_READONLY) && (
239+
!(args->flags & AMDGPU_GEM_USERPTR_ANONONLY) ||
240+
!(args->flags & AMDGPU_GEM_USERPTR_REGISTER))) {
240241

241242
/* if we want to write to it we must require anonymous
242243
memory and install a MMU notifier */

drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,13 +611,59 @@ void amdgpu_driver_preclose_kms(struct drm_device *dev,
611611
u32 amdgpu_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe)
612612
{
613613
struct amdgpu_device *adev = dev->dev_private;
614+
int vpos, hpos, stat;
615+
u32 count;
614616

615617
if (pipe >= adev->mode_info.num_crtc) {
616618
DRM_ERROR("Invalid crtc %u\n", pipe);
617619
return -EINVAL;
618620
}
619621

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;
621667
}
622668

623669
/**

drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ struct amdgpu_crtc {
407407
u32 line_time;
408408
u32 wm_low;
409409
u32 wm_high;
410+
u32 lb_vblank_lead_lines;
410411
struct drm_display_mode hw_mode;
411412
};
412413

@@ -528,6 +529,10 @@ struct amdgpu_framebuffer {
528529
#define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \
529530
((em) == ATOM_ENCODER_MODE_DP_MST))
530531

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+
531536
void amdgpu_link_encoder_connector(struct drm_device *dev);
532537

533538
struct drm_connector *

drivers/gpu/drm/amd/amdgpu/amdgpu_object.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ static void amdgpu_ttm_bo_destroy(struct ttm_buffer_object *tbo)
100100
list_del_init(&bo->list);
101101
mutex_unlock(&bo->adev->gem.mutex);
102102
drm_gem_object_release(&bo->gem_base);
103+
amdgpu_bo_unref(&bo->parent);
103104
kfree(bo->metadata);
104105
kfree(bo);
105106
}

drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -587,9 +587,13 @@ static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm,
587587
uint32_t flags = amdgpu_ttm_tt_pte_flags(gtt->adev, ttm, bo_mem);
588588
int r;
589589

590-
if (gtt->userptr)
591-
amdgpu_ttm_tt_pin_userptr(ttm);
592-
590+
if (gtt->userptr) {
591+
r = amdgpu_ttm_tt_pin_userptr(ttm);
592+
if (r) {
593+
DRM_ERROR("failed to pin userptr\n");
594+
return r;
595+
}
596+
}
593597
gtt->offset = (unsigned long)(bo_mem->start << PAGE_SHIFT);
594598
if (!ttm->num_pages) {
595599
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,
797801
if (mem && mem->mem_type != TTM_PL_SYSTEM)
798802
flags |= AMDGPU_PTE_VALID;
799803

800-
if (mem && mem->mem_type == TTM_PL_TT)
804+
if (mem && mem->mem_type == TTM_PL_TT) {
801805
flags |= AMDGPU_PTE_SYSTEM;
802806

803-
if (!ttm || ttm->caching_state == tt_cached)
804-
flags |= AMDGPU_PTE_SNOOPED;
807+
if (ttm->caching_state == tt_cached)
808+
flags |= AMDGPU_PTE_SNOOPED;
809+
}
805810

806811
if (adev->asic_type >= CHIP_TOPAZ)
807812
flags |= AMDGPU_PTE_EXECUTABLE;

0 commit comments

Comments
 (0)