From patchwork Fri Oct 30 01:00:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Abhinav Kumar X-Patchwork-Id: 11868153 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8FB7A14B7 for ; Fri, 30 Oct 2020 01:12:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 64E1E20728 for ; Fri, 30 Oct 2020 01:12:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=mg.codeaurora.org header.i=@mg.codeaurora.org header.b="xHd2UZCW" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725372AbgJ3BMZ (ORCPT ); Thu, 29 Oct 2020 21:12:25 -0400 Received: from z5.mailgun.us ([104.130.96.5]:23112 "EHLO z5.mailgun.us" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725797AbgJ3BMZ (ORCPT ); Thu, 29 Oct 2020 21:12:25 -0400 DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; q=dns/txt; s=smtp; t=1604020344; h=Content-Transfer-Encoding: Content-Type: MIME-Version: References: In-Reply-To: Message-Id: Date: Subject: Cc: To: From: Sender; bh=yrRq+Yyojnj/WiiSBZi31VWL/zQhOFjHtFCa2OEUncA=; b=xHd2UZCWlL2FvU+yD1wTisK1AhXUcNL3oEET486KQ9Ulm0WXnnpMoWAjonzN+aEuSBtm0EnK Q8hMmhjYT/q6RRxp3VWhWTJYOiIpaDl2vRUC00oumIvn6/Ojp+vUqVOSfAp34qwJEzq4QSyJ oiRV5OMA7N2boU6Q3G9wxZWad0A= X-Mailgun-Sending-Ip: 104.130.96.5 X-Mailgun-Sid: WyI1MzIzYiIsICJsaW51eC1hcm0tbXNtQHZnZXIua2VybmVsLm9yZyIsICJiZTllNGEiXQ== Received: from smtp.codeaurora.org (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by smtp-out-n02.prod.us-west-2.postgun.com with SMTP id 5f9b65d9bdb473cf165e46fa (version=TLS1.2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); Fri, 30 Oct 2020 01:01:13 GMT Sender: abhinavk=codeaurora.org@mg.codeaurora.org Received: by smtp.codeaurora.org (Postfix, from userid 1001) id 5E79FC433C6; Fri, 30 Oct 2020 01:01:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-caf-mail-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=ALL_TRUSTED,BAYES_00,SPF_FAIL, URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.0 Received: from abhinavk-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: abhinavk) by smtp.codeaurora.org (Postfix) with ESMTPSA id 28920C433C6; Fri, 30 Oct 2020 01:01:10 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 28920C433C6 Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; spf=fail smtp.mailfrom=abhinavk@codeaurora.org From: Abhinav Kumar To: dri-devel@lists.freedesktop.org Cc: Abhinav Kumar , linux-arm-msm@vger.kernel.org, freedreno@lists.freedesktop.org, robdclark@gmail.com, seanpaul@chromium.org, swboyd@chromium.org, nganji@codeaurora.org, aravindh@codeaurora.org, tanmay@codeaurora.org, khsieh@codeaurora.org, daniel@ffwll.ch, kernel test robot Subject: [PATCH v2 1/4] drm: allow drm_atomic_print_state() to accept any drm_printer Date: Thu, 29 Oct 2020 18:00:58 -0700 Message-Id: <20201030010101.4345-2-abhinavk@codeaurora.org> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20201030010101.4345-1-abhinavk@codeaurora.org> References: <20201030010101.4345-1-abhinavk@codeaurora.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Currently drm_atomic_print_state() internally allocates and uses a drm_info printer. Allow it to accept any drm_printer type so that the API can be leveraged even for taking drm snapshot. Rename the drm_atomic_print_state() to drm_atomic_print_new_state() so that it reflects its functionality better. changes in v2: - Rename the function drm_atomic_print_state to drm_atomic_print_new_state and update the commit text - Fix kbot errors - Add kernel doc for the newly exported function Reported-by: kernel test robot Signed-off-by: Abhinav Kumar Reviewed-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic.c | 29 +++++++++++++++---- drivers/gpu/drm/drm_atomic_uapi.c | 4 ++- drivers/gpu/drm/drm_crtc_internal.h | 4 ++- .../gpu/drm/selftests/test-drm_framebuffer.c | 1 + 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 58527f151984..5df7b67ced78 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2014 Red Hat * Copyright (C) 2014 Intel Corp. + * Copyright (c) 2020, The Linux Foundation. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -1543,9 +1544,21 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set, } EXPORT_SYMBOL(__drm_atomic_helper_set_config); -void drm_atomic_print_state(const struct drm_atomic_state *state) +/** + * drm_atomic_print_new_state - prints drm atomic state + * @state: atomic configuration to check + * @p: drm printer + * + * This functions prints the drm atomic state snapshot using the drm printer + * which is passed to it. This snapshot can be used for debugging purposes. + * + * Note that this function looks into the new state objects and hence its not + * safe to be used after the call to drm_atomic_helper_commit_hw_done(). + * + */ +void drm_atomic_print_new_state(const struct drm_atomic_state *state, + struct drm_printer *p) { - struct drm_printer p = drm_info_printer(state->dev->dev); struct drm_plane *plane; struct drm_plane_state *plane_state; struct drm_crtc *crtc; @@ -1554,17 +1567,23 @@ void drm_atomic_print_state(const struct drm_atomic_state *state) struct drm_connector_state *connector_state; int i; + if (!p) { + DRM_ERROR("invalid drm printer\n"); + return; + } + DRM_DEBUG_ATOMIC("checking %p\n", state); for_each_new_plane_in_state(state, plane, plane_state, i) - drm_atomic_plane_print_state(&p, plane_state); + drm_atomic_plane_print_state(p, plane_state); for_each_new_crtc_in_state(state, crtc, crtc_state, i) - drm_atomic_crtc_print_state(&p, crtc_state); + drm_atomic_crtc_print_state(p, crtc_state); for_each_new_connector_in_state(state, connector, connector_state, i) - drm_atomic_connector_print_state(&p, connector_state); + drm_atomic_connector_print_state(p, connector_state); } +EXPORT_SYMBOL(drm_atomic_print_new_state); static void __drm_state_dump(struct drm_device *dev, struct drm_printer *p, bool take_locks) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 25c269bc4681..b4b3cb28a8ea 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -2,6 +2,7 @@ * Copyright (C) 2014 Red Hat * Copyright (C) 2014 Intel Corp. * Copyright (C) 2018 Intel Corp. + * Copyright (c) 2020, The Linux Foundation. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -1294,6 +1295,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, struct drm_out_fence_state *fence_state; int ret = 0; unsigned int i, j, num_fences; + struct drm_printer p = drm_info_printer(dev->dev); /* disallow for drivers not supporting atomic: */ if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) @@ -1413,7 +1415,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, ret = drm_atomic_nonblocking_commit(state); } else { if (drm_debug_enabled(DRM_UT_STATE)) - drm_atomic_print_state(state); + drm_atomic_print_new_state(state, &p); ret = drm_atomic_commit(state); } diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index da96b2f64d7e..2bd56ec9fb0e 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h @@ -5,6 +5,7 @@ * Jesse Barnes * Copyright © 2014 Intel Corporation * Daniel Vetter + * Copyright (c) 2020, The Linux Foundation. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -233,7 +234,8 @@ int __drm_atomic_helper_disable_plane(struct drm_plane *plane, int __drm_atomic_helper_set_config(struct drm_mode_set *set, struct drm_atomic_state *state); -void drm_atomic_print_state(const struct drm_atomic_state *state); +void drm_atomic_print_new_state(const struct drm_atomic_state *state, + struct drm_printer *p); /* drm_atomic_uapi.c */ int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state, diff --git a/drivers/gpu/drm/selftests/test-drm_framebuffer.c b/drivers/gpu/drm/selftests/test-drm_framebuffer.c index 2d29ea6f92e2..9296c68cbe71 100644 --- a/drivers/gpu/drm/selftests/test-drm_framebuffer.c +++ b/drivers/gpu/drm/selftests/test-drm_framebuffer.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "../drm_crtc_internal.h" From patchwork Fri Oct 30 01:00:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abhinav Kumar X-Patchwork-Id: 11868159 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E80FE697 for ; Fri, 30 Oct 2020 01:12:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B397A20747 for ; Fri, 30 Oct 2020 01:12:38 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=mg.codeaurora.org header.i=@mg.codeaurora.org header.b="WYaGJC1F" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726094AbgJ3BMi (ORCPT ); Thu, 29 Oct 2020 21:12:38 -0400 Received: from m42-4.mailgun.net ([69.72.42.4]:18135 "EHLO m42-4.mailgun.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725797AbgJ3BMh (ORCPT ); Thu, 29 Oct 2020 21:12:37 -0400 DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; q=dns/txt; s=smtp; t=1604020355; h=Content-Transfer-Encoding: MIME-Version: References: In-Reply-To: Message-Id: Date: Subject: Cc: To: From: Sender; bh=OVb2izspCWDda0Ouuxpa1iadH85jmfnpjruFmYTu4QQ=; b=WYaGJC1FR1p31jq2cw5HnADD2Fqg05QGisyb309RVC5u2tRszYYALrVuSrs5H+Y36vzhn6Z+ fgiwDDsf8ibNKolhPoljqQ0mEYxJTzzQpc2Sgr3AzRoMpzDtjKqfXzkB+foLvvn5+FZ7CwZ3 RPRs+mU/TX03rW0RmqZaobYLOSQ= X-Mailgun-Sending-Ip: 69.72.42.4 X-Mailgun-Sid: WyI1MzIzYiIsICJsaW51eC1hcm0tbXNtQHZnZXIua2VybmVsLm9yZyIsICJiZTllNGEiXQ== Received: from smtp.codeaurora.org (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by smtp-out-n02.prod.us-west-2.postgun.com with SMTP id 5f9b65edc3d7c9858abf8d90 (version=TLS1.2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); Fri, 30 Oct 2020 01:01:33 GMT Sender: abhinavk=codeaurora.org@mg.codeaurora.org Received: by smtp.codeaurora.org (Postfix, from userid 1001) id 9860EC433FF; Fri, 30 Oct 2020 01:01:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-caf-mail-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=ALL_TRUSTED,BAYES_00,SPF_FAIL, URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.0 Received: from abhinavk-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: abhinavk) by smtp.codeaurora.org (Postfix) with ESMTPSA id C50A6C433C8; Fri, 30 Oct 2020 01:01:29 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org C50A6C433C8 Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; spf=fail smtp.mailfrom=abhinavk@codeaurora.org From: Abhinav Kumar To: dri-devel@lists.freedesktop.org Cc: Abhinav Kumar , linux-arm-msm@vger.kernel.org, freedreno@lists.freedesktop.org, robdclark@gmail.com, seanpaul@chromium.org, swboyd@chromium.org, nganji@codeaurora.org, aravindh@codeaurora.org, tanmay@codeaurora.org, khsieh@codeaurora.org, daniel@ffwll.ch, kernel test robot Subject: [PATCH v2 2/4] drm/msm/dpu: add support to dump dpu registers Date: Thu, 29 Oct 2020 18:00:59 -0700 Message-Id: <20201030010101.4345-3-abhinavk@codeaurora.org> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20201030010101.4345-1-abhinavk@codeaurora.org> References: <20201030010101.4345-1-abhinavk@codeaurora.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Add the dpu_dbg module which adds supports to dump dpu registers which can be used in case of error conditions. changes in v2: Fix kbot errors Reported-by: kernel test robot Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/Makefile | 2 + drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.c | 316 ++++++++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.h | 273 +++++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_dbg_util.c | 314 +++++++++++++++++ .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 4 +- drivers/gpu/drm/msm/msm_drv.c | 6 +- 6 files changed, 913 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_dbg_util.c diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 340682cd0f32..96bd1398edac 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -54,6 +54,8 @@ msm-y := \ disp/dpu1/dpu_core_irq.o \ disp/dpu1/dpu_core_perf.o \ disp/dpu1/dpu_crtc.o \ + disp/dpu1/dpu_dbg.o \ + disp/dpu1/dpu_dbg_util.o \ disp/dpu1/dpu_encoder.o \ disp/dpu1/dpu_encoder_phys_cmd.o \ disp/dpu1/dpu_encoder_phys_vid.o \ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.c new file mode 100644 index 000000000000..f83682668e87 --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.c @@ -0,0 +1,316 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2009-2020, The Linux Foundation. All rights reserved. + */ + +#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ + +#include "dpu_dbg.h" +#include "dpu_hw_catalog.h" + +/* global dpu debug base structure */ +static struct dpu_dbg_base dpu_dbg; + + +#ifdef CONFIG_DEV_COREDUMP +static ssize_t dpu_devcoredump_read(char *buffer, loff_t offset, + size_t count, void *data, size_t datalen) +{ + struct drm_print_iterator iter; + struct drm_printer p; + + iter.data = buffer; + iter.offset = 0; + iter.start = offset; + iter.remain = count; + + p = drm_coredump_printer(&iter); + + drm_printf(&p, "---\n"); + + drm_printf(&p, "module: " KBUILD_MODNAME "\n"); + drm_printf(&p, "dpu devcoredump\n"); + drm_printf(&p, "timestamp %lld\n", ktime_to_ns(dpu_dbg.timestamp)); + + dpu_dbg.dpu_dbg_printer = &p; + dpu_dbg.enable_reg_dump = DPU_DBG_DUMP_IN_COREDUMP; + + drm_printf(&p, "===================dpu regs================\n"); + + _dpu_dump_array(&dpu_dbg, dpu_dbg.req_dump_blks, + ARRAY_SIZE(dpu_dbg.req_dump_blks), + dpu_dbg.work_panic, "evtlog_workitem", + dpu_dbg.dump_all); + + drm_printf(&p, "===================dpu drm state================\n"); + + if (dpu_dbg.atomic_state) + drm_atomic_print_new_state(dpu_dbg.atomic_state, + &p); + + return count - iter.remain; +} + +static void dpu_devcoredump_free(void *data) +{ + if (dpu_dbg.atomic_state) { + drm_atomic_state_put(dpu_dbg.atomic_state); + dpu_dbg.atomic_state = NULL; + } + dpu_dbg.coredump_pending = false; +} + +static void dpu_devcoredump_capture_state(void) +{ + struct drm_device *ddev; + struct drm_modeset_acquire_ctx ctx; + + dpu_dbg.timestamp = ktime_get(); + + ddev = dpu_dbg.drm_dev; + + drm_modeset_acquire_init(&ctx, 0); + + while (drm_modeset_lock_all_ctx(ddev, &ctx) != 0) + drm_modeset_backoff(&ctx); + + dpu_dbg.atomic_state = drm_atomic_helper_duplicate_state(ddev, + &ctx); + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); +} +#else +static void dpu_devcoredump_capture_state(void) +{ +} +#endif /* CONFIG_DEV_COREDUMP */ + +/** + * _dpu_dump_work - deferred dump work function + * @work: work structure + */ +static void _dpu_dump_work(struct kthread_work *work) +{ + /* reset the enable_reg_dump to default before every dump */ + dpu_dbg.enable_reg_dump = DEFAULT_REGDUMP; + + _dpu_dump_array(&dpu_dbg, dpu_dbg.req_dump_blks, + ARRAY_SIZE(dpu_dbg.req_dump_blks), + dpu_dbg.work_panic, "evtlog_workitem", + dpu_dbg.dump_all); + + dpu_devcoredump_capture_state(); + +#ifdef CONFIG_DEV_COREDUMP + if (dpu_dbg.enable_reg_dump & DPU_DBG_DUMP_IN_MEM) { + dev_coredumpm(dpu_dbg.dev, THIS_MODULE, &dpu_dbg, 0, GFP_KERNEL, + dpu_devcoredump_read, dpu_devcoredump_free); + dpu_dbg.coredump_pending = true; + } +#endif +} + +void dpu_dbg_dump(enum dpu_dbg_dump_context dump_mode, const char *name, ...) +{ + int i, index = 0; + bool do_panic = false; + bool dump_all = false; + va_list args; + char *blk_name = NULL; + struct dpu_dbg_reg_base *blk_base = NULL; + struct dpu_dbg_reg_base **blk_arr; + u32 blk_len; + + /* + * if there is a coredump pending return immediately till dump + * if read by userspace or timeout happens + */ + if (((dpu_dbg.enable_reg_dump == DPU_DBG_DUMP_IN_MEM) || + (dpu_dbg.enable_reg_dump == DPU_DBG_DUMP_IN_COREDUMP)) && + dpu_dbg.coredump_pending) { + pr_debug("coredump is pending read\n"); + return; + } + + blk_arr = &dpu_dbg.req_dump_blks[0]; + blk_len = ARRAY_SIZE(dpu_dbg.req_dump_blks); + + memset(dpu_dbg.req_dump_blks, 0, + sizeof(dpu_dbg.req_dump_blks)); + dpu_dbg.dump_all = false; + dpu_dbg.dump_mode = dump_mode; + + va_start(args, name); + i = 0; + while ((blk_name = va_arg(args, char*))) { + + if (IS_ERR_OR_NULL(blk_name)) + break; + + blk_base = _dpu_dump_get_blk_addr(&dpu_dbg, blk_name); + if (blk_base) { + if (index < blk_len) { + blk_arr[index] = blk_base; + index++; + } else { + pr_err("insufficient space to dump %s\n", + blk_name); + } + } + + if (!strcmp(blk_name, "all")) + dump_all = true; + + if (!strcmp(blk_name, "panic")) + do_panic = true; + + } + va_end(args); + + dpu_dbg.work_panic = do_panic; + dpu_dbg.dump_all = dump_all; + + kthread_queue_work(dpu_dbg.dump_worker, + &dpu_dbg.dump_work); + +} + +int dpu_dbg_init(struct device *dev) +{ + if (!dev) { + pr_err("invalid params\n"); + return -EINVAL; + } + + mutex_init(&dpu_dbg.mutex); + INIT_LIST_HEAD(&dpu_dbg.reg_base_list); + dpu_dbg.dev = dev; + + dpu_dbg.work_panic = false; + dpu_dbg.enable_reg_dump = DEFAULT_REGDUMP; + + dpu_dbg.dump_worker = kthread_create_worker(0, "%s", "dpu_dbg"); + if (IS_ERR(dpu_dbg.dump_worker)) + dev_err(dev, "failed to create dpu dbg task\n"); + + kthread_init_work(&dpu_dbg.dump_work, _dpu_dump_work); + + pr_info("dump:%d\n", dpu_dbg.enable_reg_dump); + + return 0; +} + +void dpu_dbg_register_drm_dev(struct drm_device *ddev) +{ + dpu_dbg.drm_dev = ddev; +} + +static void dpu_dbg_reg_base_destroy(void) +{ + struct dpu_dbg_reg_range *range_node, *range_tmp; + struct dpu_dbg_reg_base *blk_base, *blk_tmp; + struct dpu_dbg_base *dbg_base = &dpu_dbg; + + /* if the dbg init failed or was never called */ + if (!dbg_base || !dpu_dbg.dev) + return; + + list_for_each_entry_safe(blk_base, blk_tmp, &dbg_base->reg_base_list, + reg_base_head) { + list_for_each_entry_safe(range_node, range_tmp, + &blk_base->sub_range_list, head) { + list_del(&range_node->head); + kfree(range_node); + } + list_del(&blk_base->reg_base_head); + kfree(blk_base); + } +} + +/** + * dpu_dbg_destroy - destroy dpu debug facilities + */ +void dpu_dbg_destroy(void) +{ + if (dpu_dbg.dump_worker) + kthread_destroy_worker(dpu_dbg.dump_worker); + dpu_dbg_reg_base_destroy(); + mutex_destroy(&dpu_dbg.mutex); +} + +int dpu_dbg_reg_register_base(const char *name, void __iomem *base, + size_t max_offset) +{ + struct dpu_dbg_base *dbg_base = &dpu_dbg; + struct dpu_dbg_reg_base *reg_base; + + if (!name || !strlen(name)) { + pr_err("no debug name provided\n"); + return -EINVAL; + } + + reg_base = kzalloc(sizeof(*reg_base), GFP_KERNEL); + if (!reg_base) + return -ENOMEM; + + strlcpy(reg_base->name, name, sizeof(reg_base->name)); + reg_base->base = base; + reg_base->max_offset = max_offset; + reg_base->off = 0; + reg_base->cnt = DEFAULT_BASE_REG_CNT; + reg_base->reg_dump = NULL; + + /* Initialize list to make sure check for null list will be valid */ + INIT_LIST_HEAD(®_base->sub_range_list); + + pr_debug("%s base: %pK max_offset 0x%zX\n", reg_base->name, + reg_base->base, reg_base->max_offset); + + list_add(®_base->reg_base_head, &dbg_base->reg_base_list); + + return 0; +} + +void dpu_dbg_reg_register_dump_range(const char *base_name, + const char *range_name, u32 offset_start, u32 offset_end, + uint32_t xin_id) +{ + struct dpu_dbg_reg_base *reg_base; + struct dpu_dbg_reg_range *range; + + reg_base = _dpu_dump_get_blk_addr(&dpu_dbg, base_name); + if (!reg_base) { + pr_err("error: for range %s unable to locate base %s\n", + range_name, base_name); + return; + } + + if (!range_name || strlen(range_name) == 0) { + pr_err("%pS: bad range name, base_name %s, offset_start 0x%X, end 0x%X\n", + __builtin_return_address(0), base_name, + offset_start, offset_end); + return; + } + + if (offset_end - offset_start < REG_DUMP_ALIGN || + offset_start > offset_end) { + pr_err("%pS: bad range, base_name %s, range_name %s, offset_start 0x%X, end 0x%X\n", + __builtin_return_address(0), base_name, + range_name, offset_start, offset_end); + return; + } + + range = kzalloc(sizeof(*range), GFP_KERNEL); + if (!range) + return; + + strlcpy(range->range_name, range_name, sizeof(range->range_name)); + range->offset.start = offset_start; + range->offset.end = offset_end; + range->xin_id = xin_id; + list_add_tail(&range->head, ®_base->sub_range_list); + + pr_debug("base %s, range %s, start 0x%X, end 0x%X\n", + base_name, range->range_name, + range->offset.start, range->offset.end); +} diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.h new file mode 100644 index 000000000000..2cea13288cef --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.h @@ -0,0 +1,273 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef DPU_DBG_H_ +#define DPU_DBG_H_ + +#include +#include +#include "../../../drm_crtc_internal.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DPU_DBG_DUMP_DATA_LIMITER (NULL) + +enum dpu_dbg_dump_flag { + DPU_DBG_DUMP_IN_LOG = BIT(0), + DPU_DBG_DUMP_IN_MEM = BIT(1), + DPU_DBG_DUMP_IN_COREDUMP = BIT(2), +}; + +enum dpu_dbg_dump_context { + DPU_DBG_DUMP_PROC_CTX, + DPU_DBG_DUMP_CLK_ENABLED_CTX, +}; + +#define DPU_DBG_BASE_MAX 10 + +#define DEFAULT_PANIC 0 +#define DEFAULT_REGDUMP DPU_DBG_DUMP_IN_MEM +#define DEFAULT_BASE_REG_CNT DEFAULT_MDSS_HW_BLOCK_SIZE +#define ROW_BYTES 16 +#define RANGE_NAME_LEN 40 +#define REG_BASE_NAME_LEN 80 + +/* print debug ranges in groups of 4 u32s */ +#define REG_DUMP_ALIGN 16 + +/** + * struct dpu_dbg_reg_offset - tracking for start and end of region + * @start: start offset + * @start: end offset + */ +struct dpu_dbg_reg_offset { + u32 start; + u32 end; +}; + +/** + * struct dpu_dbg_reg_range - register dumping named sub-range + * @head: head of this node + * @reg_dump: address for the mem dump + * @range_name: name of this range + * @offset: offsets for range to dump + * @xin_id: client xin id + */ +struct dpu_dbg_reg_range { + struct list_head head; + u32 *reg_dump; + char range_name[RANGE_NAME_LEN]; + struct dpu_dbg_reg_offset offset; + uint32_t xin_id; +}; + +/** + * struct dpu_dbg_reg_base - register region base. + * may sub-ranges: sub-ranges are used for dumping + * or may not have sub-ranges: dumping is base -> max_offset + * @reg_base_head: head of this node + * @sub_range_list: head to the list with dump ranges + * @name: register base name + * @base: base pointer + * @off: cached offset of region for manual register dumping + * @cnt: cached range of region for manual register dumping + * @max_offset: length of region + * @buf: buffer used for manual register dumping + * @buf_len: buffer length used for manual register dumping + * @reg_dump: address for the mem dump if no ranges used + * @cb: callback for external dump function, null if not defined + * @cb_ptr: private pointer to callback function + */ +struct dpu_dbg_reg_base { + struct list_head reg_base_head; + struct list_head sub_range_list; + char name[REG_BASE_NAME_LEN]; + void __iomem *base; + size_t off; + size_t cnt; + size_t max_offset; + char *buf; + size_t buf_len; + u32 *reg_dump; + void (*cb)(void *ptr); + void *cb_ptr; +}; + +/** + * struct dpu_dbg_base - global sde debug base structure + * @evtlog: event log instance + * @reg_base_list: list of register dumping regions + * @dev: device pointer + * @drm_dev: drm device pointer + * @mutex: mutex to serialize access to serialze dumps, debugfs access + * @req_dump_blks: list of blocks requested for dumping + * @work_panic: panic after dump if internal user passed "panic" special region + * @enable_reg_dump: whether to dump registers into memory, kernel log, or both + * @dump_all: dump all entries in register dump + * @coredump_pending: coredump is pending read from userspace + * @atomic_state: atomic state duplicated at the time of the error + * @dump_worker: kworker thread which runs the dump work + * @dump_work: kwork which dumps the registers and drm state + * @timestamp: timestamp at which the coredump was captured + * @dpu_dbg_printer: drm printer handle used to take drm snapshot + * @dump_mode: decides whether the data is dumped in memory or logs + */ +struct dpu_dbg_base { + struct list_head reg_base_list; + struct device *dev; + struct drm_device *drm_dev; + struct mutex mutex; + + struct dpu_dbg_reg_base *req_dump_blks[DPU_DBG_BASE_MAX]; + + bool work_panic; + u32 enable_reg_dump; + + bool dump_all; + bool coredump_pending; + + struct drm_atomic_state *atomic_state; + + struct kthread_worker *dump_worker; + struct kthread_work dump_work; + ktime_t timestamp; + + struct drm_printer *dpu_dbg_printer; + + enum dpu_dbg_dump_context dump_mode; +}; + +struct dpu_dbg_power_ctrl { + void *handle; + void *client; + int (*enable_fn)(void *handle, void *client, bool enable); +}; + + +/** + * DPU_DBG_DUMP - trigger dumping of all dpu_dbg facilities + * @va_args: list of named register dump ranges and regions to dump, as + * registered previously through dpu_dbg_reg_register_base and + * dpu_dbg_reg_register_dump_range. + * Including the special name "panic" will trigger a panic after + * the dumping work has completed. + */ +#define DPU_DBG_DUMP(...) dpu_dbg_dump(DPU_DBG_DUMP_PROC_CTX, __func__, \ + ##__VA_ARGS__, DPU_DBG_DUMP_DATA_LIMITER) + +/** + * DPU_DBG_DUMP_CLK_EN - trigger dumping of all dpu_dbg facilities, without clk + * @va_args: list of named register dump ranges and regions to dump, as + * registered previously through dpu_dbg_reg_register_base and + * dpu_dbg_reg_register_dump_range. + * Including the special name "panic" will trigger a panic after + * the dumping work has completed. + */ +#define DPU_DBG_DUMP_CLK_EN(...) dpu_dbg_dump(DPU_DBG_DUMP_CLK_ENABLED_CTX, \ + __func__, ##__VA_ARGS__, DPU_DBG_DUMP_DATA_LIMITER) + +/** + * dpu_dbg_init - initialize global sde debug facilities: evtlog, regdump + * @dev: device handle + * Returns: 0 or -ERROR + */ +int dpu_dbg_init(struct device *dev); + +/** + * dpu_dbg_register_drm_dev - register a drm device with the dpu dbg module + * @ddev: drm device hangle + * Returns: void + */ +void dpu_dbg_register_drm_dev(struct drm_device *ddev); + +/** + * dpu_dbg_destroy - destroy the global sde debug facilities + * Returns: none + */ +void dpu_dbg_destroy(void); + +/** + * dpu_dbg_dump - trigger dumping of all dpu_dbg facilities + * @queue_work: whether to queue the dumping work to the work_struct + * @name: string indicating origin of dump + * @va_args: list of named register dump ranges and regions to dump, as + * registered previously through dpu_dbg_reg_register_base and + * dpu_dbg_reg_register_dump_range. + * Including the special name "panic" will trigger a panic after + * the dumping work has completed. + * Returns: none + */ +void dpu_dbg_dump(enum dpu_dbg_dump_context mode, const char *name, ...); + +/** + * dpu_dbg_reg_register_base - register a hw register address section for later + * dumping. call this before calling dpu_dbg_reg_register_dump_range + * to be able to specify sub-ranges within the base hw range. + * @name: name of base region + * @base: base pointer of region + * @max_offset: length of region + * Returns: 0 or -ERROR + */ +int dpu_dbg_reg_register_base(const char *name, void __iomem *base, + size_t max_offset); + +/** + * dpu_dbg_reg_register_dump_range - register a hw register sub-region for + * later register dumping associated with base specified by + * dpu_dbg_reg_register_base + * @base_name: name of base region + * @range_name: name of sub-range within base region + * @offset_start: sub-range's start offset from base's base pointer + * @offset_end: sub-range's end offset from base's base pointer + * @xin_id: xin id + * Returns: none + */ +void dpu_dbg_reg_register_dump_range(const char *base_name, + const char *range_name, u32 offset_start, u32 offset_end, + uint32_t xin_id); + +/** + * dpu_dbg_set_sde_top_offset - set the target specific offset from mdss base + * address of the top registers. Used for accessing debug bus controls. + * @blk_off: offset from mdss base of the top block + */ +void dpu_dbg_set_sde_top_offset(u32 blk_off); + +/** + * _dpu_dump_array - dump array of register bases + * @blk_arr: array of register base pointers + * @len: length of blk_arr + * @do_panic: whether to trigger a panic after dumping + * @name: string indicating origin of dump + * @dump_all: dump all regs + */ +void _dpu_dump_array(struct dpu_dbg_base *dbg_base, + struct dpu_dbg_reg_base *blk_arr[], + u32 len, bool do_panic, const char *name, bool dump_all); + +/** + * _dpu_dump_get_blk_addr - retrieve register block address by name + * @blk_name: register blk name + * @Return: register blk base, or NULL + */ +struct dpu_dbg_reg_base *_dpu_dump_get_blk_addr(struct dpu_dbg_base *dbg_base, + const char *blk_name); + +#endif /* DPU_DBG_H_ */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_dbg_util.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_dbg_util.c new file mode 100644 index 000000000000..30e03674bfd6 --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_dbg_util.c @@ -0,0 +1,314 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ + +#include "dpu_dbg.h" +#include "dpu_hw_catalog.h" + +/** + * _sde_power_check - check if power needs to enabled + * @dump_mode: to check if power need to be enabled + * Return: true if success; false otherwise + */ +static inline bool _dpu_power_check(enum dpu_dbg_dump_context dump_mode) +{ + return (dump_mode == DPU_DBG_DUMP_CLK_ENABLED_CTX) ? false : true; +} + +/** + * _dpu_dump_reg - helper function for dumping rotator register set content + * @dump_name: register set name + * @reg_dump_flag: dumping flag controlling in-log/memory dump location + * @base_addr: starting address of io region for calculating offsets to print + * @addr: starting address offset for dumping + * @len_bytes: range of the register set + * @dump_mem: output buffer for memory dump location option + * @from_isr: whether being called from isr context + */ +static void _dpu_dump_reg(struct dpu_dbg_base *dbg_base, + const char *dump_name, u32 reg_dump_flag, + void __iomem *base_addr, void __iomem *addr, + size_t len_bytes, u32 **dump_mem) +{ + u32 in_log, in_mem, len_align, len_padded, in_dump; + u32 *dump_addr = NULL; + void __iomem *end_addr; + int i; + int rc; + + if (!len_bytes) + return; + + in_log = (reg_dump_flag & DPU_DBG_DUMP_IN_LOG); + in_mem = (reg_dump_flag & DPU_DBG_DUMP_IN_MEM); + in_dump = (reg_dump_flag & DPU_DBG_DUMP_IN_COREDUMP); + + pr_debug("%s: reg_dump_flag=%d in_log=%d in_mem=%d\n", + dump_name, reg_dump_flag, in_log, in_mem); + + if (!in_log && !in_mem && !in_dump) + return; + + if (in_log) + dev_info(dbg_base->dev, "%s: start_offset 0x%lx len 0x%zx\n", + dump_name, (unsigned long)(addr - base_addr), + len_bytes); + + len_align = (len_bytes + REG_DUMP_ALIGN - 1) / REG_DUMP_ALIGN; + len_padded = len_align * REG_DUMP_ALIGN; + end_addr = addr + len_bytes; + + if (in_mem || in_dump) { + if (dump_mem && !(*dump_mem)) + *dump_mem = devm_kzalloc(dbg_base->dev, len_padded, + GFP_KERNEL); + + if (dump_mem && *dump_mem) { + dump_addr = *dump_mem; + dev_info(dbg_base->dev, + "%s: start_addr:0x%pK len:0x%x reg_offset=0x%lx\n", + dump_name, dump_addr, len_padded, + (unsigned long)(addr - base_addr)); + if (in_dump) + drm_printf(dbg_base->dpu_dbg_printer, + "%s: start_addr:0x%pK len:0x%x reg_offset=0x%lx\n", + dump_name, dump_addr, + len_padded, + (unsigned long)(addr - + base_addr)); + } else { + in_mem = 0; + pr_err("dump_mem: kzalloc fails!\n"); + } + } + + if (_dpu_power_check(dbg_base->dump_mode)) { + rc = pm_runtime_get_sync(dbg_base->dev); + if (rc < 0) { + pr_err("failed to enable power %d\n", rc); + return; + } + } + + for (i = 0; i < len_align; i++) { + u32 x0, x4, x8, xc; + + if (in_log || in_mem) { + x0 = (addr < end_addr) ? readl_relaxed(addr + 0x0) : 0; + x4 = (addr + 0x4 < end_addr) ? readl_relaxed(addr + + 0x4) : 0; + x8 = (addr + 0x8 < end_addr) ? readl_relaxed(addr + + 0x8) : 0; + xc = (addr + 0xc < end_addr) ? readl_relaxed(addr + + 0xc) : 0; + } + + if (in_log) + dev_info(dbg_base->dev, + "0x%lx : %08x %08x %08x %08x\n", + (unsigned long)(addr - base_addr), + x0, x4, x8, xc); + + if (dump_addr && in_mem) { + dump_addr[i * 4] = x0; + dump_addr[i * 4 + 1] = x4; + dump_addr[i * 4 + 2] = x8; + dump_addr[i * 4 + 3] = xc; + } + + if (in_dump) { + drm_printf(dbg_base->dpu_dbg_printer, + "0x%lx : %08x %08x %08x %08x\n", + (unsigned long)(addr - base_addr), + dump_addr[i * 4], + dump_addr[i * 4 + 1], + dump_addr[i * 4 + 2], + dump_addr[i * 4 + 3]); + + } + + addr += REG_DUMP_ALIGN; + } + + if (_dpu_power_check(dbg_base->dump_mode)) + pm_runtime_put_sync(dbg_base->dev); +} + +/** + * _dpu_dbg_get_dump_range - helper to retrieve dump length for a range node + * @range_node: range node to dump + * @max_offset: max offset of the register base + * @Return: length + */ +static u32 _dpu_dbg_get_dump_range(struct dpu_dbg_reg_offset *range_node, + size_t max_offset) +{ + u32 length = 0; + + if (range_node->start == 0 && range_node->end == 0) { + length = max_offset; + } else if (range_node->start < max_offset) { + if (range_node->end > max_offset) + length = max_offset - range_node->start; + else if (range_node->start < range_node->end) + length = range_node->end - range_node->start; + } + + return length; +} + +static int _dpu_dump_reg_range_cmp(void *priv, struct list_head *a, + struct list_head *b) +{ + struct dpu_dbg_reg_range *ar, *br; + + if (!a || !b) + return 0; + + ar = container_of(a, struct dpu_dbg_reg_range, head); + br = container_of(b, struct dpu_dbg_reg_range, head); + + return ar->offset.start - br->offset.start; +} + +/** + * _dpu_dump_reg_by_ranges - dump ranges or full range of the register blk base + * @dbg: register blk base structure + * @reg_dump_flag: dump target, memory, kernel log, or both + */ +static void _dpu_dump_reg_by_ranges(struct dpu_dbg_base *dbg_base, + struct dpu_dbg_reg_base *dbg, + u32 reg_dump_flag) +{ + void __iomem *addr; + size_t len; + struct dpu_dbg_reg_range *range_node; + + if (!dbg || !(dbg->base || dbg->cb)) { + pr_err("dbg base is null!\n"); + return; + } + + dev_info(dbg_base->dev, "%s:=========%s DUMP=========\n", __func__, + dbg->name); + + if (reg_dump_flag & DPU_DBG_DUMP_IN_COREDUMP) + drm_printf(dbg_base->dpu_dbg_printer, + "%s:=========%s DUMP=========\n", + __func__, dbg->name); + + if (dbg->cb) { + dbg->cb(dbg->cb_ptr); + /* If there is a list to dump the registers by ranges, use the ranges */ + } else if (!list_empty(&dbg->sub_range_list)) { + /* sort the list by start address first */ + list_sort(NULL, &dbg->sub_range_list, _dpu_dump_reg_range_cmp); + list_for_each_entry(range_node, &dbg->sub_range_list, head) { + len = _dpu_dbg_get_dump_range(&range_node->offset, + dbg->max_offset); + addr = dbg->base + range_node->offset.start; + + pr_debug("%s: range_base=0x%pK start=0x%x end=0x%x\n", + range_node->range_name, + addr, range_node->offset.start, + range_node->offset.end); + + _dpu_dump_reg(dbg_base, range_node->range_name, + reg_dump_flag, + dbg->base, addr, len, + &range_node->reg_dump); + } + } else { + /* If there is no list to dump ranges, dump all registers */ + dev_info(dbg_base->dev, + "Ranges not found, will dump full registers\n"); + dev_info(dbg_base->dev, "base:0x%pK len:0x%zx\n", dbg->base, + dbg->max_offset); + addr = dbg->base; + len = dbg->max_offset; + _dpu_dump_reg(dbg_base, dbg->name, reg_dump_flag, + dbg->base, addr, len, + &dbg->reg_dump); + } +} + +/** + * _dpu_dump_reg_by_blk - dump a named register base region + * @blk_name: register blk name + */ +static void _dpu_dump_reg_by_blk(struct dpu_dbg_base *dbg_base, + const char *blk_name) +{ + struct dpu_dbg_reg_base *blk_base; + + if (!dbg_base) + return; + + list_for_each_entry(blk_base, &dbg_base->reg_base_list, reg_base_head) { + if (strlen(blk_base->name) && + !strcmp(blk_base->name, blk_name)) { + _dpu_dump_reg_by_ranges(dbg_base, blk_base, + dbg_base->enable_reg_dump); + break; + } + } +} + +/** + * _dpu_dump_reg_all - dump all register regions + */ +static void _dpu_dump_reg_all(struct dpu_dbg_base *dbg_base) +{ + struct dpu_dbg_reg_base *blk_base; + + if (!dbg_base) + return; + + list_for_each_entry(blk_base, &dbg_base->reg_base_list, reg_base_head) { + + if (!strlen(blk_base->name)) + continue; + + _dpu_dump_reg_by_blk(dbg_base, blk_base->name); + } +} + +struct dpu_dbg_reg_base *_dpu_dump_get_blk_addr(struct dpu_dbg_base *dbg_base, + const char *blk_name) +{ + struct dpu_dbg_reg_base *blk_base; + + list_for_each_entry(blk_base, &dbg_base->reg_base_list, reg_base_head) + if (strlen(blk_base->name) && !strcmp(blk_base->name, blk_name)) + return blk_base; + + return NULL; +} + +void _dpu_dump_array(struct dpu_dbg_base *dbg_base, + struct dpu_dbg_reg_base *blk_arr[], + u32 len, bool do_panic, const char *name, bool dump_all) +{ + int i; + + mutex_lock(&dbg_base->mutex); + + if (dump_all || !blk_arr || !len) { + _dpu_dump_reg_all(dbg_base); + } else { + for (i = 0; i < len; i++) { + if (blk_arr[i] != NULL) + _dpu_dump_reg_by_ranges(dbg_base, + blk_arr[i], + dbg_base->enable_reg_dump); + } + } + + if (do_panic) + panic(name); + + mutex_unlock(&dbg_base->mutex); +} diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index 3544af1a45c5..b2ab22be4c55 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. */ #ifndef _DPU_HW_CATALOG_H @@ -52,6 +52,8 @@ #define DPU_HW_BLK_NAME_LEN 16 +/* default size of valid register space for MDSS_HW block (offset 0) */ +#define DEFAULT_MDSS_HW_BLOCK_SIZE 0x5C #define MAX_IMG_WIDTH 0x3fff #define MAX_IMG_HEIGHT 0x3fff diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 49685571dc0e..f6fb0187388f 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018, 2020 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark */ @@ -17,6 +17,7 @@ #include #include #include +#include "dpu_dbg.h" #include "msm_drv.h" #include "msm_debugfs.h" @@ -268,6 +269,8 @@ static int msm_drm_uninit(struct device *dev) msm_fbdev_free(ddev); #endif + dpu_dbg_destroy(); + drm_mode_config_cleanup(ddev); pm_runtime_get_sync(dev); @@ -1303,6 +1306,7 @@ static int msm_pdev_probe(struct platform_device *pdev) fail: of_platform_depopulate(&pdev->dev); + dpu_dbg_destroy(); return ret; } From patchwork Fri Oct 30 01:01:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abhinav Kumar X-Patchwork-Id: 11868157 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9906814B7 for ; Fri, 30 Oct 2020 01:12:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5A7D520729 for ; Fri, 30 Oct 2020 01:12:38 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=mg.codeaurora.org header.i=@mg.codeaurora.org header.b="ZQklHe9a" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726099AbgJ3BMh (ORCPT ); Thu, 29 Oct 2020 21:12:37 -0400 Received: from z5.mailgun.us ([104.130.96.5]:16138 "EHLO z5.mailgun.us" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726094AbgJ3BMh (ORCPT ); Thu, 29 Oct 2020 21:12:37 -0400 DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; q=dns/txt; s=smtp; t=1604020356; h=Content-Transfer-Encoding: MIME-Version: References: In-Reply-To: Message-Id: Date: Subject: Cc: To: From: Sender; bh=sw2mC7RIgv80MDXRWPdQ3efL5iAOzqk3BZUG5+YmdtA=; b=ZQklHe9a7fQfIAs3lxDAe62bN/TH4QJMmziNuDpQog+FNc5k/XEGoX/VmFlDzHCY4VbbNG2A Y4+J50CDYKr9zI7bpGTfYQK14W4VQC/rLLMZSYkai/Vgug04D8zIKyy5FMCJn7NJHjAV5bM4 /227I6Hh/0JwM9KM27fsOYQtnRE= X-Mailgun-Sending-Ip: 104.130.96.5 X-Mailgun-Sid: WyI1MzIzYiIsICJsaW51eC1hcm0tbXNtQHZnZXIua2VybmVsLm9yZyIsICJiZTllNGEiXQ== Received: from smtp.codeaurora.org (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by smtp-out-n01.prod.us-west-2.postgun.com with SMTP id 5f9b65eec3d7c9858abf8f55 (version=TLS1.2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); Fri, 30 Oct 2020 01:01:34 GMT Sender: abhinavk=codeaurora.org@mg.codeaurora.org Received: by smtp.codeaurora.org (Postfix, from userid 1001) id A5D09C433CB; Fri, 30 Oct 2020 01:01:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-caf-mail-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=ALL_TRUSTED,BAYES_00,SPF_FAIL, URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.0 Received: from abhinavk-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: abhinavk) by smtp.codeaurora.org (Postfix) with ESMTPSA id 60AA8C433F0; Fri, 30 Oct 2020 01:01:32 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 60AA8C433F0 Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; spf=fail smtp.mailfrom=abhinavk@codeaurora.org From: Abhinav Kumar To: dri-devel@lists.freedesktop.org Cc: Abhinav Kumar , linux-arm-msm@vger.kernel.org, freedreno@lists.freedesktop.org, robdclark@gmail.com, seanpaul@chromium.org, swboyd@chromium.org, nganji@codeaurora.org, aravindh@codeaurora.org, tanmay@codeaurora.org, khsieh@codeaurora.org, daniel@ffwll.ch Subject: [PATCH v2 3/4] drm/msm: register the base address with dpu_dbg module Date: Thu, 29 Oct 2020 18:01:00 -0700 Message-Id: <20201030010101.4345-4-abhinavk@codeaurora.org> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20201030010101.4345-1-abhinavk@codeaurora.org> References: <20201030010101.4345-1-abhinavk@codeaurora.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Register the base address of various dpu sub-modules with the dpu_dbg module so that it can be dumped out during error scenarios. changes in v2: - Fix an issue where the same dsi client was getting registered multiple times to the dpu_dbg module Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.c | 4 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 6 ++++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c | 7 +++-- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 5 +++- .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c | 6 ++++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 8 +++++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c | 7 ++++- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 12 +++++++-- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 4 ++- drivers/gpu/drm/msm/dp/dp_catalog.c | 12 +++++++++ drivers/gpu/drm/msm/dp/dp_catalog.h | 4 +++ drivers/gpu/drm/msm/dp/dp_display.c | 2 ++ drivers/gpu/drm/msm/dsi/dsi.c | 1 + drivers/gpu/drm/msm/dsi/dsi.h | 1 + drivers/gpu/drm/msm/dsi/dsi_host.c | 15 ++++++++++- drivers/gpu/drm/msm/msm_drv.c | 26 ++++++++++++++++++- drivers/gpu/drm/msm/msm_drv.h | 3 ++- 17 files changed, 108 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.c index f83682668e87..06d28efb45c9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.c @@ -263,7 +263,7 @@ int dpu_dbg_reg_register_base(const char *name, void __iomem *base, /* Initialize list to make sure check for null list will be valid */ INIT_LIST_HEAD(®_base->sub_range_list); - pr_debug("%s base: %pK max_offset 0x%zX\n", reg_base->name, + pr_info("%s base: %pK max_offset 0x%zX\n", reg_base->name, reg_base->base, reg_base->max_offset); list_add(®_base->reg_base_head, &dbg_base->reg_base_list); @@ -310,7 +310,7 @@ void dpu_dbg_reg_register_dump_range(const char *base_name, range->xin_id = xin_id; list_add_tail(&range->head, ®_base->sub_range_list); - pr_debug("base %s, range %s, start 0x%X, end 0x%X\n", + pr_info("base_name %s, range_name %s, start 0x%X, end 0x%X\n", base_name, range->range_name, range->offset.start, range->offset.end); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index 758c355b4fd8..3a827ea96723 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. */ #include @@ -7,6 +7,7 @@ #include "dpu_hw_ctl.h" #include "dpu_kms.h" #include "dpu_trace.h" +#include "dpu_dbg.h" #define CTL_LAYER(lm) \ (((lm) == LM_5) ? (0x024) : (((lm) - LM_0) * 0x004)) @@ -588,6 +589,9 @@ struct dpu_hw_ctl *dpu_hw_ctl_init(enum dpu_ctl idx, dpu_hw_blk_init(&c->base, DPU_HW_BLK_CTL, idx, &dpu_hw_ops); + dpu_dbg_reg_register_dump_range(DPU_DBG_NAME, cfg->name, c->hw.blk_off, + c->hw.blk_off + c->hw.length, c->hw.xin_id); + return c; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c index a7a24539921f..ee9ae02f5e7f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. */ #include "dpu_hwio.h" @@ -7,7 +7,7 @@ #include "dpu_hw_lm.h" #include "dpu_hw_dspp.h" #include "dpu_kms.h" - +#include "dpu_dbg.h" /* DSPP_PCC */ #define PCC_EN BIT(0) @@ -115,6 +115,9 @@ struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx, dpu_hw_blk_init(&c->base, DPU_HW_BLK_DSPP, idx, &dpu_hw_ops); + dpu_dbg_reg_register_dump_range(DPU_DBG_NAME, cfg->name, c->hw.blk_off, + c->hw.blk_off + c->hw.length, c->hw.xin_id); + return c; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c index 6f0f54588124..d8198d4d42bc 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c @@ -1,11 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #include "dpu_hwio.h" #include "dpu_hw_catalog.h" #include "dpu_hw_intf.h" #include "dpu_kms.h" +#include "dpu_dbg.h" #define INTF_TIMING_ENGINE_EN 0x000 #define INTF_CONFIG 0x004 @@ -319,6 +320,8 @@ struct dpu_hw_intf *dpu_hw_intf_init(enum dpu_intf idx, dpu_hw_blk_init(&c->base, DPU_HW_BLK_INTF, idx, &dpu_hw_ops); + dpu_dbg_reg_register_dump_range(DPU_DBG_NAME, cfg->name, c->hw.blk_off, + c->hw.blk_off + c->hw.length, c->hw.xin_id); return c; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c index bea4ab5c58c5..0dc6d161e890 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. */ #include @@ -10,6 +10,7 @@ #include "dpu_hw_pingpong.h" #include "dpu_kms.h" #include "dpu_trace.h" +#include "dpu_dbg.h" #define PP_TEAR_CHECK_EN 0x000 #define PP_SYNC_CONFIG_VSYNC 0x004 @@ -260,6 +261,9 @@ struct dpu_hw_pingpong *dpu_hw_pingpong_init(enum dpu_pingpong idx, dpu_hw_blk_init(&c->base, DPU_HW_BLK_PINGPONG, idx, &dpu_hw_ops); + dpu_dbg_reg_register_dump_range(DPU_DBG_NAME, cfg->name, c->hw.blk_off, + c->hw.blk_off + c->hw.length, c->hw.xin_id); + return c; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c index c940b69435e1..873fc828538d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. */ #include "dpu_hwio.h" @@ -7,6 +7,7 @@ #include "dpu_hw_lm.h" #include "dpu_hw_sspp.h" #include "dpu_kms.h" +#include "dpu_dbg.h" #define DPU_FETCH_CONFIG_RESET_VALUE 0x00000087 @@ -736,6 +737,11 @@ struct dpu_hw_pipe *dpu_hw_sspp_init(enum dpu_sspp idx, dpu_hw_blk_init(&hw_pipe->base, DPU_HW_BLK_SSPP, idx, &dpu_hw_ops); + dpu_dbg_reg_register_dump_range(DPU_DBG_NAME, cfg->name, + hw_pipe->hw.blk_off, + hw_pipe->hw.blk_off + hw_pipe->hw.length, + hw_pipe->hw.xin_id); + return hw_pipe; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c index 01b76766a9a8..f042471815cc 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c @@ -1,11 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. */ #include "dpu_hwio.h" #include "dpu_hw_catalog.h" #include "dpu_hw_top.h" #include "dpu_kms.h" +#include "dpu_dbg.h" #define SSPP_SPARE 0x28 @@ -326,6 +327,10 @@ struct dpu_hw_mdp *dpu_hw_mdptop_init(enum dpu_mdp idx, dpu_hw_blk_init(&mdp->base, DPU_HW_BLK_TOP, idx, &dpu_hw_ops); + dpu_dbg_reg_register_dump_range(DPU_DBG_NAME, cfg->name, + mdp->hw.blk_off, mdp->hw.blk_off + mdp->hw.length, + mdp->hw.xin_id); + return mdp; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index d93c44f6996d..dc64e032d82f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2018, 2020 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark */ @@ -27,6 +27,7 @@ #include "dpu_encoder.h" #include "dpu_plane.h" #include "dpu_crtc.h" +#include "dpu_dbg.h" #define CREATE_TRACE_POINTS #include "dpu_trace.h" @@ -908,7 +909,14 @@ static int dpu_kms_hw_init(struct msm_kms *kms) dpu_kms->mmio = NULL; goto error; } - DRM_DEBUG("mapped dpu address space @%pK\n", dpu_kms->mmio); + + dpu_kms->mmio_len = msm_iomap_size(dpu_kms->pdev, "mdp"); + + DRM_DEBUG("mapped dpu address space @%pK len = 0x%lx\n", + dpu_kms->mmio, dpu_kms->mmio_len); + + dpu_dbg_reg_register_base(DPU_DBG_NAME, + dpu_kms->mmio, dpu_kms->mmio_len); dpu_kms->vbif[VBIF_RT] = msm_ioremap(dpu_kms->pdev, "vbif", "vbif"); if (IS_ERR(dpu_kms->vbif[VBIF_RT])) { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 1c0e4c0c9ffb..a478b40868dd 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark */ @@ -103,6 +103,8 @@ struct dpu_kms { /* io/register spaces: */ void __iomem *mmio, *vbif[VBIF_MAX], *reg_dma; + unsigned long mmio_len; + struct regulator *vdd; struct regulator *mmagic; struct regulator *venus; diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index b15b4ce4ba35..efde98a3d9ab 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -63,6 +63,18 @@ struct dp_catalog_private { u8 aux_lut_cfg_index[PHY_AUX_CFG_MAX]; }; +void dp_catalog_register_dbg_base(struct dp_catalog *dp_catalog) +{ + char dbg_name[32]; + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + snprintf(dbg_name, 32, "dp_ctrl"); + + dpu_dbg_reg_register_base(dbg_name, catalog->io->dp_controller.base, + catalog->io->dp_controller.len); +} + static inline u32 dp_read_aux(struct dp_catalog_private *catalog, u32 offset) { offset += MSM_DP_CONTROLLER_AUX_OFFSET; diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h index 4b7666f1fe6f..af48590913e3 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.h +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h @@ -9,6 +9,7 @@ #include #include "dp_parser.h" +#include "dpu_dbg.h" /* interrupts */ #define DP_INTR_HPD BIT(0) @@ -71,6 +72,9 @@ struct dp_catalog { u32 audio_data; }; +/* Debug module */ +void dp_catalog_register_dbg_base(struct dp_catalog *dp_catalog); + /* AUX APIs */ u32 dp_catalog_aux_read_data(struct dp_catalog *dp_catalog); int dp_catalog_aux_write_data(struct dp_catalog *dp_catalog); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index e175aa3fd3a9..4a5735564be2 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -230,6 +230,8 @@ static int dp_display_bind(struct device *dev, struct device *master, if (rc) DRM_ERROR("Audio registration Dp failed\n"); + dp_catalog_register_dbg_base(dp->catalog); + end: return rc; } diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 627048851d99..16b297f68086 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -119,6 +119,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) } priv->dsi[msm_dsi->id] = msm_dsi; + msm_dsi_dbg_register_base(msm_dsi->host); return 0; } diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 78ef5d4ed922..d6960b37e7fe 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -175,6 +175,7 @@ void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host, struct msm_dsi_phy_clk_request *clk_req, bool is_dual_dsi); void msm_dsi_host_destroy(struct mipi_dsi_host *host); +void msm_dsi_dbg_register_base(struct mipi_dsi_host *host); int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, struct drm_device *dev); int msm_dsi_host_init(struct msm_dsi *msm_dsi); diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index b17ac6c27554..4b87e258a418 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved. */ #include @@ -26,6 +26,8 @@ #include "sfpb.xml.h" #include "dsi_cfg.h" #include "msm_kms.h" +#include "dpu_dbg.h" +#include "msm_drv.h" #define DSI_RESET_TOGGLE_DELAY_MS 20 @@ -1919,6 +1921,17 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) return ret; } +void msm_dsi_dbg_register_base(struct mipi_dsi_host *host) +{ + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); + char dbg_name[32]; + + snprintf(dbg_name, 32, "dsi%d_ctrl", + msm_host->id); + dpu_dbg_reg_register_base(dbg_name, msm_host->ctrl_base, + msm_iomap_size(msm_host->pdev, "dsi_ctrl")); +} + void msm_dsi_host_destroy(struct mipi_dsi_host *host) { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index f6fb0187388f..df505a3d53e8 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -17,8 +17,8 @@ #include #include #include -#include "dpu_dbg.h" +#include "dpu_dbg.h" #include "msm_drv.h" #include "msm_debugfs.h" #include "msm_fence.h" @@ -166,6 +166,24 @@ void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name, return _msm_ioremap(pdev, name, dbgname, true); } +unsigned long msm_iomap_size(struct platform_device *pdev, const char *name) +{ + struct resource *res; + + if (name) + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); + else + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (!res) { + dev_dbg(&pdev->dev, "failed to get memory resource: %s\n", + name); + return 0; + } + + return resource_size(res); +} + void msm_writel(u32 data, void __iomem *addr) { if (reglog) @@ -535,6 +553,8 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) if (ret) goto err_msm_uninit; + dpu_dbg_register_drm_dev(ddev); + drm_mode_config_reset(ddev); #ifdef CONFIG_DRM_FBDEV_EMULATION @@ -1282,6 +1302,10 @@ static int msm_pdev_probe(struct platform_device *pdev) int ret; if (get_mdp_ver(pdev)) { + ret = dpu_dbg_init(&pdev->dev); + if (ret) + pr_err("dpu_dbg_init failed ret = %d\n", ret); + ret = add_display_components(&pdev->dev, &match); if (ret) return ret; diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index b9dd8f8f4887..211161bdce2f 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018, 2020 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark */ @@ -476,6 +476,7 @@ void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, const char *dbgname); void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name, const char *dbgname); +unsigned long msm_iomap_size(struct platform_device *pdev, const char *name); void msm_writel(u32 data, void __iomem *addr); u32 msm_readl(const void __iomem *addr); From patchwork Fri Oct 30 01:01:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abhinav Kumar X-Patchwork-Id: 11868115 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2482A1130 for ; Fri, 30 Oct 2020 01:02:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EE93E2054F for ; Fri, 30 Oct 2020 01:02:58 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=mg.codeaurora.org header.i=@mg.codeaurora.org header.b="O8RAxVX+" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726009AbgJ3BCj (ORCPT ); Thu, 29 Oct 2020 21:02:39 -0400 Received: from m42-4.mailgun.net ([69.72.42.4]:28774 "EHLO m42-4.mailgun.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725372AbgJ3BCi (ORCPT ); Thu, 29 Oct 2020 21:02:38 -0400 DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; q=dns/txt; s=smtp; t=1604019696; h=Content-Transfer-Encoding: MIME-Version: References: In-Reply-To: Message-Id: Date: Subject: Cc: To: From: Sender; bh=J1HPpQZ9qKoiP3yWBEUXeGMKJONcI5AQ29AQ64ceNhI=; b=O8RAxVX+rGe/U13ZqAot4/NpC7M8d/ginbsVlESEQIvjhnc9Sy6ASrf1bswUCA5I6uZZir9p lQikzi1oiMg54/Rbi2wyXogp0TQOFN3WWG0xcGz4TOdKmWezM8/GOfzRZyQM8HBJa7XM3x2M VS/ntBRfNI16mkoMGycj1hbKtfg= X-Mailgun-Sending-Ip: 69.72.42.4 X-Mailgun-Sid: WyI1MzIzYiIsICJsaW51eC1hcm0tbXNtQHZnZXIua2VybmVsLm9yZyIsICJiZTllNGEiXQ== Received: from smtp.codeaurora.org (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by smtp-out-n03.prod.us-west-2.postgun.com with SMTP id 5f9b65f08335df16577668a2 (version=TLS1.2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); Fri, 30 Oct 2020 01:01:36 GMT Sender: abhinavk=codeaurora.org@mg.codeaurora.org Received: by smtp.codeaurora.org (Postfix, from userid 1001) id 76FFDC433C9; Fri, 30 Oct 2020 01:01:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-caf-mail-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=ALL_TRUSTED,BAYES_00,SPF_FAIL, URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.0 Received: from abhinavk-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: abhinavk) by smtp.codeaurora.org (Postfix) with ESMTPSA id 8A1D0C43385; Fri, 30 Oct 2020 01:01:34 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 8A1D0C43385 Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; spf=fail smtp.mailfrom=abhinavk@codeaurora.org From: Abhinav Kumar To: dri-devel@lists.freedesktop.org Cc: Abhinav Kumar , linux-arm-msm@vger.kernel.org, freedreno@lists.freedesktop.org, robdclark@gmail.com, seanpaul@chromium.org, swboyd@chromium.org, nganji@codeaurora.org, aravindh@codeaurora.org, tanmay@codeaurora.org, khsieh@codeaurora.org, daniel@ffwll.ch Subject: [PATCH v2 4/4] drm/msm/dpu: add dpu_dbg points across dpu driver Date: Thu, 29 Oct 2020 18:01:01 -0700 Message-Id: <20201030010101.4345-5-abhinavk@codeaurora.org> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20201030010101.4345-1-abhinavk@codeaurora.org> References: <20201030010101.4345-1-abhinavk@codeaurora.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Add dpu_dbg points across dpu driver to trigger dumps when critical errors are hit. changes in v2: none Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 12 ++++++++++-- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 5 +++-- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 5 ++++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index f7f5c258b553..a2ee1af73c9f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2018, 2020 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark */ @@ -26,6 +26,7 @@ #include "dpu_crtc.h" #include "dpu_trace.h" #include "dpu_core_irq.h" +#include "dpu_dbg.h" #define DPU_DEBUG_ENC(e, fmt, ...) DPU_DEBUG("enc%d " fmt,\ (e) ? (e)->base.base.id : -1, ##__VA_ARGS__) @@ -1313,6 +1314,11 @@ static void dpu_encoder_underrun_callback(struct drm_encoder *drm_enc, DPU_ATRACE_BEGIN("encoder_underrun_callback"); atomic_inc(&phy_enc->underrun_cnt); + + /* trigger dump only on the first underrun */ + if (atomic_read(&phy_enc->underrun_cnt) == 1) + DPU_DBG_DUMP("all"); + trace_dpu_enc_underrun_cb(DRMID(drm_enc), atomic_read(&phy_enc->underrun_cnt)); DPU_ATRACE_END("encoder_underrun_callback"); @@ -1553,8 +1559,10 @@ static void dpu_encoder_helper_hw_reset(struct dpu_encoder_phys *phys_enc) ctl->idx); rc = ctl->ops.reset(ctl); - if (rc) + if (rc) { DPU_ERROR_ENC(dpu_enc, "ctl %d reset failure\n", ctl->idx); + DPU_DBG_DUMP("all"); + } phys_enc->enable_state = DPU_ENC_ENABLED; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c index 8493d68ad841..58f79557b560 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ @@ -9,6 +9,7 @@ #include "dpu_core_irq.h" #include "dpu_formats.h" #include "dpu_trace.h" +#include "dpu_dbg.h" #define DPU_DEBUG_CMDENC(e, fmt, ...) DPU_DEBUG("enc%d intf%d " fmt, \ (e) && (e)->base.parent ? \ @@ -213,7 +214,7 @@ static int _dpu_encoder_phys_cmd_handle_ppdone_timeout( phys_enc->hw_ctl->idx - CTL_0, cmd_enc->pp_timeout_report_cnt, atomic_read(&phys_enc->pending_kickoff_cnt)); - + DPU_DBG_DUMP("all"); dpu_encoder_helper_unregister_irq(phys_enc, INTR_IDX_RDPTR); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index 805e059b50b7..46c5320150fa 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ @@ -8,6 +8,7 @@ #include "dpu_core_irq.h" #include "dpu_formats.h" #include "dpu_trace.h" +#include "dpu_dbg.h" #define DPU_DEBUG_VIDENC(e, fmt, ...) DPU_DEBUG("enc%d intf%d " fmt, \ (e) && (e)->parent ? \ @@ -467,6 +468,7 @@ static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc) "update pending flush ctl %d flush_mask 0%x intf_mask 0x%x\n", ctl->idx - CTL_0, flush_mask, intf_flush_mask); + atomic_set(&phys_enc->underrun_cnt, 0); /* ctl_flush & timing engine enable will be triggered by framework */ if (phys_enc->enable_state == DPU_ENC_DISABLED) @@ -549,6 +551,7 @@ static void dpu_encoder_phys_vid_prepare_for_kickoff( if (rc) { DPU_ERROR_VIDENC(phys_enc, "ctl %d reset failure: %d\n", ctl->idx, rc); + DPU_DBG_DUMP("all"); dpu_encoder_helper_unregister_irq(phys_enc, INTR_IDX_VSYNC); } }