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