blob: 834706a973d230e8e989acf8f7f6b1eb62431c7b [file] [log] [blame]
Shrenuj Bansala419c792016-10-20 14:05:11 -07001/* Copyright (c) 2002,2008-2017, The Linux Foundation. All rights reserved.
2 *
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.
6 *
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.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/debugfs.h>
16
17#include "kgsl.h"
18#include "kgsl_device.h"
19#include "kgsl_sharedmem.h"
20#include "kgsl_debugfs.h"
21
22/*default log levels is error for everything*/
23#define KGSL_LOG_LEVEL_MAX 7
24
25struct dentry *kgsl_debugfs_dir;
26static struct dentry *proc_d_debugfs;
27
28static inline int kgsl_log_set(unsigned int *log_val, void *data, u64 val)
29{
30 *log_val = min_t(unsigned int, val, KGSL_LOG_LEVEL_MAX);
31 return 0;
32}
33
34#define KGSL_DEBUGFS_LOG(__log) \
35static int __log ## _set(void *data, u64 val) \
36{ \
37 struct kgsl_device *device = data; \
38 return kgsl_log_set(&device->__log, data, val); \
39} \
40static int __log ## _get(void *data, u64 *val) \
41{ \
42 struct kgsl_device *device = data; \
43 *val = device->__log; \
44 return 0; \
45} \
46DEFINE_SIMPLE_ATTRIBUTE(__log ## _fops, \
47__log ## _get, __log ## _set, "%llu\n") \
48
49KGSL_DEBUGFS_LOG(drv_log);
50KGSL_DEBUGFS_LOG(cmd_log);
51KGSL_DEBUGFS_LOG(ctxt_log);
52KGSL_DEBUGFS_LOG(mem_log);
53KGSL_DEBUGFS_LOG(pwr_log);
54
55static int _strict_set(void *data, u64 val)
56{
57 kgsl_sharedmem_set_noretry(val ? true : false);
58 return 0;
59}
60
61static int _strict_get(void *data, u64 *val)
62{
63 *val = kgsl_sharedmem_get_noretry();
64 return 0;
65}
66
67DEFINE_SIMPLE_ATTRIBUTE(_strict_fops, _strict_get, _strict_set, "%llu\n");
68
69void kgsl_device_debugfs_init(struct kgsl_device *device)
70{
71 if (kgsl_debugfs_dir && !IS_ERR(kgsl_debugfs_dir))
72 device->d_debugfs = debugfs_create_dir(device->name,
73 kgsl_debugfs_dir);
74
75 if (!device->d_debugfs || IS_ERR(device->d_debugfs))
76 return;
77
78 debugfs_create_file("log_level_cmd", 0644, device->d_debugfs, device,
79 &cmd_log_fops);
80 debugfs_create_file("log_level_ctxt", 0644, device->d_debugfs, device,
81 &ctxt_log_fops);
82 debugfs_create_file("log_level_drv", 0644, device->d_debugfs, device,
83 &drv_log_fops);
84 debugfs_create_file("log_level_mem", 0644, device->d_debugfs, device,
85 &mem_log_fops);
86 debugfs_create_file("log_level_pwr", 0644, device->d_debugfs, device,
87 &pwr_log_fops);
88}
89
Lynus Vaz519dacfd2017-02-14 12:17:37 +053090void kgsl_device_debugfs_close(struct kgsl_device *device)
91{
92 debugfs_remove_recursive(device->d_debugfs);
93}
94
Shrenuj Bansala419c792016-10-20 14:05:11 -070095struct type_entry {
96 int type;
97 const char *str;
98};
99
100static const struct type_entry memtypes[] = { KGSL_MEM_TYPES };
101
102static const char *memtype_str(int memtype)
103{
104 int i;
105
106 for (i = 0; i < ARRAY_SIZE(memtypes); i++)
107 if (memtypes[i].type == memtype)
108 return memtypes[i].str;
109 return "unknown";
110}
111
112static char get_alignflag(const struct kgsl_memdesc *m)
113{
114 int align = kgsl_memdesc_get_align(m);
115
116 if (align >= ilog2(SZ_1M))
117 return 'L';
118 else if (align >= ilog2(SZ_64K))
119 return 'l';
120 return '-';
121}
122
123static char get_cacheflag(const struct kgsl_memdesc *m)
124{
125 static const char table[] = {
126 [KGSL_CACHEMODE_WRITECOMBINE] = '-',
127 [KGSL_CACHEMODE_UNCACHED] = 'u',
128 [KGSL_CACHEMODE_WRITEBACK] = 'b',
129 [KGSL_CACHEMODE_WRITETHROUGH] = 't',
130 };
131
132 return table[kgsl_memdesc_get_cachemode(m)];
133}
134
135
136static int print_mem_entry(void *data, void *ptr)
137{
138 struct seq_file *s = data;
139 struct kgsl_mem_entry *entry = ptr;
140 char flags[10];
141 char usage[16];
142 struct kgsl_memdesc *m = &entry->memdesc;
143 unsigned int usermem_type = kgsl_memdesc_usermem_type(m);
144 int egl_surface_count = 0, egl_image_count = 0;
145
146 if (m->flags & KGSL_MEMFLAGS_SPARSE_VIRT)
147 return 0;
148
149 flags[0] = kgsl_memdesc_is_global(m) ? 'g' : '-';
150 flags[1] = '-';
151 flags[2] = !(m->flags & KGSL_MEMFLAGS_GPUREADONLY) ? 'w' : '-';
152 flags[3] = get_alignflag(m);
153 flags[4] = get_cacheflag(m);
154 flags[5] = kgsl_memdesc_use_cpu_map(m) ? 'p' : '-';
155 flags[6] = (m->useraddr) ? 'Y' : 'N';
156 flags[7] = kgsl_memdesc_is_secured(m) ? 's' : '-';
157 flags[8] = m->flags & KGSL_MEMFLAGS_SPARSE_PHYS ? 'P' : '-';
158 flags[9] = '\0';
159
160 kgsl_get_memory_usage(usage, sizeof(usage), m->flags);
161
162 if (usermem_type == KGSL_MEM_ENTRY_ION)
163 kgsl_get_egl_counts(entry, &egl_surface_count,
164 &egl_image_count);
165
166 seq_printf(s, "%pK %pK %16llu %5d %9s %10s %16s %5d %16llu %6d %6d",
167 (uint64_t *)(uintptr_t) m->gpuaddr,
168 (unsigned long *) m->useraddr,
169 m->size, entry->id, flags,
170 memtype_str(usermem_type),
171 usage, (m->sgt ? m->sgt->nents : 0), m->mapsize,
172 egl_surface_count, egl_image_count);
173
174 if (entry->metadata[0] != 0)
175 seq_printf(s, " %s", entry->metadata);
176
177 seq_putc(s, '\n');
178
179 return 0;
180}
181
182static struct kgsl_mem_entry *process_mem_seq_find(struct seq_file *s,
183 void *ptr, loff_t pos)
184{
185 struct kgsl_mem_entry *entry = ptr;
186 struct kgsl_process_private *private = s->private;
187 int id = 0;
188
189 loff_t temp_pos = 1;
190
191 if (entry != SEQ_START_TOKEN)
192 id = entry->id + 1;
193
194 spin_lock(&private->mem_lock);
195 for (entry = idr_get_next(&private->mem_idr, &id); entry;
196 id++, entry = idr_get_next(&private->mem_idr, &id),
197 temp_pos++) {
198 if (temp_pos == pos && kgsl_mem_entry_get(entry)) {
199 spin_unlock(&private->mem_lock);
200 goto found;
201 }
202 }
203 spin_unlock(&private->mem_lock);
204
205 entry = NULL;
206found:
207 if (ptr != SEQ_START_TOKEN)
208 kgsl_mem_entry_put(ptr);
209
210 return entry;
211}
212
213static void *process_mem_seq_start(struct seq_file *s, loff_t *pos)
214{
215 loff_t seq_file_offset = *pos;
216
217 if (seq_file_offset == 0)
218 return SEQ_START_TOKEN;
219 else
220 return process_mem_seq_find(s, SEQ_START_TOKEN,
221 seq_file_offset);
222}
223
224static void process_mem_seq_stop(struct seq_file *s, void *ptr)
225{
226 if (ptr && ptr != SEQ_START_TOKEN)
227 kgsl_mem_entry_put(ptr);
228}
229
230static void *process_mem_seq_next(struct seq_file *s, void *ptr,
231 loff_t *pos)
232{
233 ++*pos;
234 return process_mem_seq_find(s, ptr, 1);
235}
236
237static int process_mem_seq_show(struct seq_file *s, void *ptr)
238{
239 if (ptr == SEQ_START_TOKEN) {
240 seq_printf(s, "%16s %16s %16s %5s %9s %10s %16s %5s %16s %6s %6s\n",
241 "gpuaddr", "useraddr", "size", "id", "flags", "type",
242 "usage", "sglen", "mapsize", "eglsrf", "eglimg");
243 return 0;
244 } else
245 return print_mem_entry(s, ptr);
246}
247
248static const struct seq_operations process_mem_seq_fops = {
249 .start = process_mem_seq_start,
250 .stop = process_mem_seq_stop,
251 .next = process_mem_seq_next,
252 .show = process_mem_seq_show,
253};
254
255static int process_mem_open(struct inode *inode, struct file *file)
256{
257 int ret;
258 pid_t pid = (pid_t) (unsigned long) inode->i_private;
259 struct seq_file *s = NULL;
260 struct kgsl_process_private *private = NULL;
261
262 private = kgsl_process_private_find(pid);
263
264 if (!private)
265 return -ENODEV;
266
267 ret = seq_open(file, &process_mem_seq_fops);
268 if (ret)
269 kgsl_process_private_put(private);
270 else {
271 s = file->private_data;
272 s->private = private;
273 }
274
275 return ret;
276}
277
278static int process_mem_release(struct inode *inode, struct file *file)
279{
280 struct kgsl_process_private *private =
281 ((struct seq_file *)file->private_data)->private;
282
283 if (private)
284 kgsl_process_private_put(private);
285
286 return seq_release(inode, file);
287}
288
289static const struct file_operations process_mem_fops = {
290 .open = process_mem_open,
291 .read = seq_read,
292 .llseek = seq_lseek,
293 .release = process_mem_release,
294};
295
296static int print_sparse_mem_entry(int id, void *ptr, void *data)
297{
298 struct seq_file *s = data;
299 struct kgsl_mem_entry *entry = ptr;
300 struct kgsl_memdesc *m = &entry->memdesc;
301 struct rb_node *node;
302
303 if (!(m->flags & KGSL_MEMFLAGS_SPARSE_VIRT))
304 return 0;
305
Lynus Vazdb41c9c2017-10-30 17:50:43 +0530306 spin_lock(&entry->bind_lock);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700307 node = rb_first(&entry->bind_tree);
308
309 while (node != NULL) {
310 struct sparse_bind_object *obj = rb_entry(node,
311 struct sparse_bind_object, node);
312 seq_printf(s, "%5d %16llx %16llx %16llx %16llx\n",
313 entry->id, entry->memdesc.gpuaddr,
314 obj->v_off, obj->size, obj->p_off);
315 node = rb_next(node);
316 }
Lynus Vazdb41c9c2017-10-30 17:50:43 +0530317 spin_unlock(&entry->bind_lock);
Shrenuj Bansala419c792016-10-20 14:05:11 -0700318
319 seq_putc(s, '\n');
320
321 return 0;
322}
323
324static int process_sparse_mem_print(struct seq_file *s, void *unused)
325{
326 struct kgsl_process_private *private = s->private;
327
328 seq_printf(s, "%5s %16s %16s %16s %16s\n",
329 "v_id", "gpuaddr", "v_offset", "v_size", "p_offset");
330
331 spin_lock(&private->mem_lock);
332 idr_for_each(&private->mem_idr, print_sparse_mem_entry, s);
333 spin_unlock(&private->mem_lock);
334
335 return 0;
336}
337
338static int process_sparse_mem_open(struct inode *inode, struct file *file)
339{
340 int ret;
341 pid_t pid = (pid_t) (unsigned long) inode->i_private;
342 struct kgsl_process_private *private = NULL;
343
344 private = kgsl_process_private_find(pid);
345
346 if (!private)
347 return -ENODEV;
348
349 ret = single_open(file, process_sparse_mem_print, private);
350 if (ret)
351 kgsl_process_private_put(private);
352
353 return ret;
354}
355
356static const struct file_operations process_sparse_mem_fops = {
357 .open = process_sparse_mem_open,
358 .read = seq_read,
359 .llseek = seq_lseek,
360 .release = process_mem_release,
361};
362
363static int globals_print(struct seq_file *s, void *unused)
364{
365 kgsl_print_global_pt_entries(s);
366 return 0;
367}
368
369static int globals_open(struct inode *inode, struct file *file)
370{
371 return single_open(file, globals_print, NULL);
372}
373
374static int globals_release(struct inode *inode, struct file *file)
375{
376 return single_release(inode, file);
377}
378
379static const struct file_operations global_fops = {
380 .open = globals_open,
381 .read = seq_read,
382 .llseek = seq_lseek,
383 .release = globals_release,
384};
385
386/**
387 * kgsl_process_init_debugfs() - Initialize debugfs for a process
388 * @private: Pointer to process private structure created for the process
389 *
390 * kgsl_process_init_debugfs() is called at the time of creating the
391 * process struct when a process opens kgsl device for the first time.
392 * This function is not fatal - all we do is print a warning message if
393 * the files can't be created
394 */
395void kgsl_process_init_debugfs(struct kgsl_process_private *private)
396{
397 unsigned char name[16];
398 struct dentry *dentry;
399
400 snprintf(name, sizeof(name), "%d", private->pid);
401
402 private->debug_root = debugfs_create_dir(name, proc_d_debugfs);
403
404 /*
405 * Both debugfs_create_dir() and debugfs_create_file() return
406 * ERR_PTR(-ENODEV) if debugfs is disabled in the kernel but return
407 * NULL on error when it is enabled. For both usages we need to check
408 * for ERROR or NULL and only print a warning on an actual failure
409 * (i.e. - when the return value is NULL)
410 */
411
412 if (IS_ERR_OR_NULL(private->debug_root)) {
413 WARN((private->debug_root == NULL),
414 "Unable to create debugfs dir for %s\n", name);
415 private->debug_root = NULL;
416 return;
417 }
418
419 dentry = debugfs_create_file("mem", 0444, private->debug_root,
420 (void *) ((unsigned long) private->pid), &process_mem_fops);
421
422 if (IS_ERR_OR_NULL(dentry))
423 WARN((dentry == NULL),
424 "Unable to create 'mem' file for %s\n", name);
425
426 dentry = debugfs_create_file("sparse_mem", 0444, private->debug_root,
427 (void *) ((unsigned long) private->pid),
428 &process_sparse_mem_fops);
429
430 if (IS_ERR_OR_NULL(dentry))
431 WARN((dentry == NULL),
432 "Unable to create 'sparse_mem' file for %s\n", name);
433
434}
435
436void kgsl_core_debugfs_init(void)
437{
438 struct dentry *debug_dir;
439
440 kgsl_debugfs_dir = debugfs_create_dir("kgsl", NULL);
441
442 debugfs_create_file("globals", 0444, kgsl_debugfs_dir, NULL,
443 &global_fops);
444
445 debug_dir = debugfs_create_dir("debug", kgsl_debugfs_dir);
446
447 debugfs_create_file("strict_memory", 0644, debug_dir, NULL,
448 &_strict_fops);
449
450 proc_d_debugfs = debugfs_create_dir("proc", kgsl_debugfs_dir);
451}
452
453void kgsl_core_debugfs_close(void)
454{
455 debugfs_remove_recursive(kgsl_debugfs_dir);
456}