1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright © 2022 Intel Corporation
4 */
5
6 #include "xe_guc_debugfs.h"
7
8 #include <drm/drm_debugfs.h>
9 #include <drm/drm_managed.h>
10
11 #include "xe_device.h"
12 #include "xe_gt.h"
13 #include "xe_guc.h"
14 #include "xe_guc_ct.h"
15 #include "xe_guc_log.h"
16 #include "xe_guc_pc.h"
17 #include "xe_macros.h"
18 #include "xe_pm.h"
19
20 /*
21 * guc_debugfs_show - A show callback for struct drm_info_list
22 * @m: the &seq_file
23 * @data: data used by the drm debugfs helpers
24 *
25 * This callback can be used in struct drm_info_list to describe debugfs
26 * files that are &xe_guc specific in similar way how we handle &xe_gt
27 * specific files using &xe_gt_debugfs_simple_show.
28 *
29 * It is assumed that those debugfs files will be created on directory entry
30 * which grandparent struct dentry d_inode->i_private points to &xe_gt.
31 *
32 * /sys/kernel/debug/dri/0/
33 * ├── gt0 # dent->d_parent->d_parent (d_inode->i_private == gt)
34 * │ ├── uc # dent->d_parent
35 * │ │ ├── guc_info # dent
36 * │ │ ├── guc_...
37 *
38 * This function assumes that &m->private will be set to the &struct
39 * drm_info_node corresponding to the instance of the info on a given &struct
40 * drm_minor (see struct drm_info_list.show for details).
41 *
42 * This function also assumes that struct drm_info_list.data will point to the
43 * function code that will actually print a file content::
44 *
45 * int (*print)(struct xe_guc *, struct drm_printer *)
46 *
47 * Example::
48 *
49 * int foo(struct xe_guc *guc, struct drm_printer *p)
50 * {
51 * drm_printf(p, "enabled %d\n", guc->submission_state.enabled);
52 * return 0;
53 * }
54 *
55 * static const struct drm_info_list bar[] = {
56 * { name = "foo", .show = guc_debugfs_show, .data = foo },
57 * };
58 *
59 * parent = debugfs_create_dir("uc", gtdir);
60 * drm_debugfs_create_files(bar, ARRAY_SIZE(bar), parent, minor);
61 *
62 * Return: 0 on success or a negative error code on failure.
63 */
guc_debugfs_show(struct seq_file * m,void * data)64 static int guc_debugfs_show(struct seq_file *m, void *data)
65 {
66 struct drm_printer p = drm_seq_file_printer(m);
67 struct drm_info_node *node = m->private;
68 struct dentry *parent = node->dent->d_parent;
69 struct dentry *grandparent = parent->d_parent;
70 struct xe_gt *gt = grandparent->d_inode->i_private;
71 struct xe_device *xe = gt_to_xe(gt);
72 int (*print)(struct xe_guc *, struct drm_printer *) = node->info_ent->data;
73 int ret;
74
75 xe_pm_runtime_get(xe);
76 ret = print(>->uc.guc, &p);
77 xe_pm_runtime_put(xe);
78
79 return ret;
80 }
81
guc_log(struct xe_guc * guc,struct drm_printer * p)82 static int guc_log(struct xe_guc *guc, struct drm_printer *p)
83 {
84 xe_guc_log_print(&guc->log, p);
85 return 0;
86 }
87
guc_log_dmesg(struct xe_guc * guc,struct drm_printer * p)88 static int guc_log_dmesg(struct xe_guc *guc, struct drm_printer *p)
89 {
90 xe_guc_log_print_dmesg(&guc->log);
91 return 0;
92 }
93
guc_ctb(struct xe_guc * guc,struct drm_printer * p)94 static int guc_ctb(struct xe_guc *guc, struct drm_printer *p)
95 {
96 xe_guc_ct_print(&guc->ct, p, true);
97 return 0;
98 }
99
guc_pc(struct xe_guc * guc,struct drm_printer * p)100 static int guc_pc(struct xe_guc *guc, struct drm_printer *p)
101 {
102 xe_guc_pc_print(&guc->pc, p);
103 return 0;
104 }
105
106 /*
107 * only for GuC debugfs files which can be safely used on the VF as well:
108 * - without access to the GuC privileged registers
109 * - without access to the PF specific GuC objects
110 */
111 static const struct drm_info_list vf_safe_debugfs_list[] = {
112 { "guc_info", .show = guc_debugfs_show, .data = xe_guc_print_info },
113 { "guc_ctb", .show = guc_debugfs_show, .data = guc_ctb },
114 };
115
116 /* For GuC debugfs files that require the SLPC support */
117 static const struct drm_info_list slpc_debugfs_list[] = {
118 { "guc_pc", .show = guc_debugfs_show, .data = guc_pc },
119 };
120
121 /* everything else should be added here */
122 static const struct drm_info_list pf_only_debugfs_list[] = {
123 { "guc_log", .show = guc_debugfs_show, .data = guc_log },
124 { "guc_log_dmesg", .show = guc_debugfs_show, .data = guc_log_dmesg },
125 };
126
xe_guc_debugfs_register(struct xe_guc * guc,struct dentry * parent)127 void xe_guc_debugfs_register(struct xe_guc *guc, struct dentry *parent)
128 {
129 struct xe_device *xe = guc_to_xe(guc);
130 struct drm_minor *minor = xe->drm.primary;
131
132 drm_debugfs_create_files(vf_safe_debugfs_list,
133 ARRAY_SIZE(vf_safe_debugfs_list),
134 parent, minor);
135
136 if (!IS_SRIOV_VF(xe)) {
137 drm_debugfs_create_files(pf_only_debugfs_list,
138 ARRAY_SIZE(pf_only_debugfs_list),
139 parent, minor);
140
141 if (!xe->info.skip_guc_pc)
142 drm_debugfs_create_files(slpc_debugfs_list,
143 ARRAY_SIZE(slpc_debugfs_list),
144 parent, minor);
145 }
146 }
147