blob: 72832776659d479faed3d85a3c047372d0f5e9c7 [file] [log] [blame]
Lloyd Atkinson5d40d312016-09-06 08:34:13 -04001/* Copyright (c) 2016, 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#define pr_fmt(fmt) "sde_evtlog:[%s] " fmt, __func__
14
15#include <linux/delay.h>
16#include <linux/spinlock.h>
17#include <linux/ktime.h>
18#include <linux/debugfs.h>
19#include <linux/uaccess.h>
20#include <linux/dma-buf.h>
21
22#include "sde_dbg.h"
23#include "sde_trace.h"
24
25#ifdef CONFIG_DRM_SDE_EVTLOG_DEBUG
Lloyd Atkinsona54513f2016-10-03 22:31:43 -040026#define SDE_EVTLOG_DEFAULT_ENABLE 1
Lloyd Atkinson5d40d312016-09-06 08:34:13 -040027#else
Lloyd Atkinsona54513f2016-10-03 22:31:43 -040028#define SDE_EVTLOG_DEFAULT_ENABLE 0
Lloyd Atkinson5d40d312016-09-06 08:34:13 -040029#endif
30
Lloyd Atkinsona54513f2016-10-03 22:31:43 -040031#define SDE_DBG_DEFAULT_PANIC 1
Lloyd Atkinson5d40d312016-09-06 08:34:13 -040032
33/*
34 * evtlog will print this number of entries when it is called through
35 * sysfs node or panic. This prevents kernel log from evtlog message
36 * flood.
37 */
38#define SDE_EVTLOG_PRINT_ENTRY 256
39
40/*
41 * evtlog keeps this number of entries in memory for debug purpose. This
42 * number must be greater than print entry to prevent out of bound evtlog
43 * entry array access.
44 */
45#define SDE_EVTLOG_ENTRY (SDE_EVTLOG_PRINT_ENTRY * 4)
46#define SDE_EVTLOG_MAX_DATA 15
47#define SDE_EVTLOG_BUF_MAX 512
48#define SDE_EVTLOG_BUF_ALIGN 32
49
50DEFINE_SPINLOCK(sde_evtloglock);
51
52struct tlog {
53 u32 counter;
54 s64 time;
55 const char *name;
56 int line;
57 u32 data[SDE_EVTLOG_MAX_DATA];
58 u32 data_cnt;
59 int pid;
60};
61
62static struct sde_dbg_evtlog {
63 struct tlog logs[SDE_EVTLOG_ENTRY];
64 u32 first;
65 u32 last;
66 u32 curr;
67 struct dentry *evtlog;
68 u32 evtlog_enable;
69 u32 panic_on_err;
Lloyd Atkinsona54513f2016-10-03 22:31:43 -040070 struct work_struct evtlog_dump_work;
71 bool work_panic;
Lloyd Atkinson5d40d312016-09-06 08:34:13 -040072} sde_dbg_evtlog;
73
74static inline bool sde_evtlog_is_enabled(u32 flag)
75{
76 return (flag & sde_dbg_evtlog.evtlog_enable) ||
77 (flag == SDE_EVTLOG_ALL && sde_dbg_evtlog.evtlog_enable);
78}
79
80void sde_evtlog(const char *name, int line, int flag, ...)
81{
82 unsigned long flags;
83 int i, val = 0;
84 va_list args;
85 struct tlog *log;
86
87 if (!sde_evtlog_is_enabled(flag))
88 return;
89
90 spin_lock_irqsave(&sde_evtloglock, flags);
91 log = &sde_dbg_evtlog.logs[sde_dbg_evtlog.curr];
92 log->time = ktime_to_us(ktime_get());
93 log->name = name;
94 log->line = line;
95 log->data_cnt = 0;
96 log->pid = current->pid;
97
98 va_start(args, flag);
99 for (i = 0; i < SDE_EVTLOG_MAX_DATA; i++) {
100
101 val = va_arg(args, int);
102 if (val == SDE_EVTLOG_DATA_LIMITER)
103 break;
104
105 log->data[i] = val;
106 }
107 va_end(args);
108 log->data_cnt = i;
109 sde_dbg_evtlog.curr = (sde_dbg_evtlog.curr + 1) % SDE_EVTLOG_ENTRY;
110 sde_dbg_evtlog.last++;
111
112 trace_sde_evtlog(name, line, i > 0 ? log->data[0] : 0,
113 i > 1 ? log->data[1] : 0);
114
115 spin_unlock_irqrestore(&sde_evtloglock, flags);
116}
117
118/* always dump the last entries which are not dumped yet */
Lloyd Atkinsona54513f2016-10-03 22:31:43 -0400119static bool _sde_evtlog_dump_calc_range(void)
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400120{
121 static u32 next;
122 bool need_dump = true;
123 unsigned long flags;
124 struct sde_dbg_evtlog *evtlog = &sde_dbg_evtlog;
125
126 spin_lock_irqsave(&sde_evtloglock, flags);
127
128 evtlog->first = next;
129
130 if (evtlog->last == evtlog->first) {
131 need_dump = false;
132 goto dump_exit;
133 }
134
135 if (evtlog->last < evtlog->first) {
136 evtlog->first %= SDE_EVTLOG_ENTRY;
137 if (evtlog->last < evtlog->first)
138 evtlog->last += SDE_EVTLOG_ENTRY;
139 }
140
141 if ((evtlog->last - evtlog->first) > SDE_EVTLOG_PRINT_ENTRY) {
142 pr_warn("evtlog buffer overflow before dump: %d\n",
143 evtlog->last - evtlog->first);
144 evtlog->first = evtlog->last - SDE_EVTLOG_PRINT_ENTRY;
145 }
146 next = evtlog->first + 1;
147
148dump_exit:
149 spin_unlock_irqrestore(&sde_evtloglock, flags);
150
151 return need_dump;
152}
153
154static ssize_t sde_evtlog_dump_entry(char *evtlog_buf, ssize_t evtlog_buf_size)
155{
156 int i;
157 ssize_t off = 0;
158 struct tlog *log, *prev_log;
159 unsigned long flags;
160
161 spin_lock_irqsave(&sde_evtloglock, flags);
162
163 log = &sde_dbg_evtlog.logs[sde_dbg_evtlog.first %
164 SDE_EVTLOG_ENTRY];
165
166 prev_log = &sde_dbg_evtlog.logs[(sde_dbg_evtlog.first - 1) %
167 SDE_EVTLOG_ENTRY];
168
169 off = snprintf((evtlog_buf + off), (evtlog_buf_size - off), "%s:%-4d",
170 log->name, log->line);
171
172 if (off < SDE_EVTLOG_BUF_ALIGN) {
173 memset((evtlog_buf + off), 0x20, (SDE_EVTLOG_BUF_ALIGN - off));
174 off = SDE_EVTLOG_BUF_ALIGN;
175 }
176
177 off += snprintf((evtlog_buf + off), (evtlog_buf_size - off),
178 "=>[%-8d:%-11llu:%9llu][%-4d]:", sde_dbg_evtlog.first,
179 log->time, (log->time - prev_log->time), log->pid);
180
181 for (i = 0; i < log->data_cnt; i++)
182 off += snprintf((evtlog_buf + off), (evtlog_buf_size - off),
183 "%x ", log->data[i]);
184
185 off += snprintf((evtlog_buf + off), (evtlog_buf_size - off), "\n");
186
187 spin_unlock_irqrestore(&sde_evtloglock, flags);
188
189 return off;
190}
191
Lloyd Atkinsona54513f2016-10-03 22:31:43 -0400192static void _sde_evtlog_dump_all(void)
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400193{
194 char evtlog_buf[SDE_EVTLOG_BUF_MAX];
195
Lloyd Atkinsona54513f2016-10-03 22:31:43 -0400196 while (_sde_evtlog_dump_calc_range()) {
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400197 sde_evtlog_dump_entry(evtlog_buf, SDE_EVTLOG_BUF_MAX);
198 pr_info("%s", evtlog_buf);
199 }
200}
201
Lloyd Atkinsona54513f2016-10-03 22:31:43 -0400202static void _sde_dump_array(bool dead, const char *name)
203{
204 _sde_evtlog_dump_all();
205
206 if (dead && sde_dbg_evtlog.panic_on_err)
207 panic(name);
208}
209
210static void _sde_dump_work(struct work_struct *work)
211{
212 _sde_dump_array(sde_dbg_evtlog.work_panic, "evtlog_workitem");
213}
214
215void sde_dbg_dump(bool queue, const char *name, ...)
216{
217 int i;
218 bool dead = false;
219 va_list args;
220 char *blk_name = NULL;
221
222 if (!sde_evtlog_is_enabled(SDE_EVTLOG_DEFAULT))
223 return;
224
225 if (queue && work_pending(&sde_dbg_evtlog.evtlog_dump_work))
226 return;
227
228 va_start(args, name);
229 for (i = 0; i < SDE_EVTLOG_MAX_DATA; i++) {
230 blk_name = va_arg(args, char*);
231 if (IS_ERR_OR_NULL(blk_name))
232 break;
233
234 if (!strcmp(blk_name, "panic"))
235 dead = true;
236 }
237 va_end(args);
238
239 if (queue) {
240 /* schedule work to dump later */
241 sde_dbg_evtlog.work_panic = dead;
242 schedule_work(&sde_dbg_evtlog.evtlog_dump_work);
243 } else {
244 _sde_dump_array(dead, name);
245 }
246}
247
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400248static int sde_evtlog_dump_open(struct inode *inode, struct file *file)
249{
250 /* non-seekable */
251 file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
252 file->private_data = inode->i_private;
253 return 0;
254}
255
256static ssize_t sde_evtlog_dump_read(struct file *file, char __user *buff,
257 size_t count, loff_t *ppos)
258{
259 ssize_t len = 0;
260 char evtlog_buf[SDE_EVTLOG_BUF_MAX];
261
Lloyd Atkinsona54513f2016-10-03 22:31:43 -0400262 if (_sde_evtlog_dump_calc_range()) {
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400263 len = sde_evtlog_dump_entry(evtlog_buf, SDE_EVTLOG_BUF_MAX);
264 if (copy_to_user(buff, evtlog_buf, len))
265 return -EFAULT;
266 *ppos += len;
267 }
268
269 return len;
270}
271
272static ssize_t sde_evtlog_dump_write(struct file *file,
273 const char __user *user_buf, size_t count, loff_t *ppos)
274{
Lloyd Atkinsona54513f2016-10-03 22:31:43 -0400275 _sde_evtlog_dump_all();
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400276
277 if (sde_dbg_evtlog.panic_on_err)
278 panic("sde");
279
280 return count;
281}
282
283static const struct file_operations sde_evtlog_fops = {
284 .open = sde_evtlog_dump_open,
285 .read = sde_evtlog_dump_read,
286 .write = sde_evtlog_dump_write,
287};
288
289int sde_evtlog_init(struct dentry *debugfs_root)
290{
291 int i;
292
293 sde_dbg_evtlog.evtlog = debugfs_create_dir("evt_dbg", debugfs_root);
294 if (IS_ERR_OR_NULL(sde_dbg_evtlog.evtlog)) {
295 pr_err("debugfs_create_dir fail, error %ld\n",
296 PTR_ERR(sde_dbg_evtlog.evtlog));
297 sde_dbg_evtlog.evtlog = NULL;
298 return -ENODEV;
299 }
300
Lloyd Atkinsona54513f2016-10-03 22:31:43 -0400301 INIT_WORK(&sde_dbg_evtlog.evtlog_dump_work, _sde_dump_work);
302 sde_dbg_evtlog.work_panic = false;
303
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400304 for (i = 0; i < SDE_EVTLOG_ENTRY; i++)
305 sde_dbg_evtlog.logs[i].counter = i;
306
307 debugfs_create_file("dump", 0644, sde_dbg_evtlog.evtlog, NULL,
308 &sde_evtlog_fops);
309 debugfs_create_u32("enable", 0644, sde_dbg_evtlog.evtlog,
310 &sde_dbg_evtlog.evtlog_enable);
311 debugfs_create_u32("panic", 0644, sde_dbg_evtlog.evtlog,
312 &sde_dbg_evtlog.panic_on_err);
313
Lloyd Atkinsona54513f2016-10-03 22:31:43 -0400314 sde_dbg_evtlog.evtlog_enable = SDE_EVTLOG_DEFAULT_ENABLE;
315 sde_dbg_evtlog.panic_on_err = SDE_DBG_DEFAULT_PANIC;
Lloyd Atkinson5d40d312016-09-06 08:34:13 -0400316
317 pr_info("evtlog_status: enable:%d, panic:%d\n",
318 sde_dbg_evtlog.evtlog_enable, sde_dbg_evtlog.panic_on_err);
319
320 return 0;
321}
322
323void sde_evtlog_destroy(void)
324{
325 debugfs_remove(sde_dbg_evtlog.evtlog);
326}