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:
@@ -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,
|
||||
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user