blob: 40ed7cab874f28d3baa84148df9f0362ab01f326 [file] [log] [blame]
Harsh Vardhan Dwivedi715fb832012-05-18 00:24:18 -06001/* Copyright (c) 2002,2008-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
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
Steve Mucklef132c6c2012-06-06 18:30:57 -070014#include <linux/module.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070015#include <linux/debugfs.h>
16
17#include "kgsl.h"
18#include "kgsl_device.h"
Jeremy Gebbenddf93012012-09-25 10:57:38 -060019#include "kgsl_sharedmem.h"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070020
21/*default log levels is error for everything*/
22#define KGSL_LOG_LEVEL_DEFAULT 3
23#define KGSL_LOG_LEVEL_MAX 7
24
25struct dentry *kgsl_debugfs_dir;
Harsh Vardhan Dwivedi715fb832012-05-18 00:24:18 -060026static struct dentry *pm_d_debugfs;
Jeremy Gebbenddf93012012-09-25 10:57:38 -060027struct dentry *proc_d_debugfs;
Harsh Vardhan Dwivedi715fb832012-05-18 00:24:18 -060028
29static int pm_dump_set(void *data, u64 val)
30{
31 struct kgsl_device *device = data;
32
33 if (val) {
34 mutex_lock(&device->mutex);
35 kgsl_postmortem_dump(device, 1);
36 mutex_unlock(&device->mutex);
37 }
38
39 return 0;
40}
41DEFINE_SIMPLE_ATTRIBUTE(pm_dump_fops,
42 NULL,
43 pm_dump_set, "%llu\n");
44
45static int pm_regs_enabled_set(void *data, u64 val)
46{
47 struct kgsl_device *device = data;
48 device->pm_regs_enabled = val ? 1 : 0;
49 return 0;
50}
51
52static int pm_regs_enabled_get(void *data, u64 *val)
53{
54 struct kgsl_device *device = data;
55 *val = device->pm_regs_enabled;
56 return 0;
57}
58
59static int pm_ib_enabled_set(void *data, u64 val)
60{
61 struct kgsl_device *device = data;
62 device->pm_ib_enabled = val ? 1 : 0;
63 return 0;
64}
65
66static int pm_ib_enabled_get(void *data, u64 *val)
67{
68 struct kgsl_device *device = data;
69 *val = device->pm_ib_enabled;
70 return 0;
71}
72
73
74DEFINE_SIMPLE_ATTRIBUTE(pm_regs_enabled_fops,
75 pm_regs_enabled_get,
76 pm_regs_enabled_set, "%llu\n");
77
78DEFINE_SIMPLE_ATTRIBUTE(pm_ib_enabled_fops,
79 pm_ib_enabled_get,
80 pm_ib_enabled_set, "%llu\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070081
82static inline int kgsl_log_set(unsigned int *log_val, void *data, u64 val)
83{
84 *log_val = min((unsigned int)val, (unsigned int)KGSL_LOG_LEVEL_MAX);
85 return 0;
86}
87
88#define KGSL_DEBUGFS_LOG(__log) \
89static int __log ## _set(void *data, u64 val) \
90{ \
91 struct kgsl_device *device = data; \
92 return kgsl_log_set(&device->__log, data, val); \
93} \
94static int __log ## _get(void *data, u64 *val) \
95{ \
96 struct kgsl_device *device = data; \
97 *val = device->__log; \
98 return 0; \
99} \
100DEFINE_SIMPLE_ATTRIBUTE(__log ## _fops, \
101__log ## _get, __log ## _set, "%llu\n"); \
102
103KGSL_DEBUGFS_LOG(drv_log);
104KGSL_DEBUGFS_LOG(cmd_log);
105KGSL_DEBUGFS_LOG(ctxt_log);
106KGSL_DEBUGFS_LOG(mem_log);
107KGSL_DEBUGFS_LOG(pwr_log);
108
109void kgsl_device_debugfs_init(struct kgsl_device *device)
110{
111 if (kgsl_debugfs_dir && !IS_ERR(kgsl_debugfs_dir))
112 device->d_debugfs = debugfs_create_dir(device->name,
113 kgsl_debugfs_dir);
114
115 if (!device->d_debugfs || IS_ERR(device->d_debugfs))
116 return;
117
118 device->cmd_log = KGSL_LOG_LEVEL_DEFAULT;
119 device->ctxt_log = KGSL_LOG_LEVEL_DEFAULT;
120 device->drv_log = KGSL_LOG_LEVEL_DEFAULT;
121 device->mem_log = KGSL_LOG_LEVEL_DEFAULT;
122 device->pwr_log = KGSL_LOG_LEVEL_DEFAULT;
123
124 debugfs_create_file("log_level_cmd", 0644, device->d_debugfs, device,
125 &cmd_log_fops);
126 debugfs_create_file("log_level_ctxt", 0644, device->d_debugfs, device,
127 &ctxt_log_fops);
128 debugfs_create_file("log_level_drv", 0644, device->d_debugfs, device,
129 &drv_log_fops);
130 debugfs_create_file("log_level_mem", 0644, device->d_debugfs, device,
131 &mem_log_fops);
132 debugfs_create_file("log_level_pwr", 0644, device->d_debugfs, device,
133 &pwr_log_fops);
Harsh Vardhan Dwivedi715fb832012-05-18 00:24:18 -0600134
135 /* Create postmortem dump control files */
136
137 pm_d_debugfs = debugfs_create_dir("postmortem", device->d_debugfs);
138
139 if (IS_ERR(pm_d_debugfs))
140 return;
141
142 debugfs_create_file("dump", 0600, pm_d_debugfs, device,
143 &pm_dump_fops);
144 debugfs_create_file("regs_enabled", 0644, pm_d_debugfs, device,
145 &pm_regs_enabled_fops);
146 debugfs_create_file("ib_enabled", 0644, pm_d_debugfs, device,
147 &pm_ib_enabled_fops);
148
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700149}
150
Jeremy Gebbenddf93012012-09-25 10:57:38 -0600151static const char * const memtype_strings[] = {
152 "gpumem",
153 "pmem",
154 "ashmem",
155 "usermap",
156 "ion",
157};
158
159static const char *memtype_str(int memtype)
160{
161 if (memtype < ARRAY_SIZE(memtype_strings))
162 return memtype_strings[memtype];
163 return "unknown";
164}
165
166static int process_mem_print(struct seq_file *s, void *unused)
167{
168 struct kgsl_mem_entry *entry;
169 struct rb_node *node;
170 struct kgsl_process_private *private = s->private;
171 char flags[3];
172 char usage[16];
173
174 spin_lock(&private->mem_lock);
175 seq_printf(s, "%8s %8s %5s %10s %16s %5s\n",
176 "gpuaddr", "size", "flags", "type", "usage", "sglen");
177 for (node = rb_first(&private->mem_rb); node; node = rb_next(node)) {
178 struct kgsl_memdesc *m;
179
180 entry = rb_entry(node, struct kgsl_mem_entry, node);
181 m = &entry->memdesc;
182
183 flags[0] = m->priv & KGSL_MEMFLAGS_GLOBAL ? 'g' : '-';
184 flags[1] = m->priv & KGSL_MEMFLAGS_GPUREADONLY ? 'r' : '-';
185 flags[2] = '\0';
186
187 kgsl_get_memory_usage(usage, sizeof(usage), m->priv);
188
189 seq_printf(s, "%08x %8d %5s %10s %16s %5d\n",
190 m->gpuaddr, m->size, flags,
191 memtype_str(entry->memtype), usage, m->sglen);
192 }
193 spin_unlock(&private->mem_lock);
194 return 0;
195}
196
197static int process_mem_open(struct inode *inode, struct file *file)
198{
199 return single_open(file, process_mem_print, inode->i_private);
200}
201
202static const struct file_operations process_mem_fops = {
203 .open = process_mem_open,
204 .read = seq_read,
205 .llseek = seq_lseek,
206 .release = single_release,
207};
208
209void
210kgsl_process_init_debugfs(struct kgsl_process_private *private)
211{
212 unsigned char name[16];
213
214 snprintf(name, sizeof(name), "%d", private->pid);
215
216 private->debug_root = debugfs_create_dir(name, proc_d_debugfs);
217 debugfs_create_file("mem", 0400, private->debug_root, private,
218 &process_mem_fops);
219}
220
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700221void kgsl_core_debugfs_init(void)
222{
223 kgsl_debugfs_dir = debugfs_create_dir("kgsl", 0);
Jeremy Gebbenddf93012012-09-25 10:57:38 -0600224 proc_d_debugfs = debugfs_create_dir("proc", kgsl_debugfs_dir);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700225}
Jordan Croused8f1c6b2011-10-04 09:31:29 -0600226
227void kgsl_core_debugfs_close(void)
228{
229 debugfs_remove_recursive(kgsl_debugfs_dir);
230}