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