1// SPDX-License-Identifier: GPL-2.0-only
2/* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
3 */
4
5#include <linux/types.h>
6#include <linux/debugfs.h>
7
8#include <drm/drm_debugfs.h>
9#include <drm/drm_file.h>
10#include <drm/drm_print.h>
11
12#include "a5xx_gpu.h"
13
14static void pfp_print(struct msm_gpu *gpu, struct drm_printer *p)
15{
16 int i;
17
18 drm_printf(p, f: "PFP state:\n");
19
20 for (i = 0; i < 36; i++) {
21 gpu_write(gpu, REG_A5XX_CP_PFP_STAT_ADDR, i);
22 drm_printf(p, f: " %02x: %08x\n", i,
23 gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA));
24 }
25}
26
27static void me_print(struct msm_gpu *gpu, struct drm_printer *p)
28{
29 int i;
30
31 drm_printf(p, f: "ME state:\n");
32
33 for (i = 0; i < 29; i++) {
34 gpu_write(gpu, REG_A5XX_CP_ME_STAT_ADDR, i);
35 drm_printf(p, f: " %02x: %08x\n", i,
36 gpu_read(gpu, REG_A5XX_CP_ME_STAT_DATA));
37 }
38}
39
40static void meq_print(struct msm_gpu *gpu, struct drm_printer *p)
41{
42 int i;
43
44 drm_printf(p, f: "MEQ state:\n");
45 gpu_write(gpu, REG_A5XX_CP_MEQ_DBG_ADDR, 0);
46
47 for (i = 0; i < 64; i++) {
48 drm_printf(p, f: " %02x: %08x\n", i,
49 gpu_read(gpu, REG_A5XX_CP_MEQ_DBG_DATA));
50 }
51}
52
53static void roq_print(struct msm_gpu *gpu, struct drm_printer *p)
54{
55 int i;
56
57 drm_printf(p, f: "ROQ state:\n");
58 gpu_write(gpu, REG_A5XX_CP_ROQ_DBG_ADDR, 0);
59
60 for (i = 0; i < 512 / 4; i++) {
61 uint32_t val[4];
62 int j;
63 for (j = 0; j < 4; j++)
64 val[j] = gpu_read(gpu, REG_A5XX_CP_ROQ_DBG_DATA);
65 drm_printf(p, f: " %02x: %08x %08x %08x %08x\n", i,
66 val[0], val[1], val[2], val[3]);
67 }
68}
69
70static int show(struct seq_file *m, void *arg)
71{
72 struct drm_info_node *node = m->private;
73 struct drm_device *dev = node->minor->dev;
74 struct msm_drm_private *priv = dev->dev_private;
75 struct drm_printer p = drm_seq_file_printer(f: m);
76 void (*show)(struct msm_gpu *gpu, struct drm_printer *p) =
77 node->info_ent->data;
78
79 show(priv->gpu, &p);
80 return 0;
81}
82
83#define ENT(n) { .name = #n, .show = show, .data = n ##_print }
84static struct drm_info_list a5xx_debugfs_list[] = {
85 ENT(pfp),
86 ENT(me),
87 ENT(meq),
88 ENT(roq),
89};
90
91/* for debugfs files that can be written to, we can't use drm helper: */
92static int
93reset_set(void *data, u64 val)
94{
95 struct drm_device *dev = data;
96 struct msm_drm_private *priv = dev->dev_private;
97 struct msm_gpu *gpu = priv->gpu;
98 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
99 struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
100
101 if (!capable(CAP_SYS_ADMIN))
102 return -EINVAL;
103
104 /* TODO do we care about trying to make sure the GPU is idle?
105 * Since this is just a debug feature limited to CAP_SYS_ADMIN,
106 * maybe it is fine to let the user keep both pieces if they
107 * try to reset an active GPU.
108 */
109
110 mutex_lock(&gpu->lock);
111
112 release_firmware(fw: adreno_gpu->fw[ADRENO_FW_PM4]);
113 adreno_gpu->fw[ADRENO_FW_PM4] = NULL;
114
115 release_firmware(fw: adreno_gpu->fw[ADRENO_FW_PFP]);
116 adreno_gpu->fw[ADRENO_FW_PFP] = NULL;
117
118 if (a5xx_gpu->pm4_bo) {
119 msm_gem_unpin_iova(a5xx_gpu->pm4_bo, gpu->aspace);
120 drm_gem_object_put(obj: a5xx_gpu->pm4_bo);
121 a5xx_gpu->pm4_bo = NULL;
122 }
123
124 if (a5xx_gpu->pfp_bo) {
125 msm_gem_unpin_iova(a5xx_gpu->pfp_bo, gpu->aspace);
126 drm_gem_object_put(obj: a5xx_gpu->pfp_bo);
127 a5xx_gpu->pfp_bo = NULL;
128 }
129
130 gpu->needs_hw_init = true;
131
132 pm_runtime_get_sync(&gpu->pdev->dev);
133 gpu->funcs->recover(gpu);
134
135 pm_runtime_put_sync(&gpu->pdev->dev);
136 mutex_unlock(lock: &gpu->lock);
137
138 return 0;
139}
140
141DEFINE_DEBUGFS_ATTRIBUTE(reset_fops, NULL, reset_set, "%llx\n");
142
143
144void a5xx_debugfs_init(struct msm_gpu *gpu, struct drm_minor *minor)
145{
146 struct drm_device *dev;
147
148 if (!minor)
149 return;
150
151 dev = minor->dev;
152
153 drm_debugfs_create_files(files: a5xx_debugfs_list,
154 ARRAY_SIZE(a5xx_debugfs_list),
155 root: minor->debugfs_root, minor);
156
157 debugfs_create_file_unsafe(name: "reset", S_IWUGO, parent: minor->debugfs_root, data: dev,
158 fops: &reset_fops);
159}
160

source code of linux/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c