diff options
author | Christian König <christian.koenig@amd.com> | 2016-02-11 09:48:30 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2016-02-16 17:24:07 -0500 |
commit | c3874b758ad52708ffdbab3e7c58e70167ce5024 (patch) | |
tree | d89f00c16563e854584c47ea144b5e2e7633bafd | |
parent | 6800e2ea2e74635e5386fc4bb43b0b69edd85a19 (diff) |
drm/amdgpu: stop blocking for page filp fences
Just register an callback and reschedule the work item if necessary.
Signed-off-by: Christian König <christian.koenig@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 43 |
2 files changed, 28 insertions, 16 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 588e86c7c5cc..fc995b45fa8f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h | |||
@@ -761,6 +761,7 @@ struct amdgpu_flip_work { | |||
761 | struct fence *excl; | 761 | struct fence *excl; |
762 | unsigned shared_count; | 762 | unsigned shared_count; |
763 | struct fence **shared; | 763 | struct fence **shared; |
764 | struct fence_cb cb; | ||
764 | }; | 765 | }; |
765 | 766 | ||
766 | 767 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 1d6ef1a95e74..edf91593ac87 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | |||
@@ -35,24 +35,32 @@ | |||
35 | #include <drm/drm_crtc_helper.h> | 35 | #include <drm/drm_crtc_helper.h> |
36 | #include <drm/drm_edid.h> | 36 | #include <drm/drm_edid.h> |
37 | 37 | ||
38 | static void amdgpu_flip_wait_fence(struct amdgpu_device *adev, | 38 | static void amdgpu_flip_callback(struct fence *f, struct fence_cb *cb) |
39 | struct fence **f) | ||
40 | { | 39 | { |
41 | long r; | 40 | struct amdgpu_flip_work *work = |
41 | container_of(cb, struct amdgpu_flip_work, cb); | ||
42 | struct amdgpu_device *adev = work->adev; | ||
43 | struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[work->crtc_id]; | ||
42 | 44 | ||
43 | if (*f == NULL) | 45 | fence_put(f); |
44 | return; | 46 | queue_work(amdgpu_crtc->pflip_queue, &work->flip_work); |
47 | } | ||
45 | 48 | ||
46 | r = fence_wait(*f, false); | 49 | static bool amdgpu_flip_handle_fence(struct amdgpu_flip_work *work, |
47 | if (r) | 50 | struct fence **f) |
48 | DRM_ERROR("failed to wait on page flip fence (%ld)!\n", r); | 51 | { |
52 | struct fence *fence= *f; | ||
53 | |||
54 | if (fence == NULL) | ||
55 | return false; | ||
49 | 56 | ||
50 | /* We continue with the page flip even if we failed to wait on | ||
51 | * the fence, otherwise the DRM core and userspace will be | ||
52 | * confused about which BO the CRTC is scanning out | ||
53 | */ | ||
54 | fence_put(*f); | ||
55 | *f = NULL; | 57 | *f = NULL; |
58 | |||
59 | if (!fence_add_callback(fence, &work->cb, amdgpu_flip_callback)) | ||
60 | return true; | ||
61 | |||
62 | fence_put(*f); | ||
63 | return false; | ||
56 | } | 64 | } |
57 | 65 | ||
58 | static void amdgpu_flip_work_func(struct work_struct *__work) | 66 | static void amdgpu_flip_work_func(struct work_struct *__work) |
@@ -68,9 +76,12 @@ static void amdgpu_flip_work_func(struct work_struct *__work) | |||
68 | int vpos, hpos, stat, min_udelay; | 76 | int vpos, hpos, stat, min_udelay; |
69 | struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id]; | 77 | struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id]; |
70 | 78 | ||
71 | amdgpu_flip_wait_fence(adev, &work->excl); | 79 | if (amdgpu_flip_handle_fence(work, &work->excl)) |
80 | return; | ||
81 | |||
72 | for (i = 0; i < work->shared_count; ++i) | 82 | for (i = 0; i < work->shared_count; ++i) |
73 | amdgpu_flip_wait_fence(adev, &work->shared[i]); | 83 | if (amdgpu_flip_handle_fence(work, &work->shared[i])) |
84 | return; | ||
74 | 85 | ||
75 | /* We borrow the event spin lock for protecting flip_status */ | 86 | /* We borrow the event spin lock for protecting flip_status */ |
76 | spin_lock_irqsave(&crtc->dev->event_lock, flags); | 87 | spin_lock_irqsave(&crtc->dev->event_lock, flags); |
@@ -234,7 +245,7 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc, | |||
234 | /* update crtc fb */ | 245 | /* update crtc fb */ |
235 | crtc->primary->fb = fb; | 246 | crtc->primary->fb = fb; |
236 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); | 247 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); |
237 | queue_work(amdgpu_crtc->pflip_queue, &work->flip_work); | 248 | amdgpu_flip_work_func(&work->flip_work); |
238 | return 0; | 249 | return 0; |
239 | 250 | ||
240 | vblank_cleanup: | 251 | vblank_cleanup: |