xref: /openbsd-src/sys/dev/pci/drm/i915/gt/uc/intel_guc_log_debugfs.c (revision 1bb76ff151c0aba8e3312a604e4cd2e5195cf4b7)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2020 Intel Corporation
4  */
5 
6 #include <linux/fs.h>
7 #include <drm/drm_print.h>
8 
9 #include "gt/intel_gt_debugfs.h"
10 #include "intel_guc.h"
11 #include "intel_guc_log.h"
12 #include "intel_guc_log_debugfs.h"
13 #include "intel_uc.h"
14 
obj_to_guc_log_dump_size(struct drm_i915_gem_object * obj)15 static u32 obj_to_guc_log_dump_size(struct drm_i915_gem_object *obj)
16 {
17 	u32 size;
18 
19 	if (!obj)
20 		return PAGE_SIZE;
21 
22 	/* "0x%08x 0x%08x 0x%08x 0x%08x\n" => 16 bytes -> 44 chars => x2.75 */
23 	size = ((obj->base.size * 11) + 3) / 4;
24 
25 	/* Add padding for final blank line, any extra header info, etc. */
26 	size = PAGE_ALIGN(size + PAGE_SIZE);
27 
28 	return size;
29 }
30 
guc_log_dump_size(struct intel_guc_log * log)31 static u32 guc_log_dump_size(struct intel_guc_log *log)
32 {
33 	struct intel_guc *guc = log_to_guc(log);
34 
35 	if (!intel_guc_is_supported(guc))
36 		return PAGE_SIZE;
37 
38 	if (!log->vma)
39 		return PAGE_SIZE;
40 
41 	return obj_to_guc_log_dump_size(log->vma->obj);
42 }
43 
44 #ifdef notyet
45 
guc_log_dump_show(struct seq_file * m,void * data)46 static int guc_log_dump_show(struct seq_file *m, void *data)
47 {
48 	struct drm_printer p = drm_seq_file_printer(m);
49 	int ret;
50 
51 	ret = intel_guc_log_dump(m->private, &p, false);
52 
53 	if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) && seq_has_overflowed(m))
54 		pr_warn_once("preallocated size:%zx for %s exceeded\n",
55 			     m->size, __func__);
56 
57 	return ret;
58 }
59 DEFINE_INTEL_GT_DEBUGFS_ATTRIBUTE_WITH_SIZE(guc_log_dump, guc_log_dump_size);
60 
guc_load_err_dump_size(struct intel_guc_log * log)61 static u32 guc_load_err_dump_size(struct intel_guc_log *log)
62 {
63 	struct intel_guc *guc = log_to_guc(log);
64 	struct intel_uc *uc = container_of(guc, struct intel_uc, guc);
65 
66 	if (!intel_guc_is_supported(guc))
67 		return PAGE_SIZE;
68 
69 	return obj_to_guc_log_dump_size(uc->load_err_log);
70 }
71 
guc_load_err_log_dump_show(struct seq_file * m,void * data)72 static int guc_load_err_log_dump_show(struct seq_file *m, void *data)
73 {
74 	struct drm_printer p = drm_seq_file_printer(m);
75 
76 	if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) && seq_has_overflowed(m))
77 		pr_warn_once("preallocated size:%zx for %s exceeded\n",
78 			     m->size, __func__);
79 
80 	return intel_guc_log_dump(m->private, &p, true);
81 }
82 DEFINE_INTEL_GT_DEBUGFS_ATTRIBUTE_WITH_SIZE(guc_load_err_log_dump, guc_load_err_dump_size);
83 
guc_log_level_get(void * data,u64 * val)84 static int guc_log_level_get(void *data, u64 *val)
85 {
86 	struct intel_guc_log *log = data;
87 
88 	if (!log->vma)
89 		return -ENODEV;
90 
91 	*val = intel_guc_log_get_level(log);
92 
93 	return 0;
94 }
95 
guc_log_level_set(void * data,u64 val)96 static int guc_log_level_set(void *data, u64 val)
97 {
98 	struct intel_guc_log *log = data;
99 
100 	if (!log->vma)
101 		return -ENODEV;
102 
103 	return intel_guc_log_set_level(log, val);
104 }
105 
106 DEFINE_SIMPLE_ATTRIBUTE(guc_log_level_fops,
107 			guc_log_level_get, guc_log_level_set,
108 			"%lld\n");
109 
guc_log_relay_open(struct inode * inode,struct file * file)110 static int guc_log_relay_open(struct inode *inode, struct file *file)
111 {
112 	struct intel_guc_log *log = inode->i_private;
113 
114 	if (!intel_guc_is_ready(log_to_guc(log)))
115 		return -ENODEV;
116 
117 	file->private_data = log;
118 
119 	return intel_guc_log_relay_open(log);
120 }
121 
122 static ssize_t
guc_log_relay_write(struct file * filp,const char __user * ubuf,size_t cnt,loff_t * ppos)123 guc_log_relay_write(struct file *filp,
124 		    const char __user *ubuf,
125 		    size_t cnt,
126 		    loff_t *ppos)
127 {
128 	struct intel_guc_log *log = filp->private_data;
129 	int val;
130 	int ret;
131 
132 	ret = kstrtoint_from_user(ubuf, cnt, 0, &val);
133 	if (ret < 0)
134 		return ret;
135 
136 	/*
137 	 * Enable and start the guc log relay on value of 1.
138 	 * Flush log relay for any other value.
139 	 */
140 	if (val == 1)
141 		ret = intel_guc_log_relay_start(log);
142 	else
143 		intel_guc_log_relay_flush(log);
144 
145 	return ret ?: cnt;
146 }
147 
guc_log_relay_release(struct inode * inode,struct file * file)148 static int guc_log_relay_release(struct inode *inode, struct file *file)
149 {
150 	struct intel_guc_log *log = inode->i_private;
151 
152 	intel_guc_log_relay_close(log);
153 	return 0;
154 }
155 
156 static const struct file_operations guc_log_relay_fops = {
157 	.owner = THIS_MODULE,
158 	.open = guc_log_relay_open,
159 	.write = guc_log_relay_write,
160 	.release = guc_log_relay_release,
161 };
162 
163 #endif /* notyet */
164 
intel_guc_log_debugfs_register(struct intel_guc_log * log,struct dentry * root)165 void intel_guc_log_debugfs_register(struct intel_guc_log *log,
166 				    struct dentry *root)
167 {
168 	STUB();
169 #ifdef notyet
170 	static const struct intel_gt_debugfs_file files[] = {
171 		{ "guc_log_dump", &guc_log_dump_fops, NULL },
172 		{ "guc_load_err_log_dump", &guc_load_err_log_dump_fops, NULL },
173 		{ "guc_log_level", &guc_log_level_fops, NULL },
174 		{ "guc_log_relay", &guc_log_relay_fops, NULL },
175 	};
176 
177 	if (!intel_guc_is_supported(log_to_guc(log)))
178 		return;
179 
180 	intel_gt_debugfs_register_files(root, files, ARRAY_SIZE(files), log);
181 #endif
182 }
183