blob: b41bd6b4b9e323ea8260052b9fbbf90efa1cf80f [file] [log] [blame]
Duy Truonge833aca2013-02-12 13:35:08 -08001/* Copyright (c) 2002,2008-2012, The Linux Foundation. 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
Tarun Karra45a50d62013-01-28 21:47:37 -080073static int pm_enabled_set(void *data, u64 val)
74{
75 struct kgsl_device *device = data;
76 device->pm_dump_enable = val;
77 return 0;
78}
79
80static int pm_enabled_get(void *data, u64 *val)
81{
82 struct kgsl_device *device = data;
83 *val = device->pm_dump_enable;
84 return 0;
85}
86
Harsh Vardhan Dwivedi715fb832012-05-18 00:24:18 -060087
88DEFINE_SIMPLE_ATTRIBUTE(pm_regs_enabled_fops,
89 pm_regs_enabled_get,
90 pm_regs_enabled_set, "%llu\n");
91
92DEFINE_SIMPLE_ATTRIBUTE(pm_ib_enabled_fops,
93 pm_ib_enabled_get,
94 pm_ib_enabled_set, "%llu\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070095
Tarun Karra45a50d62013-01-28 21:47:37 -080096DEFINE_SIMPLE_ATTRIBUTE(pm_enabled_fops,
97 pm_enabled_get,
98 pm_enabled_set, "%llu\n");
99
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700100static inline int kgsl_log_set(unsigned int *log_val, void *data, u64 val)
101{
102 *log_val = min((unsigned int)val, (unsigned int)KGSL_LOG_LEVEL_MAX);
103 return 0;
104}
105
106#define KGSL_DEBUGFS_LOG(__log) \
107static int __log ## _set(void *data, u64 val) \
108{ \
109 struct kgsl_device *device = data; \
110 return kgsl_log_set(&device->__log, data, val); \
111} \
112static int __log ## _get(void *data, u64 *val) \
113{ \
114 struct kgsl_device *device = data; \
115 *val = device->__log; \
116 return 0; \
117} \
118DEFINE_SIMPLE_ATTRIBUTE(__log ## _fops, \
119__log ## _get, __log ## _set, "%llu\n"); \
120
121KGSL_DEBUGFS_LOG(drv_log);
122KGSL_DEBUGFS_LOG(cmd_log);
123KGSL_DEBUGFS_LOG(ctxt_log);
124KGSL_DEBUGFS_LOG(mem_log);
125KGSL_DEBUGFS_LOG(pwr_log);
Tarun Karrad20d71a2013-01-25 15:38:57 -0800126KGSL_DEBUGFS_LOG(ft_log);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700127
128void kgsl_device_debugfs_init(struct kgsl_device *device)
129{
130 if (kgsl_debugfs_dir && !IS_ERR(kgsl_debugfs_dir))
131 device->d_debugfs = debugfs_create_dir(device->name,
132 kgsl_debugfs_dir);
133
134 if (!device->d_debugfs || IS_ERR(device->d_debugfs))
135 return;
136
137 device->cmd_log = KGSL_LOG_LEVEL_DEFAULT;
138 device->ctxt_log = KGSL_LOG_LEVEL_DEFAULT;
139 device->drv_log = KGSL_LOG_LEVEL_DEFAULT;
140 device->mem_log = KGSL_LOG_LEVEL_DEFAULT;
141 device->pwr_log = KGSL_LOG_LEVEL_DEFAULT;
Tarun Karrad20d71a2013-01-25 15:38:57 -0800142 device->ft_log = KGSL_LOG_LEVEL_DEFAULT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700143
144 debugfs_create_file("log_level_cmd", 0644, device->d_debugfs, device,
145 &cmd_log_fops);
146 debugfs_create_file("log_level_ctxt", 0644, device->d_debugfs, device,
147 &ctxt_log_fops);
148 debugfs_create_file("log_level_drv", 0644, device->d_debugfs, device,
149 &drv_log_fops);
150 debugfs_create_file("log_level_mem", 0644, device->d_debugfs, device,
151 &mem_log_fops);
152 debugfs_create_file("log_level_pwr", 0644, device->d_debugfs, device,
153 &pwr_log_fops);
Tarun Karrad20d71a2013-01-25 15:38:57 -0800154 debugfs_create_file("log_level_ft", 0644, device->d_debugfs, device,
155 &ft_log_fops);
Harsh Vardhan Dwivedi715fb832012-05-18 00:24:18 -0600156
157 /* Create postmortem dump control files */
158
159 pm_d_debugfs = debugfs_create_dir("postmortem", device->d_debugfs);
160
161 if (IS_ERR(pm_d_debugfs))
162 return;
163
164 debugfs_create_file("dump", 0600, pm_d_debugfs, device,
165 &pm_dump_fops);
166 debugfs_create_file("regs_enabled", 0644, pm_d_debugfs, device,
167 &pm_regs_enabled_fops);
168 debugfs_create_file("ib_enabled", 0644, pm_d_debugfs, device,
169 &pm_ib_enabled_fops);
Tarun Karra45a50d62013-01-28 21:47:37 -0800170 device->pm_dump_enable = 0;
171 debugfs_create_file("enable", 0644, pm_d_debugfs, device,
172 &pm_enabled_fops);
Harsh Vardhan Dwivedi715fb832012-05-18 00:24:18 -0600173
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700174}
175
Jeremy Gebbenddf93012012-09-25 10:57:38 -0600176static const char * const memtype_strings[] = {
177 "gpumem",
178 "pmem",
179 "ashmem",
180 "usermap",
181 "ion",
182};
183
184static const char *memtype_str(int memtype)
185{
186 if (memtype < ARRAY_SIZE(memtype_strings))
187 return memtype_strings[memtype];
188 return "unknown";
189}
190
Jordan Crousedc67dfb2012-10-25 09:41:46 -0600191static char get_alignflag(const struct kgsl_memdesc *m)
192{
193 int align = kgsl_memdesc_get_align(m);
194 if (align >= ilog2(SZ_1M))
195 return 'L';
196 else if (align >= ilog2(SZ_64K))
197 return 'l';
198 return '-';
199}
200
Jeremy Gebbenddf93012012-09-25 10:57:38 -0600201static int process_mem_print(struct seq_file *s, void *unused)
202{
203 struct kgsl_mem_entry *entry;
204 struct rb_node *node;
205 struct kgsl_process_private *private = s->private;
Rajeev Kulkarni8dfdc3362012-11-22 00:22:32 -0800206 char flags[4];
Jeremy Gebbenddf93012012-09-25 10:57:38 -0600207 char usage[16];
208
209 spin_lock(&private->mem_lock);
210 seq_printf(s, "%8s %8s %5s %10s %16s %5s\n",
211 "gpuaddr", "size", "flags", "type", "usage", "sglen");
212 for (node = rb_first(&private->mem_rb); node; node = rb_next(node)) {
213 struct kgsl_memdesc *m;
214
215 entry = rb_entry(node, struct kgsl_mem_entry, node);
216 m = &entry->memdesc;
217
Jordan Crousedc67dfb2012-10-25 09:41:46 -0600218 flags[0] = m->priv & KGSL_MEMDESC_GLOBAL ? 'g' : '-';
219 flags[1] = m->flags & KGSL_MEMFLAGS_GPUREADONLY ? 'r' : '-';
220 flags[2] = get_alignflag(m);
Rajeev Kulkarni8dfdc3362012-11-22 00:22:32 -0800221 flags[3] = '\0';
Jeremy Gebbenddf93012012-09-25 10:57:38 -0600222
Jordan Crousedc67dfb2012-10-25 09:41:46 -0600223 kgsl_get_memory_usage(usage, sizeof(usage), m->flags);
Jeremy Gebbenddf93012012-09-25 10:57:38 -0600224
225 seq_printf(s, "%08x %8d %5s %10s %16s %5d\n",
226 m->gpuaddr, m->size, flags,
227 memtype_str(entry->memtype), usage, m->sglen);
228 }
229 spin_unlock(&private->mem_lock);
230 return 0;
231}
232
233static int process_mem_open(struct inode *inode, struct file *file)
234{
235 return single_open(file, process_mem_print, inode->i_private);
236}
237
238static const struct file_operations process_mem_fops = {
239 .open = process_mem_open,
240 .read = seq_read,
241 .llseek = seq_lseek,
242 .release = single_release,
243};
244
245void
246kgsl_process_init_debugfs(struct kgsl_process_private *private)
247{
248 unsigned char name[16];
249
250 snprintf(name, sizeof(name), "%d", private->pid);
251
252 private->debug_root = debugfs_create_dir(name, proc_d_debugfs);
253 debugfs_create_file("mem", 0400, private->debug_root, private,
254 &process_mem_fops);
255}
256
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700257void kgsl_core_debugfs_init(void)
258{
259 kgsl_debugfs_dir = debugfs_create_dir("kgsl", 0);
Jeremy Gebbenddf93012012-09-25 10:57:38 -0600260 proc_d_debugfs = debugfs_create_dir("proc", kgsl_debugfs_dir);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700261}
Jordan Croused8f1c6b2011-10-04 09:31:29 -0600262
263void kgsl_core_debugfs_close(void)
264{
265 debugfs_remove_recursive(kgsl_debugfs_dir);
266}