summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRahul Sharma <rahsha@codeaurora.org>2019-01-22 14:52:24 +0530
committerGerrit - the friendly Code Review server <code-review@localhost>2019-02-08 00:49:24 -0800
commit165e5ffaffc024f77163972ed68993203aeaf77a (patch)
tree2e4248fe987a5db02a6c644c8a0e0b44073b3a7c
parent5b964b49e9fdfe977724a260d2972d5befd175a2 (diff)
drm/msm: support release/retire fence through set prop
Multiple drm clients are allowed to call the get_properties on drm device node. If sde driver creates the fence for each get_property call then it may leave fd leak in client process context because might not be expecting fences. Supporting get_property for only master device may not solve the issue because master client may still call the get_properties multiple times between two commit cycles. This patch supports release/retire fence through set property to avoid fence leak. Change-Id: I07fe63fe84901d7f96b522ca6309cfdd90a25c40 Signed-off-by: Dhaval Patel <pdhaval@codeaurora.org> Signed-off-by: Rahul Sharma <rahsha@codeaurora.org>
-rw-r--r--drivers/gpu/drm/msm/sde/sde_connector.c22
-rw-r--r--drivers/gpu/drm/msm/sde/sde_crtc.c119
2 files changed, 101 insertions, 40 deletions
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index 7930cc29f7f4..3e8b14b6acd7 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -428,6 +428,7 @@ 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 = 0;
if (!connector || !state || !property) {
SDE_ERROR("invalid argument(s), conn %pK, state %pK, prp %pK\n",
@@ -472,6 +473,23 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
SDE_ERROR("prep fb failed, %d\n", rc);
}
break;
+ case CONNECTOR_PROP_RETIRE_FENCE:
+ rc = sde_fence_create(&c_conn->retire_fence, &fence_fd, 0);
+ if (rc) {
+ SDE_ERROR("fence create failed rc:%d\n", rc);
+ goto end;
+ }
+
+ rc = copy_to_user((uint64_t __user *)val, &fence_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);
+ rc = -EFAULT;
+ goto end;
+ }
+ break;
case CONNECTOR_PROP_TOPOLOGY_CONTROL:
rc = sde_rm_check_property_topctl(val);
if (rc)
@@ -931,8 +949,8 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
"hdr_control", 0x0, 0, ~0, 0,
CONNECTOR_PROP_HDR_CONTROL);
- msm_property_install_range(&c_conn->property_info, "RETIRE_FENCE",
- 0x0, 0, INR_OPEN_MAX, 0, CONNECTOR_PROP_RETIRE_FENCE);
+ msm_property_install_volatile_range(&c_conn->property_info,
+ "RETIRE_FENCE", 0x0, 0, ~0, 0, CONNECTOR_PROP_RETIRE_FENCE);
msm_property_install_volatile_signed_range(&c_conn->property_info,
"PLL_DELTA", 0x0, INT_MIN, INT_MAX, 0,
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 733ff5f686c0..fe72149c40c0 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -1642,8 +1642,8 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
"input_fence_timeout", 0x0, 0, SDE_CRTC_MAX_INPUT_FENCE_TIMEOUT,
SDE_CRTC_INPUT_FENCE_TIMEOUT, CRTC_PROP_INPUT_FENCE_TIMEOUT);
- msm_property_install_range(&sde_crtc->property_info, "output_fence",
- 0x0, 0, INR_OPEN_MAX, 0x0, CRTC_PROP_OUTPUT_FENCE);
+ msm_property_install_volatile_range(&sde_crtc->property_info,
+ "output_fence", 0x0, 0, ~0, 0, CRTC_PROP_OUTPUT_FENCE);
msm_property_install_range(&sde_crtc->property_info,
"output_fence_offset", 0x0, 0, 1, 0,
@@ -1708,6 +1708,21 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
kfree(info);
}
+static int _sde_crtc_get_output_fence(struct drm_crtc *crtc,
+ const struct drm_crtc_state *state, uint64_t *val)
+{
+ struct sde_crtc *sde_crtc;
+ struct sde_crtc_state *cstate;
+ uint32_t offset;
+
+ sde_crtc = to_sde_crtc(crtc);
+ cstate = to_sde_crtc_state(state);
+
+ offset = sde_crtc_get_property(cstate, CRTC_PROP_OUTPUT_FENCE_OFFSET);
+
+ return sde_fence_create(&sde_crtc->output_fence, val, offset);
+}
+
/**
* sde_crtc_atomic_set_property - atomically set a crtc drm property
* @crtc: Pointer to drm crtc structure
@@ -1724,28 +1739,58 @@ static int sde_crtc_atomic_set_property(struct drm_crtc *crtc,
struct sde_crtc *sde_crtc;
struct sde_crtc_state *cstate;
int idx, ret = -EINVAL;
+ uint64_t fence_fd = 0;
if (!crtc || !state || !property) {
SDE_ERROR("invalid argument(s)\n");
+ return -EINVAL;
+ }
+
+ sde_crtc = to_sde_crtc(crtc);
+ cstate = to_sde_crtc_state(state);
+
+ ret = msm_property_atomic_set(&sde_crtc->property_info,
+ cstate->property_values, cstate->property_blobs,
+ property, val);
+
+ if (!ret) {
+ idx = msm_property_index(&sde_crtc->property_info,
+ property);
+ switch (idx) {
+ case CRTC_PROP_INPUT_FENCE_TIMEOUT:
+ _sde_crtc_set_input_fence_timeout(cstate);
+ break;
+ case CRTC_PROP_OUTPUT_FENCE:
+ ret = _sde_crtc_get_output_fence(crtc,
+ state, &fence_fd);
+ if (ret) {
+ SDE_ERROR("fence create failed rc:%d\n", ret);
+ goto exit;
+ }
+
+ ret = copy_to_user((uint64_t __user *)val, &fence_fd,
+ sizeof(uint64_t));
+
+ if (ret) {
+ SDE_ERROR("copy to user failed rc:%d\n", ret);
+ put_unused_fd(fence_fd);
+ ret = -EFAULT;
+ goto exit;
+ }
+ break;
+ default:
+ /* nothing to do */
+ break;
+ }
} else {
- sde_crtc = to_sde_crtc(crtc);
- cstate = to_sde_crtc_state(state);
- ret = msm_property_atomic_set(&sde_crtc->property_info,
- cstate->property_values, cstate->property_blobs,
+ ret = sde_cp_crtc_set_property(crtc,
property, val);
- if (!ret) {
- idx = msm_property_index(&sde_crtc->property_info,
- property);
- if (idx == CRTC_PROP_INPUT_FENCE_TIMEOUT)
- _sde_crtc_set_input_fence_timeout(cstate);
- } else {
- ret = sde_cp_crtc_set_property(crtc,
- property, val);
- }
- if (ret)
- DRM_ERROR("failed to set the property\n");
}
+exit:
+ if (ret)
+ DRM_ERROR("failed to set the property\n");
+
return ret;
}
@@ -1783,30 +1828,28 @@ static int sde_crtc_atomic_get_property(struct drm_crtc *crtc,
if (!crtc || !state) {
SDE_ERROR("invalid argument(s)\n");
- } else {
- sde_crtc = to_sde_crtc(crtc);
- cstate = to_sde_crtc_state(state);
+ return -EINVAL;
+ }
- i = msm_property_index(&sde_crtc->property_info, property);
- if (i == CRTC_PROP_OUTPUT_FENCE) {
- int offset = sde_crtc_get_property(cstate,
- CRTC_PROP_OUTPUT_FENCE_OFFSET);
+ sde_crtc = to_sde_crtc(crtc);
+ cstate = to_sde_crtc_state(state);
- ret = sde_fence_create(&sde_crtc->output_fence, val,
- offset);
- if (ret)
- SDE_ERROR("fence create failed\n");
- } else {
- ret = msm_property_atomic_get(&sde_crtc->property_info,
- cstate->property_values,
- cstate->property_blobs, property, val);
- if (ret)
- ret = sde_cp_crtc_get_property(crtc,
- property, val);
- }
+ i = msm_property_index(&sde_crtc->property_info, property);
+ if (i == CRTC_PROP_OUTPUT_FENCE) {
+ ret = _sde_crtc_get_output_fence(crtc, state, val);
+ if (ret)
+ SDE_ERROR("fence create failed\n");
+ } else {
+ ret = msm_property_atomic_get(&sde_crtc->property_info,
+ cstate->property_values,
+ cstate->property_blobs, property, val);
if (ret)
- DRM_ERROR("get property failed\n");
+ ret = sde_cp_crtc_get_property(crtc,
+ property, val);
}
+ if (ret)
+ DRM_ERROR("get property failed\n");
+
return ret;
}