diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 5e52244600420df91a5e6e60fcc94713769f953f..9460f3a4c1c2ba2348927d10946a7920956a0e53 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1355,6 +1355,15 @@ static int stall_checks(struct drm_crtc *crtc, bool nonblock) return ret < 0 ? ret : 0; } +void release_crtc_commit(struct completion *completion) +{ + struct drm_crtc_commit *commit = container_of(completion, + typeof(*commit), + flip_done); + + drm_crtc_commit_put(commit); +} + /** * drm_atomic_helper_setup_commit - setup possibly nonblocking commit * @state: new modeset state to be committed @@ -1447,6 +1456,8 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state, } crtc_state->event->base.completion = &commit->flip_done; + crtc_state->event->base.completion_release = release_crtc_commit; + drm_crtc_commit_get(commit); } return 0; diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 48e106557c92c99a563a66792310b1b3506c9050..e22645375e6074ed572ac5b9144da209289140b9 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -689,8 +689,8 @@ void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e) assert_spin_locked(&dev->event_lock); if (e->completion) { - /* ->completion might disappear as soon as it signalled. */ complete_all(e->completion); + e->completion_release(e->completion); e->completion = NULL; } diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 8671ddd256fc5a1f276e5505ba35ae445364c238..ffa8b6d6d3679c9cad742b8728ad6be9fa5f3168 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -360,6 +360,7 @@ struct drm_ioctl_desc { /* Event queued up for userspace to read */ struct drm_pending_event { struct completion *completion; + void (*completion_release)(struct completion *completion); struct drm_event *event; struct dma_fence *fence; struct list_head link;