1 /* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
15 #include <linux/types.h>
16 #include <linux/debugfs.h>
17 #include <drm/drm_print.h>
21 static int pfp_print(struct msm_gpu
*gpu
, struct drm_printer
*p
)
25 drm_printf(p
, "PFP state:\n");
27 for (i
= 0; i
< 36; i
++) {
28 gpu_write(gpu
, REG_A5XX_CP_PFP_STAT_ADDR
, i
);
29 drm_printf(p
, " %02x: %08x\n", i
,
30 gpu_read(gpu
, REG_A5XX_CP_PFP_STAT_DATA
));
36 static int me_print(struct msm_gpu
*gpu
, struct drm_printer
*p
)
40 drm_printf(p
, "ME state:\n");
42 for (i
= 0; i
< 29; i
++) {
43 gpu_write(gpu
, REG_A5XX_CP_ME_STAT_ADDR
, i
);
44 drm_printf(p
, " %02x: %08x\n", i
,
45 gpu_read(gpu
, REG_A5XX_CP_ME_STAT_DATA
));
51 static int meq_print(struct msm_gpu
*gpu
, struct drm_printer
*p
)
55 drm_printf(p
, "MEQ state:\n");
56 gpu_write(gpu
, REG_A5XX_CP_MEQ_DBG_ADDR
, 0);
58 for (i
= 0; i
< 64; i
++) {
59 drm_printf(p
, " %02x: %08x\n", i
,
60 gpu_read(gpu
, REG_A5XX_CP_MEQ_DBG_DATA
));
66 static int roq_print(struct msm_gpu
*gpu
, struct drm_printer
*p
)
70 drm_printf(p
, "ROQ state:\n");
71 gpu_write(gpu
, REG_A5XX_CP_ROQ_DBG_ADDR
, 0);
73 for (i
= 0; i
< 512 / 4; i
++) {
76 for (j
= 0; j
< 4; j
++)
77 val
[j
] = gpu_read(gpu
, REG_A5XX_CP_ROQ_DBG_DATA
);
78 drm_printf(p
, " %02x: %08x %08x %08x %08x\n", i
,
79 val
[0], val
[1], val
[2], val
[3]);
85 static int show(struct seq_file
*m
, void *arg
)
87 struct drm_info_node
*node
= (struct drm_info_node
*) m
->private;
88 struct drm_device
*dev
= node
->minor
->dev
;
89 struct msm_drm_private
*priv
= dev
->dev_private
;
90 struct drm_printer p
= drm_seq_file_printer(m
);
91 int (*show
)(struct msm_gpu
*gpu
, struct drm_printer
*p
) =
94 return show(priv
->gpu
, &p
);
97 #define ENT(n) { .name = #n, .show = show, .data = n ##_print }
98 static struct drm_info_list a5xx_debugfs_list
[] = {
105 /* for debugfs files that can be written to, we can't use drm helper: */
107 reset_set(void *data
, u64 val
)
109 struct drm_device
*dev
= data
;
110 struct msm_drm_private
*priv
= dev
->dev_private
;
111 struct msm_gpu
*gpu
= priv
->gpu
;
112 struct adreno_gpu
*adreno_gpu
= to_adreno_gpu(gpu
);
113 struct a5xx_gpu
*a5xx_gpu
= to_a5xx_gpu(adreno_gpu
);
115 if (!capable(CAP_SYS_ADMIN
))
118 /* TODO do we care about trying to make sure the GPU is idle?
119 * Since this is just a debug feature limited to CAP_SYS_ADMIN,
120 * maybe it is fine to let the user keep both pieces if they
121 * try to reset an active GPU.
124 mutex_lock(&dev
->struct_mutex
);
126 release_firmware(adreno_gpu
->fw
[ADRENO_FW_PM4
]);
127 adreno_gpu
->fw
[ADRENO_FW_PM4
] = NULL
;
129 release_firmware(adreno_gpu
->fw
[ADRENO_FW_PFP
]);
130 adreno_gpu
->fw
[ADRENO_FW_PFP
] = NULL
;
132 if (a5xx_gpu
->pm4_bo
) {
133 if (a5xx_gpu
->pm4_iova
)
134 msm_gem_put_iova(a5xx_gpu
->pm4_bo
, gpu
->aspace
);
135 drm_gem_object_unreference(a5xx_gpu
->pm4_bo
);
136 a5xx_gpu
->pm4_bo
= NULL
;
139 if (a5xx_gpu
->pfp_bo
) {
140 if (a5xx_gpu
->pfp_iova
)
141 msm_gem_put_iova(a5xx_gpu
->pfp_bo
, gpu
->aspace
);
142 drm_gem_object_unreference(a5xx_gpu
->pfp_bo
);
143 a5xx_gpu
->pfp_bo
= NULL
;
146 gpu
->needs_hw_init
= true;
148 pm_runtime_get_sync(&gpu
->pdev
->dev
);
149 gpu
->funcs
->recover(gpu
);
151 pm_runtime_put_sync(&gpu
->pdev
->dev
);
152 mutex_unlock(&dev
->struct_mutex
);
157 DEFINE_SIMPLE_ATTRIBUTE(reset_fops
, NULL
, reset_set
, "%llx\n");
160 int a5xx_debugfs_init(struct msm_gpu
*gpu
, struct drm_minor
*minor
)
162 struct drm_device
*dev
;
171 ret
= drm_debugfs_create_files(a5xx_debugfs_list
,
172 ARRAY_SIZE(a5xx_debugfs_list
),
173 minor
->debugfs_root
, minor
);
176 dev_err(dev
->dev
, "could not install a5xx_debugfs_list\n");
180 ent
= debugfs_create_file("reset", S_IWUGO
,