xref: /linux/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c (revision 260f6f4fda93c8485c8037865c941b42b9cba5d2)
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