disp: msm: sde: avoid duplicate fence create from client

SDE fence driver avoids duplicate fence creation if
fence timeline is not increased. This may lead to issue
if client closes the fence with failure ATOMIC_COMMIT.
SDE fence driver provides the closed fd node to subsequent
valid commit and leads to invalid state. This patch avoids
duplicate fence creation from crtc and connector object
instead of sde_fence.

Change-Id: Ic7b43762f0ad251fb20e42edb5f4d5f401790e14
Signed-off-by: Dhaval Patel <pdhaval@codeaurora.org>
This commit is contained in:
Dhaval Patel
2019-07-09 16:40:53 -07:00
parent 84fc2163e1
commit d710ac7f11
4 changed files with 68 additions and 44 deletions

View File

@@ -1204,7 +1204,8 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
struct sde_connector *c_conn;
struct sde_connector_state *c_state;
int idx, rc;
uint64_t fence_fd;
uint64_t fence_user_fd;
uint64_t __user prev_user_fd;
if (!connector || !state || !property) {
SDE_ERROR("invalid argument(s), conn %pK, state %pK, prp %pK\n",
@@ -1247,24 +1248,43 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
if (!val)
goto end;
rc = copy_from_user(&prev_user_fd, (void __user *)val,
sizeof(uint64_t));
if (rc) {
SDE_ERROR("copy from user failed rc:%d\n", rc);
rc = -EFAULT;
goto end;
}
/*
* update the the offset to a timeline for commit completion
* client is expected to reset the property to -1 before
* requesting for the retire fence
*/
rc = sde_fence_create(c_conn->retire_fence, &fence_fd, 1);
if (prev_user_fd == -1) {
/*
* update the offset to a timeline for
* commit completion
*/
rc = sde_fence_create(c_conn->retire_fence,
&fence_user_fd, 1);
if (rc) {
SDE_ERROR("fence create failed rc:%d\n", rc);
goto end;
}
rc = copy_to_user((uint64_t __user *)(uintptr_t)val, &fence_fd,
sizeof(uint64_t));
rc = copy_to_user((uint64_t __user *)(uintptr_t)val,
&fence_user_fd, sizeof(uint64_t));
if (rc) {
SDE_ERROR("copy to user failed rc:%d\n", rc);
/* fence will be released with timeline update */
put_unused_fd(fence_fd);
/*
* fence will be released with timeline
* update
*/
put_unused_fd(fence_user_fd);
rc = -EFAULT;
goto end;
}
}
break;
case CONNECTOR_PROP_ROI_V1:
rc = _sde_connector_set_roi_v1(c_conn, c_state,

View File

@@ -5025,7 +5025,8 @@ static int sde_crtc_atomic_set_property(struct drm_crtc *crtc,
struct sde_crtc *sde_crtc;
struct sde_crtc_state *cstate;
int idx, ret;
uint64_t fence_fd;
uint64_t fence_user_fd;
uint64_t __user prev_user_fd;
if (!crtc || !state || !property) {
SDE_ERROR("invalid argument(s)\n");
@@ -5085,20 +5086,35 @@ static int sde_crtc_atomic_set_property(struct drm_crtc *crtc,
if (!val)
goto exit;
ret = _sde_crtc_get_output_fence(crtc, state, &fence_fd);
ret = copy_from_user(&prev_user_fd, (void __user *)val,
sizeof(uint64_t));
if (ret) {
SDE_ERROR("copy from user failed rc:%d\n", ret);
ret = -EFAULT;
goto exit;
}
/*
* client is expected to reset the property to -1 before
* requesting for the release fence
*/
if (prev_user_fd == -1) {
ret = _sde_crtc_get_output_fence(crtc, state,
&fence_user_fd);
if (ret) {
SDE_ERROR("fence create failed rc:%d\n", ret);
goto exit;
}
ret = copy_to_user((uint64_t __user *)(uintptr_t)val, &fence_fd,
sizeof(uint64_t));
ret = copy_to_user((uint64_t __user *)(uintptr_t)val,
&fence_user_fd, sizeof(uint64_t));
if (ret) {
SDE_ERROR("copy to user failed rc:%d\n", ret);
put_unused_fd(fence_fd);
put_unused_fd(fence_user_fd);
ret = -EFAULT;
goto exit;
}
}
break;
default:
/* nothing to do */

View File

@@ -325,9 +325,8 @@ int sde_fence_create(struct sde_fence_context *ctx, uint64_t *val,
uint32_t offset)
{
uint32_t trigger_value;
int fd = -1, rc = -EINVAL;
int fd, rc = -EINVAL;
unsigned long flags;
struct sde_fence *fc;
if (!ctx || !val) {
SDE_ERROR("invalid argument(s), fence %d, pval %d\n",
@@ -347,22 +346,10 @@ int sde_fence_create(struct sde_fence_context *ctx, uint64_t *val,
trigger_value = ctx->commit_count + offset;
spin_unlock_irqrestore(&ctx->lock, flags);
spin_lock(&ctx->list_lock);
list_for_each_entry(fc, &ctx->fence_list_head, fence_list) {
if (trigger_value == fc->base.seqno) {
fd = fc->fd;
*val = fd;
break;
}
}
spin_unlock(&ctx->list_lock);
if (fd < 0) {
fd = _sde_fence_create_fd(ctx, trigger_value);
*val = fd;
SDE_DEBUG("fd:%d trigger:%d commit:%d offset:%d\n",
fd, trigger_value, ctx->commit_count, offset);
}
SDE_EVT32(ctx->drm_id, trigger_value, fd);
rc = (fd >= 0) ? 0 : fd;

View File

@@ -765,8 +765,9 @@ int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
switch (rc) {
case 0:
SDE_ERROR_PLANE(psde, "%ums timeout on %08X\n",
wait_ms, prefix);
SDE_ERROR_PLANE(psde, "%ums timeout on %08X fd %d\n",
wait_ms, prefix, sde_plane_get_property(pstate,
PLANE_PROP_INPUT_FENCE));
psde->is_error = true;
sde_kms_timeline_status(plane->dev);
ret = -ETIMEDOUT;