summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMidas Chien <midaschieh@google.com>2022-05-26 12:22:36 +0800
committersusi_su <susisu@google.com>2022-09-14 20:22:15 +0800
commitd0d4f65abe68ede4cd1c86678f8ad552ecd31817 (patch)
tree2907c78e650ff97fbb01810c00a9b0b971e6c378
parentb96583299e2dfd9c97af8de79a85c0027d78897e (diff)
downloaddisplay-android-gs-raviole-5.10-android13-qpr1.tar.gz
There is race condition problem when composer and irq thread to access dqe->state.event. Add lock protection to avoid this problem. Bug: 233709834 Test: enable/disable histogram Signed-off-by: Midas Chien <midaschieh@google.com> Change-Id: I1727622adb036cdc2bbaae4d9c15526b3e11c67f
-rw-r--r--samsung/exynos_drm_dqe.c12
-rw-r--r--samsung/exynos_drm_dqe.h1
2 files changed, 12 insertions, 1 deletions
diff --git a/samsung/exynos_drm_dqe.c b/samsung/exynos_drm_dqe.c
index 03851d6..2db2875 100644
--- a/samsung/exynos_drm_dqe.c
+++ b/samsung/exynos_drm_dqe.c
@@ -97,6 +97,7 @@ int histogram_request_ioctl(struct drm_device *dev, void *data,
struct decon_device *decon;
struct exynos_dqe *dqe;
uint32_t *crtc_id = data;
+ unsigned long flags;
obj = drm_mode_object_find(dev, file, *crtc_id, DRM_MODE_OBJECT_CRTC);
if (!obj) {
@@ -118,16 +119,20 @@ int histogram_request_ioctl(struct drm_device *dev, void *data,
* TODO: Now only one observer is allowed at a time at the moment.
* This will be allowed for multiple observer in the future.
*/
+ spin_lock_irqsave(&dqe->state.histogram_slock, flags);
if (dqe->state.event) {
pr_warn("decon%u histogram already registered\n", decon->id);
+ spin_unlock_irqrestore(&dqe->state.histogram_slock, flags);
return -EBUSY;
}
dqe->state.event = create_histogram_event(dev, file);
if (IS_ERR_OR_NULL(dqe->state.event)) {
dqe->state.event = NULL;
pr_err("failed to create a histogram event\n");
+ spin_unlock_irqrestore(&dqe->state.histogram_slock, flags);
return -EINVAL;
}
+ spin_unlock_irqrestore(&dqe->state.histogram_slock, flags);
pr_debug("created histogram event(0x%pK) of decon%u\n",
dqe->state.event, decon->id);
@@ -143,6 +148,7 @@ int histogram_cancel_ioctl(struct drm_device *dev, void *data,
struct decon_device *decon;
struct exynos_dqe *dqe;
uint32_t *crtc_id = data;
+ unsigned long flags;
obj = drm_mode_object_find(dev, file, *crtc_id, DRM_MODE_OBJECT_CRTC);
if (!obj) {
@@ -160,11 +166,13 @@ int histogram_cancel_ioctl(struct drm_device *dev, void *data,
return -ENODEV;
}
+ spin_lock_irqsave(&dqe->state.histogram_slock, flags);
if (dqe->state.event) {
pr_debug("remained event(0x%pK)\n", dqe->state.event);
drm_event_cancel_free(dev, &dqe->state.event->base);
dqe->state.event = NULL;
}
+ spin_unlock_irqrestore(&dqe->state.histogram_slock, flags);
pr_debug("terminated histogram event of decon%u\n", decon->id);
@@ -173,7 +181,8 @@ int histogram_cancel_ioctl(struct drm_device *dev, void *data,
void handle_histogram_event(struct exynos_dqe *dqe)
{
- struct exynos_drm_pending_histogram_event *e = dqe->state.event;
+ /* This function runs in interrupt context */
+ struct exynos_drm_pending_histogram_event *e;
struct drm_device *dev = dqe->decon->drm_dev;
uint32_t id, crtc_id;
@@ -814,6 +823,7 @@ struct exynos_dqe *exynos_dqe_register(struct decon_device *decon)
dqe->funcs = &dqe_funcs;
dqe->initialized = false;
dqe->decon = decon;
+ spin_lock_init(&dqe->state.histogram_slock);
scnprintf(dqe_name, MAX_DQE_NAME_SIZE, "dqe%u", decon->id);
dqe->dqe_class = class_create(THIS_MODULE, dqe_name);
diff --git a/samsung/exynos_drm_dqe.h b/samsung/exynos_drm_dqe.h
index 0d440d9..d578114 100644
--- a/samsung/exynos_drm_dqe.h
+++ b/samsung/exynos_drm_dqe.h
@@ -40,6 +40,7 @@ struct exynos_dqe_state {
struct histogram_bins *bins;
struct exynos_drm_pending_histogram_event *event;
u32 histogram_threshold;
+ spinlock_t histogram_slock;
enum exynos_prog_pos histogram_pos;
bool rcd_enabled;
struct drm_gem_object *cgc_gem;