197fb5e8dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2331dc0bcSRob Clark /* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
3331dc0bcSRob Clark */
4331dc0bcSRob Clark
5331dc0bcSRob Clark #include <linux/types.h>
6331dc0bcSRob Clark #include <linux/debugfs.h>
7feea39a8SSam Ravnborg
8feea39a8SSam Ravnborg #include <drm/drm_debugfs.h>
9feea39a8SSam Ravnborg #include <drm/drm_file.h>
10331dc0bcSRob Clark #include <drm/drm_print.h>
11331dc0bcSRob Clark
12331dc0bcSRob Clark #include "a5xx_gpu.h"
13331dc0bcSRob Clark
pfp_print(struct msm_gpu * gpu,struct drm_printer * p)14d768e504SBernard Zhao static void pfp_print(struct msm_gpu *gpu, struct drm_printer *p)
15331dc0bcSRob Clark {
16331dc0bcSRob Clark int i;
17331dc0bcSRob Clark
18331dc0bcSRob Clark drm_printf(p, "PFP state:\n");
19331dc0bcSRob Clark
20331dc0bcSRob Clark for (i = 0; i < 36; i++) {
21331dc0bcSRob Clark gpu_write(gpu, REG_A5XX_CP_PFP_STAT_ADDR, i);
22331dc0bcSRob Clark drm_printf(p, " %02x: %08x\n", i,
23331dc0bcSRob Clark gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA));
24331dc0bcSRob Clark }
25331dc0bcSRob Clark }
26331dc0bcSRob Clark
me_print(struct msm_gpu * gpu,struct drm_printer * p)27d768e504SBernard Zhao static void me_print(struct msm_gpu *gpu, struct drm_printer *p)
28331dc0bcSRob Clark {
29331dc0bcSRob Clark int i;
30331dc0bcSRob Clark
31331dc0bcSRob Clark drm_printf(p, "ME state:\n");
32331dc0bcSRob Clark
33331dc0bcSRob Clark for (i = 0; i < 29; i++) {
34331dc0bcSRob Clark gpu_write(gpu, REG_A5XX_CP_ME_STAT_ADDR, i);
35331dc0bcSRob Clark drm_printf(p, " %02x: %08x\n", i,
36331dc0bcSRob Clark gpu_read(gpu, REG_A5XX_CP_ME_STAT_DATA));
37331dc0bcSRob Clark }
38331dc0bcSRob Clark }
39331dc0bcSRob Clark
meq_print(struct msm_gpu * gpu,struct drm_printer * p)40d768e504SBernard Zhao static void meq_print(struct msm_gpu *gpu, struct drm_printer *p)
41331dc0bcSRob Clark {
42331dc0bcSRob Clark int i;
43331dc0bcSRob Clark
44331dc0bcSRob Clark drm_printf(p, "MEQ state:\n");
45331dc0bcSRob Clark gpu_write(gpu, REG_A5XX_CP_MEQ_DBG_ADDR, 0);
46331dc0bcSRob Clark
47331dc0bcSRob Clark for (i = 0; i < 64; i++) {
48331dc0bcSRob Clark drm_printf(p, " %02x: %08x\n", i,
49331dc0bcSRob Clark gpu_read(gpu, REG_A5XX_CP_MEQ_DBG_DATA));
50331dc0bcSRob Clark }
51331dc0bcSRob Clark }
52331dc0bcSRob Clark
roq_print(struct msm_gpu * gpu,struct drm_printer * p)53d768e504SBernard Zhao static void roq_print(struct msm_gpu *gpu, struct drm_printer *p)
54331dc0bcSRob Clark {
55331dc0bcSRob Clark int i;
56331dc0bcSRob Clark
57331dc0bcSRob Clark drm_printf(p, "ROQ state:\n");
58331dc0bcSRob Clark gpu_write(gpu, REG_A5XX_CP_ROQ_DBG_ADDR, 0);
59331dc0bcSRob Clark
60331dc0bcSRob Clark for (i = 0; i < 512 / 4; i++) {
61331dc0bcSRob Clark uint32_t val[4];
62331dc0bcSRob Clark int j;
63331dc0bcSRob Clark for (j = 0; j < 4; j++)
64331dc0bcSRob Clark val[j] = gpu_read(gpu, REG_A5XX_CP_ROQ_DBG_DATA);
65331dc0bcSRob Clark drm_printf(p, " %02x: %08x %08x %08x %08x\n", i,
66331dc0bcSRob Clark val[0], val[1], val[2], val[3]);
67331dc0bcSRob Clark }
68331dc0bcSRob Clark }
69331dc0bcSRob Clark
show(struct seq_file * m,void * arg)70331dc0bcSRob Clark static int show(struct seq_file *m, void *arg)
71331dc0bcSRob Clark {
72eea9cf72SSu Hui struct drm_info_node *node = m->private;
73331dc0bcSRob Clark struct drm_device *dev = node->minor->dev;
74331dc0bcSRob Clark struct msm_drm_private *priv = dev->dev_private;
75331dc0bcSRob Clark struct drm_printer p = drm_seq_file_printer(m);
76d768e504SBernard Zhao void (*show)(struct msm_gpu *gpu, struct drm_printer *p) =
77331dc0bcSRob Clark node->info_ent->data;
78331dc0bcSRob Clark
79d768e504SBernard Zhao show(priv->gpu, &p);
80d768e504SBernard Zhao return 0;
81331dc0bcSRob Clark }
82331dc0bcSRob Clark
83331dc0bcSRob Clark #define ENT(n) { .name = #n, .show = show, .data = n ##_print }
84331dc0bcSRob Clark static struct drm_info_list a5xx_debugfs_list[] = {
85331dc0bcSRob Clark ENT(pfp),
86331dc0bcSRob Clark ENT(me),
87331dc0bcSRob Clark ENT(meq),
88331dc0bcSRob Clark ENT(roq),
89331dc0bcSRob Clark };
90331dc0bcSRob Clark
91331dc0bcSRob Clark /* for debugfs files that can be written to, we can't use drm helper: */
92331dc0bcSRob Clark static int
reset_set(void * data,u64 val)93331dc0bcSRob Clark reset_set(void *data, u64 val)
94331dc0bcSRob Clark {
95331dc0bcSRob Clark struct drm_device *dev = data;
96331dc0bcSRob Clark struct msm_drm_private *priv = dev->dev_private;
97331dc0bcSRob Clark struct msm_gpu *gpu = priv->gpu;
98331dc0bcSRob Clark struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
99331dc0bcSRob Clark struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
100331dc0bcSRob Clark
101331dc0bcSRob Clark if (!capable(CAP_SYS_ADMIN))
102331dc0bcSRob Clark return -EINVAL;
103331dc0bcSRob Clark
104331dc0bcSRob Clark /* TODO do we care about trying to make sure the GPU is idle?
105331dc0bcSRob Clark * Since this is just a debug feature limited to CAP_SYS_ADMIN,
106331dc0bcSRob Clark * maybe it is fine to let the user keep both pieces if they
107331dc0bcSRob Clark * try to reset an active GPU.
108331dc0bcSRob Clark */
109331dc0bcSRob Clark
110c28e2f2bSRob Clark mutex_lock(&gpu->lock);
111331dc0bcSRob Clark
112c5e3548cSJordan Crouse release_firmware(adreno_gpu->fw[ADRENO_FW_PM4]);
113c5e3548cSJordan Crouse adreno_gpu->fw[ADRENO_FW_PM4] = NULL;
114331dc0bcSRob Clark
115c5e3548cSJordan Crouse release_firmware(adreno_gpu->fw[ADRENO_FW_PFP]);
116c5e3548cSJordan Crouse adreno_gpu->fw[ADRENO_FW_PFP] = NULL;
117c5e3548cSJordan Crouse
118331dc0bcSRob Clark if (a5xx_gpu->pm4_bo) {
119*057e55f3SRob Clark msm_gem_unpin_iova(a5xx_gpu->pm4_bo, gpu->vm);
120030af2b0SRob Clark drm_gem_object_put(a5xx_gpu->pm4_bo);
121331dc0bcSRob Clark a5xx_gpu->pm4_bo = NULL;
122331dc0bcSRob Clark }
123331dc0bcSRob Clark
124331dc0bcSRob Clark if (a5xx_gpu->pfp_bo) {
125*057e55f3SRob Clark msm_gem_unpin_iova(a5xx_gpu->pfp_bo, gpu->vm);
126030af2b0SRob Clark drm_gem_object_put(a5xx_gpu->pfp_bo);
127331dc0bcSRob Clark a5xx_gpu->pfp_bo = NULL;
128331dc0bcSRob Clark }
129331dc0bcSRob Clark
130331dc0bcSRob Clark gpu->needs_hw_init = true;
131331dc0bcSRob Clark
132331dc0bcSRob Clark pm_runtime_get_sync(&gpu->pdev->dev);
133331dc0bcSRob Clark gpu->funcs->recover(gpu);
134331dc0bcSRob Clark
135331dc0bcSRob Clark pm_runtime_put_sync(&gpu->pdev->dev);
136c28e2f2bSRob Clark mutex_unlock(&gpu->lock);
137331dc0bcSRob Clark
138331dc0bcSRob Clark return 0;
139331dc0bcSRob Clark }
140331dc0bcSRob Clark
1412c477ff3SDeepak R Varma DEFINE_DEBUGFS_ATTRIBUTE(reset_fops, NULL, reset_set, "%llx\n");
142331dc0bcSRob Clark
143331dc0bcSRob Clark
a5xx_debugfs_init(struct msm_gpu * gpu,struct drm_minor * minor)1447ce84471SWambui Karuga void a5xx_debugfs_init(struct msm_gpu *gpu, struct drm_minor *minor)
145331dc0bcSRob Clark {
1465abc7dd7SGustavo A. R. Silva struct drm_device *dev;
147331dc0bcSRob Clark
148331dc0bcSRob Clark if (!minor)
1497ce84471SWambui Karuga return;
150331dc0bcSRob Clark
1515abc7dd7SGustavo A. R. Silva dev = minor->dev;
1525abc7dd7SGustavo A. R. Silva
1539e2fd463SWambui Karuga drm_debugfs_create_files(a5xx_debugfs_list,
154331dc0bcSRob Clark ARRAY_SIZE(a5xx_debugfs_list),
155331dc0bcSRob Clark minor->debugfs_root, minor);
156331dc0bcSRob Clark
1572c477ff3SDeepak R Varma debugfs_create_file_unsafe("reset", S_IWUGO, minor->debugfs_root, dev,
158491d5071SGreg Kroah-Hartman &reset_fops);
159331dc0bcSRob Clark }
160