diff options
author | Midas Chien <midaschieh@google.com> | 2021-12-09 18:01:39 +0800 |
---|---|---|
committer | Midas Chien <midaschieh@google.com> | 2021-12-16 00:38:04 +0800 |
commit | d9eabf5eb9a6072b1120bb78c11ba882658f159e (patch) | |
tree | 0022abe51b7d1c96994364df0b8257b4cbe4f58e | |
parent | 066b5f0309aa57a8fb40a1ff68912a4b4ce3ba9e (diff) | |
download | display-d9eabf5eb9a6072b1120bb78c11ba882658f159e.tar.gz |
drm: samsung: add lock when dumping dpu event logs
There is race condition between read and write dpu event logs. Add lock
to protect dpu event log content to avoid race issue.
Bug: 209878019
Test: dump dpu event logs continuously and do some operators at same
time, including on/off, video, camera, chrome, youtube
Test: simulate underrun to dump dpu event logs automatically
Change-Id: Idcd77c6f2c230557be4f0851d4bcd55bb6d115df
Signed-off-by: Midas Chien <midaschieh@google.com>
-rw-r--r-- | samsung/exynos_drm_debug.c | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/samsung/exynos_drm_debug.c b/samsung/exynos_drm_debug.c index 867e3db..bef8e95 100644 --- a/samsung/exynos_drm_debug.c +++ b/samsung/exynos_drm_debug.c @@ -144,10 +144,10 @@ void DPU_EVENT_LOG(enum dpu_event_type type, int index, void *priv) spin_lock_irqsave(&decon->d.event_lock, flags); idx = atomic_inc_return(&decon->d.event_log_idx) % dpu_event_log_max; log = &decon->d.event_log[idx]; + log->type = DPU_EVT_NONE; spin_unlock_irqrestore(&decon->d.event_lock, flags); log->time = ktime_get(); - log->type = type; switch (type) { case DPU_EVT_DPP_FRAMEDONE: @@ -265,6 +265,8 @@ void DPU_EVENT_LOG(enum dpu_event_type type, int index, void *priv) default: break; } + + log->type = type; } /* @@ -294,9 +296,9 @@ void DPU_EVENT_LOG_ATOMIC_COMMIT(int index) spin_lock_irqsave(&decon->d.event_lock, flags); idx = atomic_inc_return(&decon->d.event_log_idx) % dpu_event_log_max; log = &decon->d.event_log[idx]; + log->type = DPU_EVT_NONE; spin_unlock_irqrestore(&decon->d.event_lock, flags); - log->type = DPU_EVT_ATOMIC_COMMIT; log->time = ktime_get(); decon->d.auto_refresh_frames = 0; @@ -313,6 +315,8 @@ void DPU_EVENT_LOG_ATOMIC_COMMIT(int index) decon->dpp[dpp_ch]->dbg_dma_addr; } } + + log->type = DPU_EVT_ATOMIC_COMMIT; } extern void *return_address(unsigned int); @@ -347,9 +351,9 @@ DPU_EVENT_LOG_CMD(struct dsim_device *dsim, u8 type, u8 d0, u16 len) spin_lock_irqsave(&decon->d.event_lock, flags); idx = atomic_inc_return(&decon->d.event_log_idx) % dpu_event_log_max; log = &decon->d.event_log[idx]; + log->type = DPU_EVT_NONE; spin_unlock_irqrestore(&decon->d.event_lock, flags); - log->type = DPU_EVT_DSIM_COMMAND; log->time = ktime_get(); log->data.cmd.id = type; @@ -359,6 +363,8 @@ DPU_EVENT_LOG_CMD(struct dsim_device *dsim, u8 type, u8 d0, u16 len) for (i = 0; i < DPU_CALLSTACK_MAX; i++) log->data.cmd.caller[i] = (void *)((size_t)return_address(i + 1)); + + log->type = DPU_EVT_DSIM_COMMAND; } static void dpu_print_log_atomic(struct dpu_log_atomic *atomic, @@ -378,6 +384,12 @@ static void dpu_print_log_atomic(struct dpu_log_atomic *atomic, if (win->state == DPU_WIN_STATE_DISABLED) continue; + if (win->state < DPU_WIN_STATE_DISABLED || + win->state > DPU_WIN_STATE_BUFFER) { + pr_warn("%s: invalid win state %d\n", __func__, win->state); + continue; + } + fmt = dpu_find_fmt_info(win->format); len = scnprintf(buf, sizeof(buf), @@ -597,15 +609,18 @@ static void dpu_event_log_print(const struct decon_device *decon, struct drm_pri size_t max_logs, enum dpu_event_condition condition) { int idx = atomic_read(&decon->d.event_log_idx); - struct dpu_log *log; + struct decon_device *decon_dev = (struct decon_device *)decon; + struct dpu_log dump_log; + struct dpu_log *log = &dump_log; int latest = idx % dpu_event_log_max; struct timespec64 ts; const char *str_comp; char buf[LOG_BUF_SIZE]; const struct dpu_fmt *fmt; int len; + unsigned long flags; - if (IS_ERR_OR_NULL(decon->d.event_log)) + if (IS_ERR_OR_NULL(decon_dev->d.event_log)) return; drm_printf(p, "----------------------------------------------------\n"); @@ -625,8 +640,10 @@ static void dpu_event_log_print(const struct decon_device *decon, struct drm_pri if (++idx >= dpu_event_log_max) idx = 0; - /* Seek a index */ - log = &decon->d.event_log[idx]; + /* Seek a index and copy log for dump */ + spin_lock_irqsave(&decon_dev->d.event_lock, flags); + memcpy(&dump_log, &decon_dev->d.event_log[idx], sizeof(dump_log)); + spin_unlock_irqrestore(&decon_dev->d.event_lock, flags); if (is_skip_dpu_event_dump(log->type, condition)) continue; |