UPSTREAM: drm/drm_vblank: set the dma-fence timestamp during send_vblank_event
The explicit out-fences in crtc are signaled as part of vblank event, indicating all framebuffers present on the Atomic Commit request are scanned out on the screen. Though the fence signal and the vblank event notification happens at the same time, triggered by the same hardware vsync event, the timestamp set in both are different. With drivers supporting precise vblank timestamp the difference between the two timestamps would be even higher. This might have an impact on use-mode frameworks using these fence timestamps for purposes other than simple buffer usage. For instance, the Android framework [1] uses the retire-fences as an alternative to vblank when frame-updates are in progress. Set the fence timestamp during send vblank event using a new drm_send_event_timestamp_locked variant to avoid discrepancies. [1] https://android.googlesource.com/platform/frameworks/native/+/master/ services/surfaceflinger/Scheduler/Scheduler.cpp#397 Changes in v2: - Use drm_send_event_timestamp_locked to update fence timestamp - add more information to commit text Changes in v3: - use same backend helper function for variants of drm_send_event to avoid code duplications Changes in v4: - remove WARN_ON from drm_send_event_timestamp_locked Bug: 173434777 Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org> Signed-off-by: Narendra Muppalla <NarendraM@codeaurora.org> Reviewed-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org> [sumits: minor parenthesis alignment correction] Link: https://patchwork.freedesktop.org/patch/msgid/1610757107-11892-2-git-send-email-veeras@codeaurora.org (cherry picked from commit a78e7a51d2fa9d2f482b462be4299784c884d988) Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org> Change-Id: Iaa29508f72e2c9c7abd2e3fe7a4dc7b9665336a5
This commit is contained in:
committed by
Todd Kjos
parent
430a4283cb
commit
a9b76c4519
@@ -774,6 +774,72 @@ void drm_event_cancel_free(struct drm_device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL(drm_event_cancel_free);
|
||||
|
||||
/**
|
||||
* drm_send_event_helper - send DRM event to file descriptor
|
||||
* @dev: DRM device
|
||||
* @e: DRM event to deliver
|
||||
* @timestamp: timestamp to set for the fence event in kernel's CLOCK_MONOTONIC
|
||||
* time domain
|
||||
*
|
||||
* This helper function sends the event @e, initialized with
|
||||
* drm_event_reserve_init(), to its associated userspace DRM file.
|
||||
* The timestamp variant of dma_fence_signal is used when the caller
|
||||
* sends a valid timestamp.
|
||||
*/
|
||||
void drm_send_event_helper(struct drm_device *dev,
|
||||
struct drm_pending_event *e, ktime_t timestamp)
|
||||
{
|
||||
assert_spin_locked(&dev->event_lock);
|
||||
|
||||
if (e->completion) {
|
||||
complete_all(e->completion);
|
||||
e->completion_release(e->completion);
|
||||
e->completion = NULL;
|
||||
}
|
||||
|
||||
if (e->fence) {
|
||||
if (timestamp)
|
||||
dma_fence_signal_timestamp(e->fence, timestamp);
|
||||
else
|
||||
dma_fence_signal(e->fence);
|
||||
dma_fence_put(e->fence);
|
||||
}
|
||||
|
||||
if (!e->file_priv) {
|
||||
kfree(e);
|
||||
return;
|
||||
}
|
||||
|
||||
list_del(&e->pending_link);
|
||||
list_add_tail(&e->link,
|
||||
&e->file_priv->event_list);
|
||||
wake_up_interruptible_poll(&e->file_priv->event_wait,
|
||||
EPOLLIN | EPOLLRDNORM);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_send_event_timestamp_locked - send DRM event to file descriptor
|
||||
* @dev: DRM device
|
||||
* @e: DRM event to deliver
|
||||
* @timestamp: timestamp to set for the fence event in kernel's CLOCK_MONOTONIC
|
||||
* time domain
|
||||
*
|
||||
* This function sends the event @e, initialized with drm_event_reserve_init(),
|
||||
* to its associated userspace DRM file. Callers must already hold
|
||||
* &drm_device.event_lock.
|
||||
*
|
||||
* Note that the core will take care of unlinking and disarming events when the
|
||||
* corresponding DRM file is closed. Drivers need not worry about whether the
|
||||
* DRM file for this event still exists and can call this function upon
|
||||
* completion of the asynchronous work unconditionally.
|
||||
*/
|
||||
void drm_send_event_timestamp_locked(struct drm_device *dev,
|
||||
struct drm_pending_event *e, ktime_t timestamp)
|
||||
{
|
||||
drm_send_event_helper(dev, e, timestamp);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_send_event_timestamp_locked);
|
||||
|
||||
/**
|
||||
* drm_send_event_locked - send DRM event to file descriptor
|
||||
* @dev: DRM device
|
||||
@@ -790,29 +856,7 @@ EXPORT_SYMBOL(drm_event_cancel_free);
|
||||
*/
|
||||
void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e)
|
||||
{
|
||||
assert_spin_locked(&dev->event_lock);
|
||||
|
||||
if (e->completion) {
|
||||
complete_all(e->completion);
|
||||
e->completion_release(e->completion);
|
||||
e->completion = NULL;
|
||||
}
|
||||
|
||||
if (e->fence) {
|
||||
dma_fence_signal(e->fence);
|
||||
dma_fence_put(e->fence);
|
||||
}
|
||||
|
||||
if (!e->file_priv) {
|
||||
kfree(e);
|
||||
return;
|
||||
}
|
||||
|
||||
list_del(&e->pending_link);
|
||||
list_add_tail(&e->link,
|
||||
&e->file_priv->event_list);
|
||||
wake_up_interruptible_poll(&e->file_priv->event_wait,
|
||||
EPOLLIN | EPOLLRDNORM);
|
||||
drm_send_event_helper(dev, e, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_send_event_locked);
|
||||
|
||||
@@ -836,7 +880,7 @@ void drm_send_event(struct drm_device *dev, struct drm_pending_event *e)
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev->event_lock, irqflags);
|
||||
drm_send_event_locked(dev, e);
|
||||
drm_send_event_helper(dev, e, 0);
|
||||
spin_unlock_irqrestore(&dev->event_lock, irqflags);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_send_event);
|
||||
|
||||
Reference in New Issue
Block a user